added -8-16 kHz sample rate conversion with shorts used for 16 kHz side
authordrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 19 Aug 2014 09:57:41 +0000 (09:57 +0000)
committerdrowe67 <drowe67@01035d8c-6547-0410-b346-abe4f91aad63>
Tue, 19 Aug 2014 09:57:41 +0000 (09:57 +0000)
git-svn-id: https://svn.code.sf.net/p/freetel/code@1809 01035d8c-6547-0410-b346-abe4f91aad63

codec2-dev/src/codec2_fdmdv.h
codec2-dev/src/fdmdv.c
codec2-dev/unittest/CMakeLists.txt
codec2-dev/unittest/t16_8.c
codec2-dev/unittest/t16_short_8.c [new file with mode: 0644]

index afe8381c3052c49a64c4e581df8ad29238baa6dd..8e8978dc237b88c159c0bbde5870736ca38b8944 100644 (file)
@@ -109,7 +109,9 @@ void           fdmdv_get_demod_stats(struct FDMDV *fdmdv_state, struct FDMDV_STA
 void           fdmdv_get_rx_spectrum(struct FDMDV *fdmdv_state, float mag_dB[], COMP rx_fdm[], int nin);
 
 void           fdmdv_8_to_16(float out16k[], float in8k[], int n);
+void           fdmdv_8_to_16_short(short out16k[], float in8k[], int n);
 void           fdmdv_16_to_8(float out8k[], float in16k[], int n);
+void           fdmdv_16_short_to_8(float out8k[], short in16k[], int n);
 
 void           fdmdv_freq_shift(COMP rx_fdm_fcorr[], COMP rx_fdm[], float foff, COMP *foff_phase_rect, int nin);
 
index 238abd3fd1ec90c5a217bd12520a89e231af4cc2..b40bad537d8899b367284458093521ad1a348c75 100644 (file)
@@ -1740,6 +1740,33 @@ void fdmdv_8_to_16(float out16k[], float in8k[], int n)
 
 }
 
+void fdmdv_8_to_16_short(short out16k[], float in8k[], int n)
+{
+    int i,j,k,l;
+    float acc;
+
+    /* make sure n is an integer multiple of the oversampling rate, ow
+       this function breaks */
+
+    assert((n % FDMDV_OS) == 0);
+
+    for(i=0; i<n; i++) {
+       for(j=0; j<FDMDV_OS; j++) {
+           acc = 0.0;
+           for(k=0,l=0; k<FDMDV_OS_TAPS_16K; k+=FDMDV_OS,l++)
+               acc += fdmdv_os_filter[k+j]*in8k[i-l];
+           out16k[i*FDMDV_OS+j] = acc*FDMDV_OS;
+           
+       }
+    }  
+
+    /* update filter memory */
+
+    for(i=-(FDMDV_OS_TAPS_8K); i<0; i++)
+       in8k[i] = in8k[i + n];
+
+}
+
 /*---------------------------------------------------------------------------*\
                                                        
   FUNCTION....: fdmdv_16_to_8()             
@@ -1758,13 +1785,30 @@ void fdmdv_8_to_16(float out16k[], float in8k[], int n)
 \*---------------------------------------------------------------------------*/
 
 void fdmdv_16_to_8(float out8k[], float in16k[], int n)
+{
+    int i,j,k;
+
+    for(i=0, k=0; k<n; i+=FDMDV_OS, k++) {
+        
+       out8k[k] = 0.0;
+       for(j=0; j<FDMDV_OS_TAPS_16K; j++)
+           out8k[k] += fdmdv_os_filter[j]*in16k[i-j]; 
+    }
+
+    /* update filter memory */
+
+    for(i=-FDMDV_OS_TAPS_16K; i<0; i++)
+       in16k[i] = in16k[i + n*FDMDV_OS];
+}
+
+void fdmdv_16_short_to_8(float out8k[], short in16k[], int n)
 {
     int i,j;
 
     for(i=0; i<n; i++) {
        out8k[i] = 0.0;
        for(j=0; j<FDMDV_OS_TAPS_16K; j++)
-           out8k[i] += fdmdv_os_filter[j]*in16k[i*FDMDV_OS-j];
+           out8k[i] += fdmdv_os_filter[j]*(float)in16k[i*FDMDV_OS-j];
     }
 
     /* update filter memory */
index 6977fef330b3d45269e245744530f2904d6a42e9..89cd8b82198b5ddc620b8554dfe23848db5edaf7 100644 (file)
@@ -54,6 +54,9 @@ target_link_libraries(tfdmdv codec2)
 add_executable(t16_8 t16_8.c ../src/fdmdv.c ../src/kiss_fft.c)
 target_link_libraries(t16_8 codec2)
 
+add_executable(t16_short_8 t16_short_8.c ../src/fdmdv.c ../src/kiss_fft.c)
+target_link_libraries(t16_short_8 codec2)
+
 add_executable(lspsync lspsync.c ../src/quantise.c ../src/lpc.c ../src/lsp.c ../src/dump.c ../src/kiss_fft.c ../src/codec2.c ../src/sine.c ../src/nlp.c ../src/postfilter.c ../src/phase.c ../src/interp.c ../src/pack.c ${CODEBOOKS})
 target_link_libraries(lspsync codec2)
 
index 1e64ccf71065312dc2b6070e1e8d0e3cbe97b64a..34d1f137be166f3e4655d021c49644fda5ed9dda 100644 (file)
@@ -26,7 +26,7 @@
 #define N16             (N8*FDMDV_OS)
 #define FRAMES                     50
 #define TWO_PI            6.283185307
-#define FS                       8000
+#define FS                      16000
 
 #define SINE
 
@@ -82,11 +82,11 @@ int main() {
            out16k_short[i] = (short)out16k[i];
        fwrite(out16k_short, sizeof(short), N16, f16);
        
-       /* add a 10 kHz spurious signal for fun, we want down sampler to
+       /* add a 6 kHz spurious signal, down sampler should
           knock this out */
 
        for(i=0; i<N16; i++,t1++)
-           in16k[i+FDMDV_OS_TAPS_16K] = out16k[i] + 16000.0*cos(TWO_PI*t1*1E4/FS);
+           in16k[i+FDMDV_OS_TAPS_16K] = out16k[i] + 16000.0*cos(TWO_PI*t1*6000.0/FS);
 
        /* downsample */
 
diff --git a/codec2-dev/unittest/t16_short_8.c b/codec2-dev/unittest/t16_short_8.c
new file mode 100644 (file)
index 0000000..31a1111
--- /dev/null
@@ -0,0 +1,98 @@
+/* 
+   t16__short_8.c
+   David Rowe
+   19 August 2014
+
+   Unit test for 16 to 8 kHz sample rate conversion functions.  I
+   evaluated output by plotting using Octave and looking for jaggies:
+
+     pl("../unittest/out16_short.raw",1,3000)
+     pl("../unittest/out8.raw",1,3000)
+
+   Listening to it also shows up anything nasty:
+
+     $ play -s -2 -r 16000 out16_short.raw
+     $ play -s -2 -r 8000 out8.raw
+
+  */
+
+#include <assert.h>
+#include <math.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "codec2_fdmdv.h"
+
+#define N8                        160 /* procssing buffer size at 8 kHz */
+#define N16             (N8*FDMDV_OS)
+#define FRAMES                     100
+#define TWO_PI            6.283185307
+#define FS                      16000
+
+#define SINE
+
+int main() {
+    float in8k[FDMDV_OS_TAPS_8K + N8];
+    short out16k_short[N16];
+    FILE *f16;
+
+    short in16k_short[FDMDV_OS_TAPS_16K + N16];
+    float out8k[N16];
+    short out8k_short[N8];
+    FILE *f8;
+
+    int i,f,t,t1;
+    float freq = 800.0;
+
+    f16 = fopen("out16_short.raw", "wb");
+    assert(f16 != NULL);
+    f8 = fopen("out8.raw", "wb");
+    assert(f8 != NULL);
+    
+    /* clear filter memories */
+
+    for(i=0; i<FDMDV_OS_TAPS_8K; i++)
+       in8k[i] = 0.0;
+    for(i=0; i<FDMDV_OS_TAPS_16K; i++)
+       in16k_short[i] = 0;
+
+    t = t1 = 0;
+    for(f=0; f<FRAMES; f++) {
+
+#ifdef DC
+       for(i=0; i<N8; i++)
+           in8k[FDMDV_OS_TAPS_8K+i] = 16000.0;
+#endif
+#ifdef SINE
+       for(i=0; i<N8; i++,t++)
+           in8k[FDMDV_OS_TAPS_8K+i] = 8000.0*cos(TWO_PI*t*freq/FS);
+#endif
+
+       /* upsample  */
+
+       fdmdv_8_to_16_short(out16k_short, &in8k[FDMDV_OS_TAPS_8K], N8);
+
+       fwrite(out16k_short, sizeof(short), N16, f16);
+       
+       /* add a 6 kHz spurious signal for fun, we want down sampler to
+          knock this out */
+
+       for(i=0; i<N16; i++,t1++)
+           in16k_short[i+FDMDV_OS_TAPS_16K] = out16k_short[i] + 8000.0*cos(TWO_PI*t1*6000.0/FS);
+
+       /* downsample */
+
+       fdmdv_16_short_to_8(out8k, &in16k_short[FDMDV_OS_TAPS_16K], N8);
+
+       /* save 8k to disk for plotting and check out */
+
+       for(i=0; i<N8; i++)
+           out8k_short[i] = (short)out8k[i];
+       fwrite(out8k_short, sizeof(short), N8, f8);
+       
+    }
+
+    fclose(f16);
+    fclose(f8);
+    return 0;
+
+}