Receive both time and frequency domain frames parallely Topic is solved

If you have a simple question and just want an answer.
Post Reply
shaileshwankhede
Experienced Member
Posts: 65
Joined: Fri Dec 02, 2016 1:30 pm

Receive both time and frequency domain frames parallely

Post by shaileshwankhede »

Hi,

I have xCORE Array Microphone kit and referring to 'app_usb_aud_mic_array' source. It works perfect. For some sound localization task I want to perform cross correlation between different mic channels. Default functionality of USB audio in and out also should work with this. For this I tried below two things:
  1. Replace mic_array_init_time_domain_frame, mic_array_get_next_time_domain_frame, mic_array_frame_time_domain from pcm_pdm_mic.xc of module usb audio; with respective frequency domain functions. But through user_pdm_process() function I am not able to convert frequency bins to time domain frames to output them on output audio channel. I couldn't see required library function for FFT frames to time domain to achieve default behaviour
  1. By keeping time domain code as it is I tried to add parallel tasks to get and process frequency domain frames like this:

    Code: Select all

    par
        {
            mic_array_pdm_rx(p_pdm_mics, c_4x_pdm_mic_0, c_4x_pdm_mic_1);
            mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_0, c_ds_output[0], MIC_ARRAY_NO_INTERNAL_CHANS);
            mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_1, c_ds_output[1], MIC_ARRAY_NO_INTERNAL_CHANS);
            pdm_process(c_ds_output, c_pcm_out);
            pdm_process_fft(c_ds_output, c_pcm_out);
        }
    But I get compilation errors like 'c_ds_output' used in more than two parallel statements. If I try to solve it with some workaround I get stuck in another errors. I am not getting how to execute these parallel
Please suggest how to achieve this or some other effective solution for calculating cross correlations between all adjacent mic signals without affecting existing functionality.

Thanks,
Shailesh


View Solution
User avatar
larry
Respected Member
Posts: 275
Joined: Fri Mar 12, 2010 6:03 pm

Post by larry »

One way of reading the same time domain frame in another task would be to pass the task an unsafe pointer to the frame. I would modify pcm_pdm_mic.xc like this:

Code: Select all

@@ -32,7 +32,7 @@ int data_1[4*THIRD_STAGE_COEFS_PER_STAGE * MAX_DECIMATION_FACTOR] = {0};
 
 mic_array_frame_time_domain mic_audio[2];
 
-void pdm_process(streaming chanend c_ds_output[2], chanend c_audio)
+void pdm_process(streaming chanend c_ds_output[2], chanend c_audio, chanend c)
 {
     unsigned buffer = 1;     // Buffer index
     int output[NUM_PDM_MICS];
@@ -61,6 +61,8 @@ void pdm_process(streaming chanend c_ds_output[2], chanend c_audio)
         {
             mic_array_frame_time_domain * unsafe current = mic_array_get_next_time_domain_frame(c_ds_output, 2, buffer, mic_audio, dc);
 
+            c <: current;
+
             unsafe
             {
                 int req;
@@ -89,10 +91,21 @@ void pdm_process(streaming chanend c_ds_output[2], chanend c_audio)
 #error MAX_FREQ > 48000 NOT CURRENTLY SUPPORTED
 #endif
 
+void pdm_process_fft(chanend c)
+{
+    mic_array_frame_time_domain * unsafe f;
+    while (1) {
+        unsafe {
+            c :> f;
+        }
+    }
+}
+
 void pcm_pdm_mic(chanend c_pcm_out)
 {
     streaming chan c_4x_pdm_mic_0, c_4x_pdm_mic_1;
     streaming chan c_ds_output[2];
+    chan c;
 
     /* Note, this divide should be based on master clock freq */
     configure_clock_src_divide(pdmclk, p_mclk, 2);
@@ -105,7 +118,8 @@ void pcm_pdm_mic(chanend c_pcm_out)
         mic_array_pdm_rx(p_pdm_mics, c_4x_pdm_mic_0, c_4x_pdm_mic_1);
         mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_0, c_ds_output[0]);
         mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_1, c_ds_output[1]);
-        pdm_process(c_ds_output, c_pcm_out);
+        pdm_process(c_ds_output, c_pcm_out, c);
+        pdm_process_fft(c);
     }
 }
shaileshwankhede
Experienced Member
Posts: 65
Joined: Fri Dec 02, 2016 1:30 pm

Post by shaileshwankhede »

Excellent! Now I got idea about channels. I can perform some algorithm on time frames in separate task now. But my real need was getting frequency frames in separate thread. If I try to use same streaming channel used for time domain frames and call mic_array_get_next_frequency_domain_frame, then nothing works. I guess we even cannot pass streaming chan over streaming chanend. I am getting error message
error: cannot output resource
.
Sorry it might be something silly but I am new to xmos programming. How can I create additional parallel task to get frequency frames?
Again I am attaching my modified source for reference.

Thanks,
Shailesh
Attachments
pcm_pdm_mic.xc
(4.43 KiB) Downloaded 214 times
pcm_pdm_mic.xc
(4.43 KiB) Downloaded 214 times
User avatar
larry
Respected Member
Posts: 275
Joined: Fri Mar 12, 2010 6:03 pm

Post by larry »

I don't think it's possible to output time domain and frequency domain at the same time from lib_mic_array. You'll need an additional FFT/inverse step. The mic_array_frame_fft_preprocessed mode is probably best for this.
shaileshwankhede
Experienced Member
Posts: 65
Joined: Fri Dec 02, 2016 1:30 pm

Post by shaileshwankhede »

Ohh. I hope it shouldn't cause much overhead.
Thanks for info.
shaileshwankhede
Experienced Member
Posts: 65
Joined: Fri Dec 02, 2016 1:30 pm

Post by shaileshwankhede »

Hi Larry,

Code: Select all

par
    {
        mic_array_pdm_rx(p_pdm_mics, c_4x_pdm_mic_0, c_4x_pdm_mic_1);
        mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_0, c_ds_output[0]);
        mic_array_decimate_to_pcm_4ch(c_4x_pdm_mic_1, c_ds_output[1]);
        pdm_process(c_ds_output, c_pcm_out, c);
        pdm_process_timeFrames(c);
    }
One clarification over here. I believe parallel task pdm_process_timeFrames(c) should run independently and should not affect c_pcm_out in task pdm_process(c_ds_output, c_pcm_out, c). My pdm_process_timeFrames() has some buffering of data and blocking call to vector power and some other calculations. I think even if it is blocking it should not affect other task. When I try to record any audio, it is broken and not recorded smoothly.

Correct me if I am wrong. How can I add parallel task without affecting original task.

Thanks,
Shailesh
User avatar
larry
Respected Member
Posts: 275
Joined: Fri Mar 12, 2010 6:03 pm

Post by larry »

Your code in pdm_process_timeFrames needs to be ready to input from channel c every 20.83us (or 62.5us if your system is running at 16kHz rather than 48kHz), otherwise c will block in pdm_process

If you are not sure, one way to time inside pdm_process_timeFrames is using a timer:

Code: Select all

timer t;
int start, end;
t :> start;
. . .
t :> end;
if (end - start > 2083)
        printstr("!");
Post Reply