refactored sample rate conversion code to clean up sound card 1 call back, works OK
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 3 Nov 2012 21:30:41 +0000 (21:30 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Sat, 3 Nov 2012 21:30:41 +0000 (21:30 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@924 01035d8c-6547-0410-b346-abe4f91aad63

fdmdv2/src/fdmdv2_main.cpp
fdmdv2/src/fdmdv2_main.h

index d8fcefe59075f9f302abff340ac2b06ba0730c0a..9c6b3117c2f32011d68292a5ccf37d273913c47d 100644 (file)
@@ -46,8 +46,8 @@ int g_soundCard1InDeviceNum = 0;
 int g_soundCard1OutDeviceNum = 0;
 int g_soundCard1SampleRate = 48000;
 
-int g_soundCard2InDeviceNum = 2;
-int g_soundCard2OutDeviceNum = 2;
+int g_soundCard2InDeviceNum = 1;
+int g_soundCard2OutDeviceNum = 1;
 int g_soundCard2SampleRate = 44100;
 
 int cb_cnt, cb1, cb2;
@@ -1241,6 +1241,7 @@ void MainFrame::averageData(float mag_dB[])
     }
 }
 
+#ifdef OLD
 inline void short_to_float(float out_float[], short in_short[], int n) {
     int i;
     for(i=0; i<n; i++)
@@ -1252,6 +1253,44 @@ inline void float_to_short(short out_short[], float in_float[], int n) {
     for(i=0; i<n; i++)
        out_short[i] = (short)in_float[i];
 }
+#endif
+
+// returns number of output samples generated by resampling
+
+static int resample(SRC_STATE *src,
+                       short      output_short[],     
+                       short      input_short[],      
+                       int        output_sample_rate, 
+                       int        input_sample_rate,
+                       int        length_output_short, // maximum output array length in samples
+                       int        length_input_short
+                       )
+{
+    SRC_DATA src_data;
+    float    input[N48*2];
+    float    output[N48*2];
+
+    assert(src != NULL);
+    assert(length_input_short <= N48*2);
+    assert(length_output_short <= N48*2);
+
+    src_short_to_float_array(input_short, input, length_input_short);
+
+    src_data.data_in = input;
+    src_data.data_out = output;
+    src_data.input_frames = length_input_short;
+    src_data.output_frames = length_output_short;
+    src_data.end_of_input = 0;
+    src_data.src_ratio = (float)output_sample_rate/input_sample_rate;
+
+    src_process(src, &src_data);
+
+    assert(src_data.output_frames_gen <= length_output_short);
+    src_float_to_short_array(output, output_short, src_data.output_frames_gen);
+
+    return src_data.output_frames_gen;
+}
+
 
 //-------------------------------------------------------------------------
 // rxCallback()
@@ -1286,48 +1325,36 @@ int MainFrame::rxCallback(
 
     // temp buffers re-used by tx and rx processing
 
-    short           in8k_short[N8];
-    float           in8k[2*N8];
-    float           out8k[2*N8];
+    short           in8k_short[2*N8];
+    short           in48k_short[2*N48];
     short           out8k_short[2*N8];
-    float           out48k[2*N48];
     short           out48k_short[2*N48];
-    short           in48k_short[2*N48];
-    float           in48k[2*N48];
     short           indata[MAX_FPB];
     short           outdata[MAX_FPB];
-    SRC_DATA        src_data;
+    int             nout;
 
     int             ret;
     unsigned int    i;
-
+    
     (void) timeInfo;
     (void) statusFlags;
 
     //printf("%d cb1 .. %d", cb1++, cb1-cb2);
     assert(inputBuffer != NULL);
     assert(outputBuffer != NULL);
+
     /*
        framesPerBuffer is portaudio-speak for number of samples we
        actually get from the record side and need to provide to the
        play side. On Linux (at least) it was found that
        framesPerBuffer may not always be what we ask for in the
        framesPerBuffer field of Pa_OpenStream.  For example a request
-       for 960 sample buffers lead to framesPerBuffer = 1024.
-
-       To perform the 48 to 8 kHz conversion we need an integer
-       multiple of FDMDV_OS samples.  As we can't guarantee the size
-       of framesPerBuffer we do a little FIFO buffering to interface
-       the different input and output number of sample requirements.
+       for 960 sample buffers may lead to framesPerBuffer = 1024 in
+       this call back.
 
-       We also use FIFOs at the input and output of the rx and tx
-       processing to interface between different buffer sizes.  For
-       example the number of samples rqd for the demod is time
-       varying. 
-
-       It does result in a bunch of code that's a hard to
-       understand. So I can't help think there is a better way to do this
-       ....
+       So we use a bunch of FIFOs to interface between different
+       buffer sizes required at each processing step, and to
+       communicate between the call backs for the two sound cards.
     */
     
     //
@@ -1341,77 +1368,38 @@ int MainFrame::rxCallback(
     {
         indata[i] = *rptr;
     }
-    ret = fifo_write(cbData->infifo1, indata, framesPerBuffer);
-    assert(ret != -1);
+    fifo_write(cbData->infifo1, indata, framesPerBuffer);
     
     // while we have enough input samples available ...
 
     while (fifo_read(cbData->infifo1, in48k_short, N48) == 0)
     {
-       // note: modifying fdmdv_48_to_8() to have short arrays rather
-        //       than floats would remove all these float to short
-        //       conversions
-
-#ifdef OLD
-       short_to_float(&in48k1[FDMDV_OS_TAPS], in48k_short, N48);
-        fdmdv_48_to_8(out8k, &in48k1[FDMDV_OS_TAPS], N8);
-       float_to_short(out8k_short, out8k, N8);
-#endif
-
-       src_short_to_float_array(in48k_short, in48k, N48);
-
-       src_data.data_in = in48k;
-       src_data.data_out = out8k;
-       src_data.input_frames = N48;
-       src_data.output_frames = N8;
-       src_data.end_of_input = 0;
-       src_data.src_ratio = (float)FS/g_soundCard1SampleRate;
-
-       src_process(cbData->insrc1, &src_data);
-       assert(src_data.output_frames_gen <= N8);
-
-       src_float_to_short_array(out8k, out8k_short, src_data.output_frames_gen);
-
-       fifo_write(cbData->rxinfifo, out8k_short, src_data.output_frames_gen);
+       int n8k;
+       
+       n8k = resample(cbData->insrc1, in8k_short, in48k_short, FS, g_soundCard1SampleRate, N8, N48);
+       fifo_write(cbData->rxinfifo, in8k_short, n8k);
 
         per_frame_rx_processing(cbData->rxoutfifo, g_CodecBits, cbData->rxinfifo, &g_nRxIn, &g_State, g_pCodec2);
 
-       // if demod out of sync echo audio at input to demod to
-       // headset aid in tuning (ie we hear SSB radio output)
+       // if demod out of sync just pass thru audio so we can hear
+       // SSB radio ouput as an aid to tuning
 
        if (g_State == 0)
-           memcpy(in8k, out8k, sizeof(float)*N8);
+           memcpy(out8k_short, in8k_short, sizeof(short)*n8k);
        else {
-           memset(in8k_short, 0, sizeof(short)*N8);
-           fifo_read(cbData->rxoutfifo, in8k_short, N8);           
-           src_short_to_float_array(in8k_short, in8k, N8);
-           //short_to_float(&in8k1[MEM8], in8k_short, N8);
+           memset(out8k_short, 0, sizeof(short)*N8);
+           fifo_read(cbData->rxoutfifo, out8k_short, N8);          
        }
 
-       //fdmdv_8_to_48(out48k, &in8k1[MEM8], N8);
-       //float_to_short(out48k_short, out48k, N48);
-       src_data.data_in = in8k;
-       src_data.data_out = out48k;
-       src_data.input_frames = N8;
-       src_data.output_frames = N48;
-       src_data.end_of_input = 0;
-
        if (g_nSoundCards == 1) {
-           src_data.src_ratio = (float)g_soundCard1SampleRate/FS;
-           src_process(cbData->outsrc2, &src_data);    
-           //printf("src_data.output_frames_gen: %d\n", src_data.output_frames_gen);
-           src_float_to_short_array(out48k, out48k_short, src_data.output_frames_gen);
-           fifo_write(cbData->outfifo1, out48k_short, src_data.output_frames_gen);
+           nout = resample(cbData->outsrc2, out48k_short, out8k_short, g_soundCard1SampleRate, FS, N48, N8);
+           fifo_write(cbData->outfifo1, out48k_short, nout);
        }
        else {
-           src_data.src_ratio = (float)g_soundCard2SampleRate/FS;
-           src_process(cbData->outsrc2, &src_data);
-           src_float_to_short_array(out48k, out48k_short, src_data.output_frames_gen);
-           fifo_write(cbData->outfifo2, out48k_short, src_data.output_frames_gen);
-           //printf("after outfifo2 write %d fifo_n: %d\n", src_data.output_frames_gen, fifo_n(cbData->outfifo2));
+           nout = resample(cbData->outsrc2, out48k_short, out8k_short, g_soundCard2SampleRate, FS, N48, N8);
+           fifo_write(cbData->outfifo2, out48k_short, nout);
        }
 
-       assert(src_data.output_frames_gen <= N48);
     }
 
     //
@@ -1431,12 +1419,10 @@ int MainFrame::rxCallback(
        // 48kHz, so this loop will run 0 or 1 times.
 
        while((unsigned)fifo_n(cbData->outfifo1) < framesPerBuffer) {
-           short tx_speech_in[2*N8];
-           short tx_mod_out[2*N8];
 
            // number of microphone samples we need at g_soundcards2SampleRate
 
-           int   nsam = g_soundCard2SampleRate * (float)codec2_samples_per_frame(g_pCodec2)/FS;
+           int nsam = g_soundCard2SampleRate * (float)codec2_samples_per_frame(g_pCodec2)/FS;
            assert(nsam <= 2*N48);
 
            // infifo2 is written to by another sound card so it may
@@ -1444,7 +1430,6 @@ int MainFrame::rxCallback(
            // just result in a short interruption in audio being fed
            // to codec2_enc, possibly making a click every now and
            // again in the decoded audio at the other end.
-
  
            // zero speech input just in case infifo2 underflows
 
@@ -1452,61 +1437,25 @@ int MainFrame::rxCallback(
 
            fifo_read(cbData->infifo2, in48k_short, nsam);
 
-           //if (mute_mic)
-           //  memset(in48k_short, 0, sizeof(short)*nsam); 
-
-           src_short_to_float_array(in48k_short, in48k, nsam);
-
-           src_data.data_in = in48k;
-           src_data.data_out = out8k;
-           src_data.input_frames = nsam;
-           src_data.output_frames = codec2_samples_per_frame(g_pCodec2);
-           src_data.end_of_input = 0;
-           src_data.src_ratio = (float)FS/g_soundCard2SampleRate;
-
-           src_process(cbData->insrc2, &src_data);
-           assert(src_data.output_frames_gen <= codec2_samples_per_frame(g_pCodec2));
-
-           src_float_to_short_array(out8k, tx_speech_in, src_data.output_frames_gen);
+           nout = resample(cbData->insrc2, in8k_short, in48k_short, FS, g_soundCard2SampleRate, 2*N8, nsam);
 
            if (write_file) {
-               fwrite(tx_speech_in, sizeof(short), 2*N8, g_write_file);
+               fwrite( in8k_short, sizeof(short), nout, g_write_file);
            }
 
            if (read_file) {
-               int n = fread( tx_speech_in, sizeof(short), 2*N8, g_file);
+               int n = fread( in8k_short , sizeof(short), 2*N8, g_file);
                if (n != 2*N8) {
-                   //printf("rewind\n");
                    rewind(g_file);
                }
            }
            
-           assert(codec2_samples_per_frame(g_pCodec2) == (2*N8));
-
-           per_frame_tx_processing(tx_mod_out, tx_speech_in, g_pCodec2);
+           per_frame_tx_processing(out8k_short, in8k_short, g_pCodec2);
            
            // output 40ms of modem tone
-#ifdef OLD
-
-           short_to_float(&in8k2[MEM8], tx_mod_out, 2*N8);
-           fdmdv_8_to_48(out48k, &in8k2[MEM8], 2*N8);
-           float_to_short(out48k_short, out48k, 2*N48);            
-#endif
-           src_short_to_float_array(tx_mod_out, in8k, 2*N8);
-
-           src_data.data_in = in8k;
-           src_data.data_out = out48k;
-           src_data.input_frames = 2*N8;
-           src_data.output_frames = 2*N48;
-           src_data.end_of_input = 0;
-           src_data.src_ratio = (float)g_soundCard1SampleRate/FS;
-
-           src_process(cbData->outsrc1, &src_data);
-           assert(src_data.output_frames_gen <= 2*N48);
-
-           src_float_to_short_array(out48k, out48k_short, src_data.output_frames_gen);
 
-           fifo_write(cbData->outfifo1, out48k_short, src_data.output_frames_gen );
+           nout = resample(cbData->outsrc1, out48k_short, out8k_short, g_soundCard1SampleRate, FS, 2*N48, 2*N8);
+           fifo_write(cbData->outfifo1, out48k_short, nout);
        }
     }
 
index 6f32a105543ce60f0134f796cbe9b2db80056ba0..80775beb27347df7b32cedc1293859b44452a71c 100644 (file)
@@ -132,13 +132,7 @@ typedef struct
     PlotSpectrum    *pSPPanel;
     PlotWaterfall   *pWFPanel;
 
-    // state variables (filter memories) for sample rate conversion
-    // 1 & 2 denote which sound card's audio they handle
-
-    float           in48k1[FDMDV_OS_TAPS + N48];
-    float           in8k2[MEM8 + 2*N8];
-
-    // libresample states
+    // libresample states for 48 to 8 kHz conversions
 
     SRC_STATE      *insrc1;
     SRC_STATE      *outsrc1;
@@ -238,7 +232,7 @@ class MainFrame : public TopFrame
 
        int initPortAudioDevice(PortAudioWrap *pa, int inDevice, int outDevice, int soundCard, int sampleRate);
 
   protected:
+ protected:
         // protected event handlers
         virtual void OnCloseFrame(wxCloseEvent& event);
         virtual void OnExitClick(wxCommandEvent& event);