shithub: dumb

Download patch

ref: 651e5235b72883f8480bb8138fad01bb168c16f4
parent: 9e2c91079ddbbc3d968f17e78b734d529af2afcd
author: Chris Moeller <kode54@gmail.com>
date: Fri Apr 4 16:25:43 EDT 2014

Updated sinc resampler with unscaled windowing, which fixes a lot of the previous aliasing

--- a/dumb/src/helpers/resampler.c
+++ b/dumb/src/helpers/resampler.c
@@ -19,7 +19,7 @@
 
 #include "internal/resampler.h"
 
-enum { RESAMPLER_SHIFT = 13 };
+enum { RESAMPLER_SHIFT = 10 };
 enum { RESAMPLER_RESOLUTION = 1 << RESAMPLER_SHIFT };
 enum { SINC_WIDTH = 16 };
 enum { SINC_SAMPLES = RESAMPLER_RESOLUTION * SINC_WIDTH };
@@ -28,6 +28,7 @@
 ALIGNED static float cubic_lut[CUBIC_SAMPLES];
 
 static float sinc_lut[SINC_SAMPLES + 1];
+static float window_lut[SINC_SAMPLES + 1];
 
 enum { resampler_buffer_size = SINC_WIDTH * 4 };
 
@@ -89,7 +90,8 @@
         // Lanczos
         float window = sinc(y);
 #endif
-        sinc_lut[i] = fabs(x) < SINC_WIDTH ? sinc(x) * window : 0.0;
+        sinc_lut[i] = fabs(x) < SINC_WIDTH ? sinc(x) : 0.0;
+        window_lut[i] = window;
     }
     dx = 1.0 / (float)(RESAMPLER_RESOLUTION);
     x = 0.0;
@@ -335,6 +337,30 @@
     }
 }
 
+void resampler_write_sample_fixed(void *_r, int s, unsigned char depth)
+{
+    resampler * r = ( resampler * ) _r;
+    
+    if ( r->delay_added < 0 )
+    {
+        r->delay_added = 0;
+        r->write_filled = resampler_input_delay( r );
+    }
+    
+    if ( r->write_filled < resampler_buffer_size )
+    {
+        float s32 = s;
+        s32 /= (double)(1 << (depth - 1));
+        
+        r->buffer_in[ r->write_pos ] = s32;
+        r->buffer_in[ r->write_pos + resampler_buffer_size ] = s32;
+        
+        ++r->write_filled;
+        
+        r->write_pos = ( r->write_pos + 1 ) % resampler_buffer_size;
+    }
+}
+
 static int resampler_run_zoh(resampler * r, float ** out_, float * out_end)
 {
     int in_size = r->write_filled;
@@ -407,7 +433,8 @@
             for (; i >= -SINC_WIDTH + 1; --i)
             {
                 int pos = i * step;
-                kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(inv_phase - pos)];
+                int abs_pos = abs(inv_phase - pos);
+                kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs_pos] * window_lut[abs_pos];
             }
             sample = *in++ - last_amp;
             last_amp += sample;
@@ -470,7 +497,8 @@
             for (; i >= -SINC_WIDTH + 1; --i)
             {
                 int pos = i * step;
-                kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(inv_phase - pos)];
+                int abs_pos = abs(inv_phase - pos);
+                kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs_pos] * window_lut[abs_pos];
             }
             sample = *in++ - last_amp;
             last_amp += sample;
@@ -667,6 +695,7 @@
         int phase_inc = r->phase_inc;
 
         int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION;
+        int window_step = RESAMPLER_RESOLUTION;
 
         do
         {
@@ -681,7 +710,8 @@
             for (; i >= -SINC_WIDTH + 1; --i)
             {
                 int pos = i * step;
-                kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
+                int window_pos = i * window_step;
+                kernel_sum += kernel[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)];
             }
             for (sample = 0, i = 0; i < SINC_WIDTH * 2; ++i)
                 sample += in[i] * kernel[i];
@@ -722,6 +752,7 @@
         int phase_inc = r->phase_inc;
         
         int step = phase_inc > RESAMPLER_RESOLUTION ? RESAMPLER_RESOLUTION * RESAMPLER_RESOLUTION / phase_inc : RESAMPLER_RESOLUTION;
+        int window_step = RESAMPLER_RESOLUTION;
         
         do
         {
@@ -740,7 +771,8 @@
             for (; i >= -SINC_WIDTH + 1; --i)
             {
                 int pos = i * step;
-                kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)];
+                int window_pos = i * window_step;
+                kernel_sum += kernelf[i + SINC_WIDTH - 1] = sinc_lut[abs(phase_adj - pos)] * window_lut[abs(phase - window_pos)];
             }
             for (i = 0; i < SINC_WIDTH / 2; ++i)
             {