]> code.delx.au - pulseaudio/blobdiff - src/pulsecore/resampler.c
Add new option to disable remixing from/to LFE and set it to on by default
[pulseaudio] / src / pulsecore / resampler.c
index d645639c0eba502b4e246cd423f63863f9017002..0ae029b3fda8169bc1a60d6040f594dbdaa5bfa4 100644 (file)
@@ -1,5 +1,3 @@
-/* $Id$ */
-
 /***
   This file is part of PulseAudio.
 
@@ -31,6 +29,8 @@
 #include <samplerate.h>
 #endif
 
+#include <speex/speex_resampler.h>
+
 #include <liboil/liboilfuncs.h>
 #include <liboil/liboil.h>
 
@@ -40,8 +40,6 @@
 #include <pulsecore/macro.h>
 #include <pulsecore/strbuf.h>
 
-#include "speexwrap.h"
-
 #include "ffmpeg/avcodec.h"
 
 #include "resampler.h"
@@ -375,7 +373,7 @@ size_t pa_resampler_max_block_size(pa_resampler *r) {
 
     /* We deduce the "largest" sample spec we're using during the
      * conversion */
-    ss.channels = PA_MAX(r->i_ss.channels, r->o_ss.channels);
+    ss.channels = (uint8_t) (PA_MAX(r->i_ss.channels, r->o_ss.channels));
 
     /* We silently assume that the format enum is ordered by size */
     ss.format = PA_MAX(r->i_ss.format, r->o_ss.format);
@@ -644,7 +642,7 @@ static void calc_map_table(pa_resampler *r) {
                 if (n > 0)
                     for (ic = 0; ic < r->i_ss.channels; ic++)
                         if (on_left(r->i_cm.map[ic])) {
-                            r->map_table[oc][ic] = 1.0 / n;
+                            r->map_table[oc][ic] = 1.0f / (float) n;
                             ic_connected[ic] = TRUE;
                         }
 
@@ -665,7 +663,7 @@ static void calc_map_table(pa_resampler *r) {
                 if (n > 0)
                     for (ic = 0; ic < r->i_ss.channels; ic++)
                         if (on_right(r->i_cm.map[ic])) {
-                            r->map_table[oc][ic] = 1.0 / n;
+                            r->map_table[oc][ic] = 1.0f / (float) n;
                             ic_connected[ic] = TRUE;
                         }
 
@@ -686,7 +684,7 @@ static void calc_map_table(pa_resampler *r) {
                 if (n > 0) {
                     for (ic = 0; ic < r->i_ss.channels; ic++)
                         if (on_center(r->i_cm.map[ic])) {
-                            r->map_table[oc][ic] = 1.0 / n;
+                            r->map_table[oc][ic] = 1.0f / (float) n;
                             ic_connected[ic] = TRUE;
                         }
                 } else {
@@ -703,7 +701,7 @@ static void calc_map_table(pa_resampler *r) {
                     if (n > 0)
                         for (ic = 0; ic < r->i_ss.channels; ic++)
                             if (on_left(r->i_cm.map[ic]) || on_right(r->i_cm.map[ic])) {
-                                r->map_table[oc][ic] = 1.0 / n;
+                                r->map_table[oc][ic] = 1.0f / (float) n;
                                 ic_connected[ic] = TRUE;
                             }
 
@@ -718,7 +716,11 @@ static void calc_map_table(pa_resampler *r) {
                  * channels for LFE. */
 
                 for (ic = 0; ic < r->i_ss.channels; ic++) {
-                    r->map_table[oc][ic] = 1.0 / r->i_ss.channels;
+
+                    if (!(r->flags & PA_RESAMPLER_NO_LFE))
+                        r->map_table[oc][ic] = 1.0f / (float) r->i_ss.channels;
+                    else
+                        r->map_table[oc][ic] = 0;
 
                     /* Please note that a channel connected to LFE
                      * doesn't really count as connected. */
@@ -765,12 +767,12 @@ static void calc_map_table(pa_resampler *r) {
                 for (ic = 0; ic < r->i_ss.channels; ic++) {
 
                     if (ic_connected[ic]) {
-                        r->map_table[oc][ic] *= .9;
+                        r->map_table[oc][ic] *= .9f;
                         continue;
                     }
 
                     if (on_left(r->i_cm.map[ic]))
-                        r->map_table[oc][ic] = .1 / ic_unconnected_left;
+                        r->map_table[oc][ic] = .1f / (float) ic_unconnected_left;
                 }
             }
         }
@@ -790,12 +792,12 @@ static void calc_map_table(pa_resampler *r) {
                 for (ic = 0; ic < r->i_ss.channels; ic++) {
 
                     if (ic_connected[ic]) {
-                        r->map_table[oc][ic] *= .9;
+                        r->map_table[oc][ic] *= .9f;
                         continue;
                     }
 
                     if (on_right(r->i_cm.map[ic]))
-                        r->map_table[oc][ic] = .1 / ic_unconnected_right;
+                        r->map_table[oc][ic] = .1f / (float) ic_unconnected_right;
                 }
             }
         }
@@ -816,12 +818,12 @@ static void calc_map_table(pa_resampler *r) {
                 for (ic = 0; ic < r->i_ss.channels; ic++)  {
 
                     if (ic_connected[ic]) {
-                        r->map_table[oc][ic] *= .9;
+                        r->map_table[oc][ic] *= .9f;
                         continue;
                     }
 
                     if (on_center(r->i_cm.map[ic])) {
-                        r->map_table[oc][ic] = .1 / ic_unconnected_center;
+                        r->map_table[oc][ic] = .1f / (float) ic_unconnected_center;
                         mixed_in = TRUE;
                     }
                 }
@@ -842,18 +844,18 @@ static void calc_map_table(pa_resampler *r) {
                     for (ic = 0; ic < r->i_ss.channels; ic++)  {
 
                         if (ic_connected[ic]) {
-                            r->map_table[oc][ic] *= .75;
+                            r->map_table[oc][ic] *= .75f;
                             continue;
                         }
 
                         if (on_center(r->i_cm.map[ic]))
-                            r->map_table[oc][ic] = .375 / ic_unconnected_center;
+                            r->map_table[oc][ic] = .375f / (float) ic_unconnected_center;
                     }
                 }
             }
         }
 
-        if (ic_unconnected_lfe > 0) {
+        if (ic_unconnected_lfe > 0 && !(r->flags & PA_RESAMPLER_NO_LFE)) {
 
             /* OK, so there is an unconnected LFE channel. Let's mix
              * it into all channels, with factor 0.375 */
@@ -864,7 +866,7 @@ static void calc_map_table(pa_resampler *r) {
                     continue;
 
                 for (oc = 0; oc < r->o_ss.channels; oc++)
-                    r->map_table[oc][ic] = 0.375 / ic_unconnected_lfe;
+                    r->map_table[oc][ic] = 0.375f / (float) ic_unconnected_lfe;
             }
         }
     }
@@ -907,7 +909,7 @@ static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input)
     if (!r->to_work_format_func || !input->length)
         return input;
 
-    n_samples = (input->length / r->i_fz) * r->i_ss.channels;
+    n_samples = (unsigned) ((input->length / r->i_fz) * r->i_ss.channels);
 
     r->buf1.index = 0;
     r->buf1.length = r->w_sz * n_samples;
@@ -976,7 +978,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
     if (!r->map_required || !input->length)
         return input;
 
-    in_n_samples = input->length / r->w_sz;
+    in_n_samples = (unsigned) (input->length / r->w_sz);
     n_frames = in_n_samples / r->i_ss.channels;
     out_n_samples = n_frames * r->o_ss.channels;
 
@@ -996,8 +998,8 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
 
     memset(dst, 0, r->buf2.length);
 
-    o_skip = r->w_sz * r->o_ss.channels;
-    i_skip = r->w_sz * r->i_ss.channels;
+    o_skip = (int) (r->w_sz * r->o_ss.channels);
+    i_skip = (int) (r->w_sz * r->i_ss.channels);
 
     switch (r->work_format) {
         case PA_SAMPLE_FLOAT32NE:
@@ -1015,7 +1017,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
                             (float*) dst + oc, o_skip,
                             (float*) dst + oc, o_skip,
                             (float*) src + ic, i_skip,
-                            n_frames,
+                            (int) n_frames,
                             &one, &r->map_table[oc][ic]);
                 }
             }
@@ -1039,7 +1041,7 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
                                 (int16_t*) dst + oc, o_skip,
                                 (int16_t*) dst + oc, o_skip,
                                 (int16_t*) src + ic, i_skip,
-                                n_frames,
+                                (int) n_frames,
                                 &one, &one);
 
                     } else
@@ -1048,8 +1050,8 @@ static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
                                 (int16_t*) dst + oc, o_skip,
                                 (int16_t*) dst + oc, o_skip,
                                 (int16_t*) src + ic, i_skip,
-                                n_frames,
-                                1.0, r->map_table[oc][ic]);
+                                (int) n_frames,
+                                1.0f, r->map_table[oc][ic]);
                 }
             }
 
@@ -1079,8 +1081,8 @@ static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
     if (!r->impl_resample || !input->length)
         return input;
 
-    in_n_samples = input->length / r->w_sz;
-    in_n_frames = in_n_samples / r->o_ss.channels;
+    in_n_samples = (unsigned) (input->length / r->w_sz);
+    in_n_frames = (unsigned) (in_n_samples / r->o_ss.channels);
 
     out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_FRAMES;
     out_n_samples = out_n_frames * r->o_ss.channels;
@@ -1114,8 +1116,8 @@ static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input
     if (!r->from_work_format_func || !input->length)
         return input;
 
-    n_samples = input->length / r->w_sz;
-    n_frames =  n_samples / r->o_ss.channels;
+    n_samples = (unsigned) (input->length / r->w_sz);
+    n_frames = n_samples / r->o_ss.channels;
 
     r->buf4.index = 0;
     r->buf4.length = r->o_fz * n_frames;
@@ -1180,10 +1182,10 @@ static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, un
     memset(&data, 0, sizeof(data));
 
     data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
-    data.input_frames = in_n_frames;
+    data.input_frames = (long int) in_n_frames;
 
     data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
-    data.output_frames = *out_n_frames;
+    data.output_frames = (long int) *out_n_frames;
 
     data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
     data.end_of_input = 0;
@@ -1194,7 +1196,7 @@ static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, un
     pa_memblock_release(input->memblock);
     pa_memblock_release(output->memblock);
 
-    *out_n_frames = data.output_frames_gen;
+    *out_n_frames = (unsigned) data.output_frames_gen;
 }
 
 static void libsamplerate_update_rates(pa_resampler *r) {
@@ -1247,7 +1249,7 @@ static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsi
     in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
     out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
 
-    pa_assert_se(paspfl_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
+    pa_assert_se(speex_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
 
     pa_memblock_release(input->memblock);
     pa_memblock_release(output->memblock);
@@ -1268,7 +1270,7 @@ static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsign
     in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
     out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
 
-    pa_assert_se(paspfx_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
+    pa_assert_se(speex_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
 
     pa_memblock_release(input->memblock);
     pa_memblock_release(output->memblock);
@@ -1280,23 +1282,13 @@ static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsign
 static void speex_update_rates(pa_resampler *r) {
     pa_assert(r);
 
-    if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
-        pa_assert_se(paspfx_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
-    else {
-        pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
-        pa_assert_se(paspfl_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
-    }
+    pa_assert_se(speex_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
 }
 
 static void speex_reset(pa_resampler *r) {
     pa_assert(r);
 
-    if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
-        pa_assert_se(paspfx_resampler_reset_mem(r->speex.state) == 0);
-    else  {
-        pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
-        pa_assert_se(paspfl_resampler_reset_mem(r->speex.state) == 0);
-    }
+    pa_assert_se(speex_resampler_reset_mem(r->speex.state) == 0);
 }
 
 static void speex_free(pa_resampler *r) {
@@ -1305,12 +1297,7 @@ static void speex_free(pa_resampler *r) {
     if (!r->speex.state)
         return;
 
-    if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX)
-        paspfx_resampler_destroy(r->speex.state);
-    else {
-        pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
-        paspfl_resampler_destroy(r->speex.state);
-    }
+    speex_resampler_destroy(r->speex.state);
 }
 
 static int speex_init(pa_resampler *r) {
@@ -1323,26 +1310,22 @@ static int speex_init(pa_resampler *r) {
     r->impl_reset = speex_reset;
 
     if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX) {
-        q = r->method - PA_RESAMPLER_SPEEX_FIXED_BASE;
-
-        pa_log_info("Choosing speex quality setting %i.", q);
-
-        if (!(r->speex.state = paspfx_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
-            return -1;
 
+        q = r->method - PA_RESAMPLER_SPEEX_FIXED_BASE;
         r->impl_resample = speex_resample_int;
+
     } else {
         pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
-        q = r->method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
-
-        pa_log_info("Choosing speex quality setting %i.", q);
-
-        if (!(r->speex.state = paspfl_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
-            return -1;
 
+        q = r->method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
         r->impl_resample = speex_resample_float;
     }
 
+    pa_log_info("Choosing speex quality setting %i.", q);
+
+    if (!(r->speex.state = speex_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
+        return -1;
+
     return 0;
 }
 
@@ -1375,7 +1358,7 @@ static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned
         pa_assert(o_index * fz < pa_memblock_get_length(output->memblock));
 
         oil_memcpy((uint8_t*) dst + fz * o_index,
-                   (uint8_t*) src + fz * j, fz);
+                   (uint8_t*) src + fz * j, (int) fz);
     }
 
     pa_memblock_release(input->memblock);
@@ -1451,16 +1434,16 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
                 for (c = 0; c < r->o_ss.channels; c++, s++) {
                     int16_t n;
 
-                    n = *s < 0 ? -*s : *s;
+                    n = (int16_t) (*s < 0 ? -*s : *s);
 
                     if (n > r->peaks.max_i[c])
                         r->peaks.max_i[c] = n;
                 }
 
-            for (c = 0; c < r->o_ss.channels; c++, d++)
+            for (c = 0; c < r->o_ss.channels; c++, d++) {
                  *d = r->peaks.max_i[c];
-
-            memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
+                 r->peaks.max_i[c] = 0;
+            }
         } else {
             unsigned i, c;
             float *s = (float*) ((uint8_t*) src + fz * j);
@@ -1476,11 +1459,13 @@ static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned i
                         r->peaks.max_f[c] = n;
                 }
 
-            for (c = 0; c < r->o_ss.channels; c++, d++)
+            for (c = 0; c < r->o_ss.channels; c++, d++) {
                 *d = r->peaks.max_f[c];
-
-            memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
+                r->peaks.max_f[c] = 0;
+            }
         }
+
+        start = j+1;
     }
 
     pa_memblock_release(input->memblock);
@@ -1542,7 +1527,7 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned
         p = pa_memblock_acquire(b);
 
         /* Copy the remaining data into it */
-        l = r->ffmpeg.buf[c].length;
+        l = (unsigned) r->ffmpeg.buf[c].length;
         if (r->ffmpeg.buf[c].memblock) {
             t = (int16_t*) ((uint8_t*) pa_memblock_acquire(r->ffmpeg.buf[c].memblock) + r->ffmpeg.buf[c].index);
             memcpy(p, t, l);
@@ -1562,18 +1547,18 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned
         pa_memblock_release(input->memblock);
 
         /* Calculate the resulting number of frames */
-        in = in_n_frames + l / sizeof(int16_t);
+        in = (unsigned) in_n_frames + l / (unsigned) sizeof(int16_t);
 
         /* Allocate buffer for the result */
         w = pa_memblock_new(r->mempool, *out_n_frames * sizeof(int16_t));
         q = pa_memblock_acquire(w);
 
         /* Now, resample */
-        used_frames = av_resample(r->ffmpeg.state,
-                                  q, p,
-                                  &consumed_frames,
-                                  in, *out_n_frames,
-                                  c >= (unsigned) r->o_ss.channels-1);
+        used_frames = (unsigned) av_resample(r->ffmpeg.state,
+                                             q, p,
+                                             &consumed_frames,
+                                             (int) in, (int) *out_n_frames,
+                                             c >= (unsigned) (r->o_ss.channels-1));
 
         pa_memblock_release(b);
 
@@ -1581,8 +1566,8 @@ static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned
         pa_assert(consumed_frames <= (int) in);
         if (consumed_frames < (int) in) {
             r->ffmpeg.buf[c].memblock = b;
-            r->ffmpeg.buf[c].index = consumed_frames * sizeof(int16_t);
-            r->ffmpeg.buf[c].length = (in - consumed_frames) * sizeof(int16_t);
+            r->ffmpeg.buf[c].index = (size_t) consumed_frames * sizeof(int16_t);
+            r->ffmpeg.buf[c].length = (size_t) (in - (unsigned) consumed_frames) * sizeof(int16_t);
         } else
             pa_memblock_unref(b);
 
@@ -1624,7 +1609,7 @@ static int ffmpeg_init(pa_resampler *r) {
      * internally only uses these hardcoded values, so let's use them
      * here for now as well until ffmpeg makes this configurable. */
 
-    if (!(r->ffmpeg.state = av_resample_init(r->o_ss.rate, r->i_ss.rate, 16, 10, 0, 0.8)))
+    if (!(r->ffmpeg.state = av_resample_init((int) r->o_ss.rate, (int) r->i_ss.rate, 16, 10, 0, 0.8)))
         return -1;
 
     r->impl_free = ffmpeg_free;