LCOV - code coverage report
Current view: top level - pulsecore - resampler.c (source / functions) Hit Total Coverage
Test: lcov.out Lines: 154 770 20.0 %
Date: 2012-07-17 Functions: 11 47 23.4 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 115 718 16.0 %

           Branch data     Line data    Source code
       1                 :            : /***
       2                 :            :   This file is part of PulseAudio.
       3                 :            : 
       4                 :            :   Copyright 2004-2006 Lennart Poettering
       5                 :            : 
       6                 :            :   PulseAudio is free software; you can redistribute it and/or modify
       7                 :            :   it under the terms of the GNU Lesser General Public License as published
       8                 :            :   by the Free Software Foundation; either version 2.1 of the License,
       9                 :            :   or (at your option) any later version.
      10                 :            : 
      11                 :            :   PulseAudio is distributed in the hope that it will be useful, but
      12                 :            :   WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :            :   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
      14                 :            :   General Public License for more details.
      15                 :            : 
      16                 :            :   You should have received a copy of the GNU Lesser General Public License
      17                 :            :   along with PulseAudio; if not, write to the Free Software
      18                 :            :   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
      19                 :            :   USA.
      20                 :            : ***/
      21                 :            : 
      22                 :            : #ifdef HAVE_CONFIG_H
      23                 :            : #include <config.h>
      24                 :            : #endif
      25                 :            : 
      26                 :            : #include <string.h>
      27                 :            : 
      28                 :            : #ifdef HAVE_LIBSAMPLERATE
      29                 :            : #include <samplerate.h>
      30                 :            : #endif
      31                 :            : 
      32                 :            : #ifdef HAVE_SPEEX
      33                 :            : #include <speex/speex_resampler.h>
      34                 :            : #endif
      35                 :            : 
      36                 :            : #include <pulse/xmalloc.h>
      37                 :            : #include <pulsecore/sconv.h>
      38                 :            : #include <pulsecore/log.h>
      39                 :            : #include <pulsecore/macro.h>
      40                 :            : #include <pulsecore/strbuf.h>
      41                 :            : #include <pulsecore/remap.h>
      42                 :            : #include <pulsecore/core-util.h>
      43                 :            : #include "ffmpeg/avcodec.h"
      44                 :            : 
      45                 :            : #include "resampler.h"
      46                 :            : 
      47                 :            : /* Number of samples of extra space we allow the resamplers to return */
      48                 :            : #define EXTRA_FRAMES 128
      49                 :            : 
      50                 :            : struct pa_resampler {
      51                 :            :     pa_resample_method_t method;
      52                 :            :     pa_resample_flags_t flags;
      53                 :            : 
      54                 :            :     pa_sample_spec i_ss, o_ss;
      55                 :            :     pa_channel_map i_cm, o_cm;
      56                 :            :     size_t i_fz, o_fz, w_sz;
      57                 :            :     pa_mempool *mempool;
      58                 :            : 
      59                 :            :     pa_memchunk to_work_format_buf;
      60                 :            :     pa_memchunk remap_buf;
      61                 :            :     pa_memchunk resample_buf;
      62                 :            :     pa_memchunk from_work_format_buf;
      63                 :            :     unsigned to_work_format_buf_samples;
      64                 :            :     size_t remap_buf_size;
      65                 :            :     unsigned resample_buf_samples;
      66                 :            :     unsigned from_work_format_buf_samples;
      67                 :            :     pa_bool_t remap_buf_contains_leftover_data;
      68                 :            : 
      69                 :            :     pa_sample_format_t work_format;
      70                 :            : 
      71                 :            :     pa_convert_func_t to_work_format_func;
      72                 :            :     pa_convert_func_t from_work_format_func;
      73                 :            : 
      74                 :            :     pa_remap_t remap;
      75                 :            :     pa_bool_t map_required;
      76                 :            : 
      77                 :            :     void (*impl_free)(pa_resampler *r);
      78                 :            :     void (*impl_update_rates)(pa_resampler *r);
      79                 :            :     void (*impl_resample)(pa_resampler *r, const pa_memchunk *in, unsigned in_samples, pa_memchunk *out, unsigned *out_samples);
      80                 :            :     void (*impl_reset)(pa_resampler *r);
      81                 :            : 
      82                 :            :     struct { /* data specific to the trivial resampler */
      83                 :            :         unsigned o_counter;
      84                 :            :         unsigned i_counter;
      85                 :            :     } trivial;
      86                 :            : 
      87                 :            :     struct { /* data specific to the peak finder pseudo resampler */
      88                 :            :         unsigned o_counter;
      89                 :            :         unsigned i_counter;
      90                 :            : 
      91                 :            :         float max_f[PA_CHANNELS_MAX];
      92                 :            :         int16_t max_i[PA_CHANNELS_MAX];
      93                 :            : 
      94                 :            :     } peaks;
      95                 :            : 
      96                 :            : #ifdef HAVE_LIBSAMPLERATE
      97                 :            :     struct { /* data specific to libsamplerate */
      98                 :            :         SRC_STATE *state;
      99                 :            :     } src;
     100                 :            : #endif
     101                 :            : 
     102                 :            : #ifdef HAVE_SPEEX
     103                 :            :     struct { /* data specific to speex */
     104                 :            :         SpeexResamplerState* state;
     105                 :            :     } speex;
     106                 :            : #endif
     107                 :            : 
     108                 :            :     struct { /* data specific to ffmpeg */
     109                 :            :         struct AVResampleContext *state;
     110                 :            :         pa_memchunk buf[PA_CHANNELS_MAX];
     111                 :            :     } ffmpeg;
     112                 :            : };
     113                 :            : 
     114                 :            : static int copy_init(pa_resampler *r);
     115                 :            : static int trivial_init(pa_resampler*r);
     116                 :            : #ifdef HAVE_SPEEX
     117                 :            : static int speex_init(pa_resampler*r);
     118                 :            : #endif
     119                 :            : static int ffmpeg_init(pa_resampler*r);
     120                 :            : static int peaks_init(pa_resampler*r);
     121                 :            : #ifdef HAVE_LIBSAMPLERATE
     122                 :            : static int libsamplerate_init(pa_resampler*r);
     123                 :            : #endif
     124                 :            : 
     125                 :            : static void calc_map_table(pa_resampler *r);
     126                 :            : 
     127                 :            : static int (* const init_table[])(pa_resampler*r) = {
     128                 :            : #ifdef HAVE_LIBSAMPLERATE
     129                 :            :     [PA_RESAMPLER_SRC_SINC_BEST_QUALITY]   = libsamplerate_init,
     130                 :            :     [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = libsamplerate_init,
     131                 :            :     [PA_RESAMPLER_SRC_SINC_FASTEST]        = libsamplerate_init,
     132                 :            :     [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD]     = libsamplerate_init,
     133                 :            :     [PA_RESAMPLER_SRC_LINEAR]              = libsamplerate_init,
     134                 :            : #else
     135                 :            :     [PA_RESAMPLER_SRC_SINC_BEST_QUALITY]   = NULL,
     136                 :            :     [PA_RESAMPLER_SRC_SINC_MEDIUM_QUALITY] = NULL,
     137                 :            :     [PA_RESAMPLER_SRC_SINC_FASTEST]        = NULL,
     138                 :            :     [PA_RESAMPLER_SRC_ZERO_ORDER_HOLD]     = NULL,
     139                 :            :     [PA_RESAMPLER_SRC_LINEAR]              = NULL,
     140                 :            : #endif
     141                 :            :     [PA_RESAMPLER_TRIVIAL]                 = trivial_init,
     142                 :            : #ifdef HAVE_SPEEX
     143                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+0]      = speex_init,
     144                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+1]      = speex_init,
     145                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+2]      = speex_init,
     146                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+3]      = speex_init,
     147                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+4]      = speex_init,
     148                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+5]      = speex_init,
     149                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+6]      = speex_init,
     150                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+7]      = speex_init,
     151                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+8]      = speex_init,
     152                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+9]      = speex_init,
     153                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+10]     = speex_init,
     154                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+0]      = speex_init,
     155                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+1]      = speex_init,
     156                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+2]      = speex_init,
     157                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+3]      = speex_init,
     158                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+4]      = speex_init,
     159                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+5]      = speex_init,
     160                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+6]      = speex_init,
     161                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+7]      = speex_init,
     162                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+8]      = speex_init,
     163                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+9]      = speex_init,
     164                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+10]     = speex_init,
     165                 :            : #else
     166                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+0]      = NULL,
     167                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+1]      = NULL,
     168                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+2]      = NULL,
     169                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+3]      = NULL,
     170                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+4]      = NULL,
     171                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+5]      = NULL,
     172                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+6]      = NULL,
     173                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+7]      = NULL,
     174                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+8]      = NULL,
     175                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+9]      = NULL,
     176                 :            :     [PA_RESAMPLER_SPEEX_FLOAT_BASE+10]     = NULL,
     177                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+0]      = NULL,
     178                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+1]      = NULL,
     179                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+2]      = NULL,
     180                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+3]      = NULL,
     181                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+4]      = NULL,
     182                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+5]      = NULL,
     183                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+6]      = NULL,
     184                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+7]      = NULL,
     185                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+8]      = NULL,
     186                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+9]      = NULL,
     187                 :            :     [PA_RESAMPLER_SPEEX_FIXED_BASE+10]     = NULL,
     188                 :            : #endif
     189                 :            :     [PA_RESAMPLER_FFMPEG]                  = ffmpeg_init,
     190                 :            :     [PA_RESAMPLER_AUTO]                    = NULL,
     191                 :            :     [PA_RESAMPLER_COPY]                    = copy_init,
     192                 :            :     [PA_RESAMPLER_PEAKS]                   = peaks_init,
     193                 :            : };
     194                 :            : 
     195                 :        338 : pa_resampler* pa_resampler_new(
     196                 :            :         pa_mempool *pool,
     197                 :            :         const pa_sample_spec *a,
     198                 :            :         const pa_channel_map *am,
     199                 :            :         const pa_sample_spec *b,
     200                 :            :         const pa_channel_map *bm,
     201                 :            :         pa_resample_method_t method,
     202                 :            :         pa_resample_flags_t flags) {
     203                 :            : 
     204                 :        338 :     pa_resampler *r = NULL;
     205                 :            : 
     206         [ -  + ]:        338 :     pa_assert(pool);
     207         [ -  + ]:        338 :     pa_assert(a);
     208         [ -  + ]:        338 :     pa_assert(b);
     209         [ -  + ]:        338 :     pa_assert(pa_sample_spec_valid(a));
     210         [ -  + ]:        338 :     pa_assert(pa_sample_spec_valid(b));
     211         [ -  + ]:        338 :     pa_assert(method >= 0);
     212         [ -  + ]:        338 :     pa_assert(method < PA_RESAMPLER_MAX);
     213                 :            : 
     214                 :            :     /* Fix method */
     215                 :            : 
     216 [ +  - ][ +  - ]:        338 :     if (!(flags & PA_RESAMPLER_VARIABLE_RATE) && a->rate == b->rate) {
     217                 :        338 :         pa_log_info("Forcing resampler 'copy', because of fixed, identical sample rates.");
     218                 :        338 :         method = PA_RESAMPLER_COPY;
     219                 :            :     }
     220                 :            : 
     221         [ -  + ]:        338 :     if (!pa_resample_method_supported(method)) {
     222                 :          0 :         pa_log_warn("Support for resampler '%s' not compiled in, reverting to 'auto'.", pa_resample_method_to_string(method));
     223                 :          0 :         method = PA_RESAMPLER_AUTO;
     224                 :            :     }
     225                 :            : 
     226 [ -  + ][ #  # ]:        338 :     if (method == PA_RESAMPLER_FFMPEG && (flags & PA_RESAMPLER_VARIABLE_RATE)) {
     227                 :          0 :         pa_log_info("Resampler 'ffmpeg' cannot do variable rate, reverting to resampler 'auto'.");
     228                 :          0 :         method = PA_RESAMPLER_AUTO;
     229                 :            :     }
     230                 :            : 
     231 [ +  - ][ +  - ]:        338 :     if (method == PA_RESAMPLER_COPY && ((flags & PA_RESAMPLER_VARIABLE_RATE) || a->rate != b->rate)) {
                 [ -  + ]
     232                 :          0 :         pa_log_info("Resampler 'copy' cannot change sampling rate, reverting to resampler 'auto'.");
     233                 :          0 :         method = PA_RESAMPLER_AUTO;
     234                 :            :     }
     235                 :            : 
     236         [ -  + ]:        338 :     if (method == PA_RESAMPLER_AUTO) {
     237                 :            : #ifdef HAVE_SPEEX
     238                 :          0 :         method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
     239                 :            : #else
     240                 :            :         method = PA_RESAMPLER_FFMPEG;
     241                 :            : #endif
     242                 :            :     }
     243                 :            : 
     244                 :        338 :     r = pa_xnew0(pa_resampler, 1);
     245                 :        338 :     r->mempool = pool;
     246                 :        338 :     r->method = method;
     247                 :        338 :     r->flags = flags;
     248                 :            : 
     249                 :            :     /* Fill sample specs */
     250                 :        338 :     r->i_ss = *a;
     251                 :        338 :     r->o_ss = *b;
     252                 :            : 
     253                 :            :     /* set up the remap structure */
     254                 :        338 :     r->remap.i_ss = &r->i_ss;
     255                 :        338 :     r->remap.o_ss = &r->o_ss;
     256                 :        338 :     r->remap.format = &r->work_format;
     257                 :            : 
     258         [ -  + ]:        338 :     if (am)
     259                 :          0 :         r->i_cm = *am;
     260         [ +  - ]:        338 :     else if (!pa_channel_map_init_auto(&r->i_cm, r->i_ss.channels, PA_CHANNEL_MAP_DEFAULT))
     261                 :            :         goto fail;
     262                 :            : 
     263         [ -  + ]:        338 :     if (bm)
     264                 :          0 :         r->o_cm = *bm;
     265         [ +  - ]:        338 :     else if (!pa_channel_map_init_auto(&r->o_cm, r->o_ss.channels, PA_CHANNEL_MAP_DEFAULT))
     266                 :            :         goto fail;
     267                 :            : 
     268                 :        338 :     r->i_fz = pa_frame_size(a);
     269                 :        338 :     r->o_fz = pa_frame_size(b);
     270                 :            : 
     271                 :        338 :     calc_map_table(r);
     272                 :            : 
     273                 :        338 :     pa_log_info("Using resampler '%s'", pa_resample_method_to_string(method));
     274                 :            : 
     275         [ -  + ]:        338 :     if ((method >= PA_RESAMPLER_SPEEX_FIXED_BASE && method <= PA_RESAMPLER_SPEEX_FIXED_MAX) ||
     276                 :            :         (method == PA_RESAMPLER_FFMPEG))
     277                 :          0 :         r->work_format = PA_SAMPLE_S16NE;
     278 [ -  + ][ #  # ]:        338 :     else if (method == PA_RESAMPLER_TRIVIAL || method == PA_RESAMPLER_COPY || method == PA_RESAMPLER_PEAKS) {
     279                 :            : 
     280 [ +  - ][ +  + ]:        338 :         if (r->map_required || a->format != b->format || method == PA_RESAMPLER_PEAKS) {
     281                 :            : 
     282         [ +  + ]:        312 :             if (a->format == PA_SAMPLE_S32NE || a->format == PA_SAMPLE_S32RE ||
     283 [ +  + ][ +  + ]:        240 :                 a->format == PA_SAMPLE_FLOAT32NE || a->format == PA_SAMPLE_FLOAT32RE ||
     284 [ +  + ][ +  + ]:        192 :                 a->format == PA_SAMPLE_S24NE || a->format == PA_SAMPLE_S24RE ||
     285 [ +  + ][ +  + ]:        144 :                 a->format == PA_SAMPLE_S24_32NE || a->format == PA_SAMPLE_S24_32RE ||
     286 [ +  + ][ +  + ]:        110 :                 b->format == PA_SAMPLE_S32NE || b->format == PA_SAMPLE_S32RE ||
     287 [ +  + ][ +  + ]:         90 :                 b->format == PA_SAMPLE_FLOAT32NE || b->format == PA_SAMPLE_FLOAT32RE ||
     288 [ +  + ][ +  + ]:         70 :                 b->format == PA_SAMPLE_S24NE || b->format == PA_SAMPLE_S24RE ||
     289         [ +  + ]:         50 :                 b->format == PA_SAMPLE_S24_32NE || b->format == PA_SAMPLE_S24_32RE)
     290                 :        272 :                 r->work_format = PA_SAMPLE_FLOAT32NE;
     291                 :            :             else
     292                 :         40 :                 r->work_format = PA_SAMPLE_S16NE;
     293                 :            : 
     294                 :            :         } else
     295                 :         26 :             r->work_format = a->format;
     296                 :            : 
     297                 :            :     } else
     298                 :          0 :         r->work_format = PA_SAMPLE_FLOAT32NE;
     299                 :            : 
     300                 :        338 :     pa_log_info("Using %s as working format.", pa_sample_format_to_string(r->work_format));
     301                 :            : 
     302                 :        338 :     r->w_sz = pa_sample_size_of_format(r->work_format);
     303                 :            : 
     304         [ +  + ]:        338 :     if (r->i_ss.format != r->work_format) {
     305         [ +  + ]:        280 :         if (r->work_format == PA_SAMPLE_FLOAT32NE) {
     306         [ +  - ]:        248 :             if (!(r->to_work_format_func = pa_get_convert_to_float32ne_function(r->i_ss.format)))
     307                 :            :                 goto fail;
     308                 :            :         } else {
     309         [ -  + ]:         32 :             pa_assert(r->work_format == PA_SAMPLE_S16NE);
     310         [ +  - ]:         32 :             if (!(r->to_work_format_func = pa_get_convert_to_s16ne_function(r->i_ss.format)))
     311                 :            :                 goto fail;
     312                 :            :         }
     313                 :            :     }
     314                 :            : 
     315         [ +  + ]:        338 :     if (r->o_ss.format != r->work_format) {
     316         [ +  + ]:        280 :         if (r->work_format == PA_SAMPLE_FLOAT32NE) {
     317         [ +  - ]:        248 :             if (!(r->from_work_format_func = pa_get_convert_from_float32ne_function(r->o_ss.format)))
     318                 :            :                 goto fail;
     319                 :            :         } else {
     320         [ -  + ]:         32 :             pa_assert(r->work_format == PA_SAMPLE_S16NE);
     321         [ +  - ]:         32 :             if (!(r->from_work_format_func = pa_get_convert_from_s16ne_function(r->o_ss.format)))
     322                 :            :                 goto fail;
     323                 :            :         }
     324                 :            :     }
     325                 :            : 
     326                 :            :     /* initialize implementation */
     327         [ -  + ]:        338 :     if (init_table[method](r) < 0)
     328                 :            :         goto fail;
     329                 :            : 
     330                 :            :     return r;
     331                 :            : 
     332                 :            : fail:
     333                 :          0 :     pa_xfree(r);
     334                 :            : 
     335                 :        338 :     return NULL;
     336                 :            : }
     337                 :            : 
     338                 :        338 : void pa_resampler_free(pa_resampler *r) {
     339         [ -  + ]:        338 :     pa_assert(r);
     340                 :            : 
     341         [ -  + ]:        338 :     if (r->impl_free)
     342                 :          0 :         r->impl_free(r);
     343                 :            : 
     344         [ +  + ]:        338 :     if (r->to_work_format_buf.memblock)
     345                 :        248 :         pa_memblock_unref(r->to_work_format_buf.memblock);
     346         [ -  + ]:        338 :     if (r->remap_buf.memblock)
     347                 :          0 :         pa_memblock_unref(r->remap_buf.memblock);
     348         [ -  + ]:        338 :     if (r->resample_buf.memblock)
     349                 :          0 :         pa_memblock_unref(r->resample_buf.memblock);
     350         [ -  + ]:        338 :     if (r->from_work_format_buf.memblock)
     351                 :          0 :         pa_memblock_unref(r->from_work_format_buf.memblock);
     352                 :            : 
     353                 :        338 :     pa_xfree(r);
     354                 :        338 : }
     355                 :            : 
     356                 :          0 : void pa_resampler_set_input_rate(pa_resampler *r, uint32_t rate) {
     357         [ #  # ]:          0 :     pa_assert(r);
     358         [ #  # ]:          0 :     pa_assert(rate > 0);
     359                 :            : 
     360         [ #  # ]:          0 :     if (r->i_ss.rate == rate)
     361                 :          0 :         return;
     362                 :            : 
     363                 :          0 :     r->i_ss.rate = rate;
     364                 :            : 
     365                 :          0 :     r->impl_update_rates(r);
     366                 :            : }
     367                 :            : 
     368                 :          0 : void pa_resampler_set_output_rate(pa_resampler *r, uint32_t rate) {
     369         [ #  # ]:          0 :     pa_assert(r);
     370         [ #  # ]:          0 :     pa_assert(rate > 0);
     371                 :            : 
     372         [ #  # ]:          0 :     if (r->o_ss.rate == rate)
     373                 :          0 :         return;
     374                 :            : 
     375                 :          0 :     r->o_ss.rate = rate;
     376                 :            : 
     377                 :          0 :     r->impl_update_rates(r);
     378                 :            : }
     379                 :            : 
     380                 :          0 : size_t pa_resampler_request(pa_resampler *r, size_t out_length) {
     381         [ #  # ]:          0 :     pa_assert(r);
     382                 :            : 
     383                 :            :     /* Let's round up here to make it more likely that the caller will get at
     384                 :            :      * least out_length amount of data from pa_resampler_run().
     385                 :            :      *
     386                 :            :      * We don't take the leftover into account here. If we did, then it might
     387                 :            :      * be in theory possible that this function would return 0 and
     388                 :            :      * pa_resampler_run() would also return 0. That could lead to infinite
     389                 :            :      * loops. When the leftover is ignored here, such loops would eventually
     390                 :            :      * terminate, because the leftover would grow each round, finally
     391                 :            :      * surpassing the minimum input threshold of the resampler. */
     392                 :          0 :     return (((((out_length + r->o_fz-1) / r->o_fz) * r->i_ss.rate) + r->o_ss.rate-1) / r->o_ss.rate) * r->i_fz;
     393                 :            : }
     394                 :            : 
     395                 :          0 : size_t pa_resampler_result(pa_resampler *r, size_t in_length) {
     396                 :            :     size_t frames;
     397                 :            : 
     398         [ #  # ]:          0 :     pa_assert(r);
     399                 :            : 
     400                 :            :     /* Let's round up here to ensure that the caller will always allocate big
     401                 :            :      * enough output buffer. */
     402                 :            : 
     403                 :          0 :     frames = (in_length + r->i_fz - 1) / r->i_fz;
     404                 :            : 
     405         [ #  # ]:          0 :     if (r->remap_buf_contains_leftover_data)
     406                 :          0 :         frames += r->remap_buf.length / (r->w_sz * r->o_ss.channels);
     407                 :            : 
     408                 :          0 :     return ((frames * r->o_ss.rate + r->i_ss.rate - 1) / r->i_ss.rate) * r->o_fz;
     409                 :            : }
     410                 :            : 
     411                 :          0 : size_t pa_resampler_max_block_size(pa_resampler *r) {
     412                 :            :     size_t block_size_max;
     413                 :            :     pa_sample_spec max_ss;
     414                 :            :     size_t max_fs;
     415                 :            :     size_t frames;
     416                 :            : 
     417         [ #  # ]:          0 :     pa_assert(r);
     418                 :            : 
     419                 :          0 :     block_size_max = pa_mempool_block_size_max(r->mempool);
     420                 :            : 
     421                 :            :     /* We deduce the "largest" sample spec we're using during the
     422                 :            :      * conversion */
     423                 :          0 :     max_ss.channels = (uint8_t) (PA_MAX(r->i_ss.channels, r->o_ss.channels));
     424                 :            : 
     425                 :            :     /* We silently assume that the format enum is ordered by size */
     426                 :          0 :     max_ss.format = PA_MAX(r->i_ss.format, r->o_ss.format);
     427                 :          0 :     max_ss.format = PA_MAX(max_ss.format, r->work_format);
     428                 :            : 
     429                 :          0 :     max_ss.rate = PA_MAX(r->i_ss.rate, r->o_ss.rate);
     430                 :            : 
     431                 :          0 :     max_fs = pa_frame_size(&max_ss);
     432                 :          0 :     frames = block_size_max / max_fs - EXTRA_FRAMES;
     433                 :            : 
     434         [ #  # ]:          0 :     if (r->remap_buf_contains_leftover_data)
     435                 :          0 :         frames -= r->remap_buf.length / (r->w_sz * r->o_ss.channels);
     436                 :            : 
     437                 :          0 :     return (frames * r->i_ss.rate / max_ss.rate) * r->i_fz;
     438                 :            : }
     439                 :            : 
     440                 :          0 : void pa_resampler_reset(pa_resampler *r) {
     441         [ #  # ]:          0 :     pa_assert(r);
     442                 :            : 
     443         [ #  # ]:          0 :     if (r->impl_reset)
     444                 :          0 :         r->impl_reset(r);
     445                 :            : 
     446                 :          0 :     r->remap_buf_contains_leftover_data = FALSE;
     447                 :          0 : }
     448                 :            : 
     449                 :          0 : pa_resample_method_t pa_resampler_get_method(pa_resampler *r) {
     450         [ #  # ]:          0 :     pa_assert(r);
     451                 :            : 
     452                 :          0 :     return r->method;
     453                 :            : }
     454                 :            : 
     455                 :          0 : const pa_channel_map* pa_resampler_input_channel_map(pa_resampler *r) {
     456         [ #  # ]:          0 :     pa_assert(r);
     457                 :            : 
     458                 :          0 :     return &r->i_cm;
     459                 :            : }
     460                 :            : 
     461                 :          0 : const pa_sample_spec* pa_resampler_input_sample_spec(pa_resampler *r) {
     462         [ #  # ]:          0 :     pa_assert(r);
     463                 :            : 
     464                 :          0 :     return &r->i_ss;
     465                 :            : }
     466                 :            : 
     467                 :          0 : const pa_channel_map* pa_resampler_output_channel_map(pa_resampler *r) {
     468         [ #  # ]:          0 :     pa_assert(r);
     469                 :            : 
     470                 :          0 :     return &r->o_cm;
     471                 :            : }
     472                 :            : 
     473                 :          0 : const pa_sample_spec* pa_resampler_output_sample_spec(pa_resampler *r) {
     474         [ #  # ]:          0 :     pa_assert(r);
     475                 :            : 
     476                 :          0 :     return &r->o_ss;
     477                 :            : }
     478                 :            : 
     479                 :            : static const char * const resample_methods[] = {
     480                 :            :     "src-sinc-best-quality",
     481                 :            :     "src-sinc-medium-quality",
     482                 :            :     "src-sinc-fastest",
     483                 :            :     "src-zero-order-hold",
     484                 :            :     "src-linear",
     485                 :            :     "trivial",
     486                 :            :     "speex-float-0",
     487                 :            :     "speex-float-1",
     488                 :            :     "speex-float-2",
     489                 :            :     "speex-float-3",
     490                 :            :     "speex-float-4",
     491                 :            :     "speex-float-5",
     492                 :            :     "speex-float-6",
     493                 :            :     "speex-float-7",
     494                 :            :     "speex-float-8",
     495                 :            :     "speex-float-9",
     496                 :            :     "speex-float-10",
     497                 :            :     "speex-fixed-0",
     498                 :            :     "speex-fixed-1",
     499                 :            :     "speex-fixed-2",
     500                 :            :     "speex-fixed-3",
     501                 :            :     "speex-fixed-4",
     502                 :            :     "speex-fixed-5",
     503                 :            :     "speex-fixed-6",
     504                 :            :     "speex-fixed-7",
     505                 :            :     "speex-fixed-8",
     506                 :            :     "speex-fixed-9",
     507                 :            :     "speex-fixed-10",
     508                 :            :     "ffmpeg",
     509                 :            :     "auto",
     510                 :            :     "copy",
     511                 :            :     "peaks"
     512                 :            : };
     513                 :            : 
     514                 :        338 : const char *pa_resample_method_to_string(pa_resample_method_t m) {
     515                 :            : 
     516         [ +  - ]:        338 :     if (m < 0 || m >= PA_RESAMPLER_MAX)
     517                 :            :         return NULL;
     518                 :            : 
     519                 :        338 :     return resample_methods[m];
     520                 :            : }
     521                 :            : 
     522                 :        338 : int pa_resample_method_supported(pa_resample_method_t m) {
     523                 :            : 
     524         [ +  - ]:        338 :     if (m < 0 || m >= PA_RESAMPLER_MAX)
     525                 :            :         return 0;
     526                 :            : 
     527                 :            : #ifndef HAVE_LIBSAMPLERATE
     528                 :            :     if (m <= PA_RESAMPLER_SRC_LINEAR)
     529                 :            :         return 0;
     530                 :            : #endif
     531                 :            : 
     532                 :            : #ifndef HAVE_SPEEX
     533                 :            :     if (m >= PA_RESAMPLER_SPEEX_FLOAT_BASE && m <= PA_RESAMPLER_SPEEX_FLOAT_MAX)
     534                 :            :         return 0;
     535                 :            :     if (m >= PA_RESAMPLER_SPEEX_FIXED_BASE && m <= PA_RESAMPLER_SPEEX_FIXED_MAX)
     536                 :            :         return 0;
     537                 :            : #endif
     538                 :            : 
     539                 :        338 :     return 1;
     540                 :            : }
     541                 :            : 
     542                 :          0 : pa_resample_method_t pa_parse_resample_method(const char *string) {
     543                 :            :     pa_resample_method_t m;
     544                 :            : 
     545         [ #  # ]:          0 :     pa_assert(string);
     546                 :            : 
     547         [ #  # ]:          0 :     for (m = 0; m < PA_RESAMPLER_MAX; m++)
     548         [ #  # ]:          0 :         if (pa_streq(string, resample_methods[m]))
     549                 :            :             return m;
     550                 :            : 
     551         [ #  # ]:          0 :     if (pa_streq(string, "speex-fixed"))
     552                 :            :         return PA_RESAMPLER_SPEEX_FIXED_BASE + 3;
     553                 :            : 
     554         [ #  # ]:          0 :     if (pa_streq(string, "speex-float"))
     555                 :            :         return PA_RESAMPLER_SPEEX_FLOAT_BASE + 3;
     556                 :            : 
     557                 :          0 :     return PA_RESAMPLER_INVALID;
     558                 :            : }
     559                 :            : 
     560                 :          0 : static pa_bool_t on_left(pa_channel_position_t p) {
     561                 :            : 
     562                 :          0 :     return
     563                 :          0 :         p == PA_CHANNEL_POSITION_FRONT_LEFT ||
     564                 :          0 :         p == PA_CHANNEL_POSITION_REAR_LEFT ||
     565         [ #  # ]:          0 :         p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
     566                 :          0 :         p == PA_CHANNEL_POSITION_SIDE_LEFT ||
     567 [ #  # ][ #  # ]:          0 :         p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
     568                 :          0 :         p == PA_CHANNEL_POSITION_TOP_REAR_LEFT;
     569                 :            : }
     570                 :            : 
     571                 :          0 : static pa_bool_t on_right(pa_channel_position_t p) {
     572                 :            : 
     573                 :          0 :     return
     574                 :          0 :         p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
     575                 :          0 :         p == PA_CHANNEL_POSITION_REAR_RIGHT ||
     576         [ #  # ]:          0 :         p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER ||
     577                 :          0 :         p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
     578 [ #  # ][ #  # ]:          0 :         p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
     579                 :          0 :         p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT;
     580                 :            : }
     581                 :            : 
     582                 :            : static pa_bool_t on_center(pa_channel_position_t p) {
     583                 :            : 
     584                 :          0 :     return
     585                 :          0 :         p == PA_CHANNEL_POSITION_FRONT_CENTER ||
     586                 :          0 :         p == PA_CHANNEL_POSITION_REAR_CENTER ||
     587                 :          0 :         p == PA_CHANNEL_POSITION_TOP_CENTER ||
     588 [ #  # ][ #  # ]:          0 :         p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER ||
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     589                 :          0 :         p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
     590                 :            : }
     591                 :            : 
     592                 :            : static pa_bool_t on_lfe(pa_channel_position_t p) {
     593                 :            :     return
     594                 :            :         p == PA_CHANNEL_POSITION_LFE;
     595                 :            : }
     596                 :            : 
     597                 :            : static pa_bool_t on_front(pa_channel_position_t p) {
     598                 :          0 :     return
     599                 :            :         p == PA_CHANNEL_POSITION_FRONT_LEFT ||
     600                 :          0 :         p == PA_CHANNEL_POSITION_FRONT_RIGHT ||
     601                 :          0 :         p == PA_CHANNEL_POSITION_FRONT_CENTER ||
     602                 :          0 :         p == PA_CHANNEL_POSITION_TOP_FRONT_LEFT ||
     603         [ #  # ]:          0 :         p == PA_CHANNEL_POSITION_TOP_FRONT_RIGHT ||
     604                 :          0 :         p == PA_CHANNEL_POSITION_TOP_FRONT_CENTER ||
     605 [ #  # ][ #  # ]:          0 :         p == PA_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER ||
     606                 :          0 :         p == PA_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER;
     607                 :            : }
     608                 :            : 
     609                 :            : static pa_bool_t on_rear(pa_channel_position_t p) {
     610                 :          0 :     return
     611                 :            :         p == PA_CHANNEL_POSITION_REAR_LEFT ||
     612                 :          0 :         p == PA_CHANNEL_POSITION_REAR_RIGHT ||
     613                 :          0 :         p == PA_CHANNEL_POSITION_REAR_CENTER ||
     614                 :          0 :         p == PA_CHANNEL_POSITION_TOP_REAR_LEFT ||
     615 [ #  # ][ #  # ]:          0 :         p == PA_CHANNEL_POSITION_TOP_REAR_RIGHT ||
     616                 :          0 :         p == PA_CHANNEL_POSITION_TOP_REAR_CENTER;
     617                 :            : }
     618                 :            : 
     619                 :            : static pa_bool_t on_side(pa_channel_position_t p) {
     620                 :          0 :     return
     621                 :          0 :         p == PA_CHANNEL_POSITION_SIDE_LEFT ||
     622                 :          0 :         p == PA_CHANNEL_POSITION_SIDE_RIGHT ||
     623                 :          0 :         p == PA_CHANNEL_POSITION_TOP_CENTER;
     624                 :            : }
     625                 :            : 
     626                 :            : enum {
     627                 :            :     ON_FRONT,
     628                 :            :     ON_REAR,
     629                 :            :     ON_SIDE,
     630                 :            :     ON_OTHER
     631                 :            : };
     632                 :            : 
     633                 :          0 : static int front_rear_side(pa_channel_position_t p) {
     634         [ #  # ]:          0 :     if (on_front(p))
     635                 :            :         return ON_FRONT;
     636         [ #  # ]:          0 :     if (on_rear(p))
     637                 :            :         return ON_REAR;
     638         [ #  # ]:          0 :     if (on_side(p))
     639                 :            :         return ON_SIDE;
     640                 :          0 :     return ON_OTHER;
     641                 :            : }
     642                 :            : 
     643                 :        338 : static void calc_map_table(pa_resampler *r) {
     644                 :            :     unsigned oc, ic;
     645                 :            :     unsigned n_oc, n_ic;
     646                 :            :     pa_bool_t ic_connected[PA_CHANNELS_MAX];
     647                 :            :     pa_bool_t remix;
     648                 :            :     pa_strbuf *s;
     649                 :            :     char *t;
     650                 :            :     pa_remap_t *m;
     651                 :            : 
     652         [ -  + ]:        338 :     pa_assert(r);
     653                 :            : 
     654 [ +  - ][ +  - ]:        338 :     if (!(r->map_required = (r->i_ss.channels != r->o_ss.channels || (!(r->flags & PA_RESAMPLER_NO_REMAP) && !pa_channel_map_equal(&r->i_cm, &r->o_cm)))))
         [ +  - ][ -  + ]
     655                 :        338 :         return;
     656                 :            : 
     657                 :          0 :     m = &r->remap;
     658                 :            : 
     659                 :          0 :     n_oc = r->o_ss.channels;
     660                 :          0 :     n_ic = r->i_ss.channels;
     661                 :            : 
     662                 :          0 :     memset(m->map_table_f, 0, sizeof(m->map_table_f));
     663                 :          0 :     memset(m->map_table_i, 0, sizeof(m->map_table_i));
     664                 :            : 
     665                 :            :     memset(ic_connected, 0, sizeof(ic_connected));
     666                 :          0 :     remix = (r->flags & (PA_RESAMPLER_NO_REMAP|PA_RESAMPLER_NO_REMIX)) == 0;
     667                 :            : 
     668         [ #  # ]:          0 :     for (oc = 0; oc < n_oc; oc++) {
     669                 :          0 :         pa_bool_t oc_connected = FALSE;
     670                 :          0 :         pa_channel_position_t b = r->o_cm.map[oc];
     671                 :            : 
     672         [ #  # ]:          0 :         for (ic = 0; ic < n_ic; ic++) {
     673                 :          0 :             pa_channel_position_t a = r->i_cm.map[ic];
     674                 :            : 
     675         [ #  # ]:          0 :             if (r->flags & PA_RESAMPLER_NO_REMAP) {
     676                 :            :                 /* We shall not do any remapping. Hence, just check by index */
     677                 :            : 
     678         [ #  # ]:          0 :                 if (ic == oc)
     679                 :          0 :                     m->map_table_f[oc][ic] = 1.0;
     680                 :            : 
     681                 :          0 :                 continue;
     682                 :            :             }
     683                 :            : 
     684         [ #  # ]:          0 :             if (r->flags & PA_RESAMPLER_NO_REMIX) {
     685                 :            :                 /* We shall not do any remixing. Hence, just check by name */
     686                 :            : 
     687         [ #  # ]:          0 :                 if (a == b)
     688                 :          0 :                     m->map_table_f[oc][ic] = 1.0;
     689                 :            : 
     690                 :          0 :                 continue;
     691                 :            :             }
     692                 :            : 
     693         [ #  # ]:          0 :             pa_assert(remix);
     694                 :            : 
     695                 :            :             /* OK, we shall do the full monty: upmixing and
     696                 :            :              * downmixing. Our algorithm is relatively simple, does
     697                 :            :              * not do spacialization, delay elements or apply lowpass
     698                 :            :              * filters for LFE. Patches are always welcome,
     699                 :            :              * though. Oh, and it doesn't do any matrix
     700                 :            :              * decoding. (Which probably wouldn't make any sense
     701                 :            :              * anyway.)
     702                 :            :              *
     703                 :            :              * This code is not idempotent: downmixing an upmixed
     704                 :            :              * stereo stream is not identical to the original. The
     705                 :            :              * volume will not match, and the two channels will be a
     706                 :            :              * linear combination of both.
     707                 :            :              *
     708                 :            :              * This is loosely based on random suggestions found on the
     709                 :            :              * Internet, such as this:
     710                 :            :              * http://www.halfgaar.net/surround-sound-in-linux and the
     711                 :            :              * alsa upmix plugin.
     712                 :            :              *
     713                 :            :              * The algorithm works basically like this:
     714                 :            :              *
     715                 :            :              * 1) Connect all channels with matching names.
     716                 :            :              *
     717                 :            :              * 2) Mono Handling:
     718                 :            :              *    S:Mono: Copy into all D:channels
     719                 :            :              *    D:Mono: Copy in all S:channels
     720                 :            :              *
     721                 :            :              * 3) Mix D:Left, D:Right:
     722                 :            :              *    D:Left: If not connected, avg all S:Left
     723                 :            :              *    D:Right: If not connected, avg all S:Right
     724                 :            :              *
     725                 :            :              * 4) Mix D:Center
     726                 :            :              *       If not connected, avg all S:Center
     727                 :            :              *       If still not connected, avg all S:Left, S:Right
     728                 :            :              *
     729                 :            :              * 5) Mix D:LFE
     730                 :            :              *       If not connected, avg all S:*
     731                 :            :              *
     732                 :            :              * 6) Make sure S:Left/S:Right is used: S:Left/S:Right: If
     733                 :            :              *    not connected, mix into all D:left and all D:right
     734                 :            :              *    channels. Gain is 0.1, the current left and right
     735                 :            :              *    should be multiplied by 0.9.
     736                 :            :              *
     737                 :            :              * 7) Make sure S:Center, S:LFE is used:
     738                 :            :              *
     739                 :            :              *    S:Center, S:LFE: If not connected, mix into all
     740                 :            :              *    D:left, all D:right, all D:center channels, gain is
     741                 :            :              *    0.375. The current (as result of 1..6) factors
     742                 :            :              *    should be multiplied by 0.75. (Alt. suggestion: 0.25
     743                 :            :              *    vs. 0.5) If C-front is only mixed into
     744                 :            :              *    L-front/R-front if available, otherwise into all L/R
     745                 :            :              *    channels. Similarly for C-rear.
     746                 :            :              *
     747                 :            :              * S: and D: shall relate to the source resp. destination channels.
     748                 :            :              *
     749                 :            :              * Rationale: 1, 2 are probably obvious. For 3: this
     750                 :            :              * copies front to rear if needed. For 4: we try to find
     751                 :            :              * some suitable C source for C, if we don't find any, we
     752                 :            :              * avg L and R. For 5: LFE is mixed from all channels. For
     753                 :            :              * 6: the rear channels should not be dropped entirely,
     754                 :            :              * however have only minimal impact. For 7: movies usually
     755                 :            :              * encode speech on the center channel. Thus we have to
     756                 :            :              * make sure this channel is distributed to L and R if not
     757                 :            :              * available in the output. Also, LFE is used to achieve a
     758                 :            :              * greater dynamic range, and thus we should try to do our
     759                 :            :              * best to pass it to L+R.
     760                 :            :              */
     761                 :            : 
     762 [ #  # ][ #  # ]:          0 :             if (a == b || a == PA_CHANNEL_POSITION_MONO || b == PA_CHANNEL_POSITION_MONO) {
     763                 :          0 :                 m->map_table_f[oc][ic] = 1.0;
     764                 :            : 
     765                 :          0 :                 oc_connected = TRUE;
     766                 :          0 :                 ic_connected[ic] = TRUE;
     767                 :            :             }
     768                 :            :         }
     769                 :            : 
     770 [ #  # ][ #  # ]:          0 :         if (!oc_connected && remix) {
     771                 :            :             /* OK, we shall remix */
     772                 :            : 
     773                 :            :             /* Try to find matching input ports for this output port */
     774                 :            : 
     775         [ #  # ]:          0 :             if (on_left(b)) {
     776                 :            :                 unsigned n = 0;
     777                 :            : 
     778                 :            :                 /* We are not connected and on the left side, let's
     779                 :            :                  * average all left side input channels. */
     780                 :            : 
     781         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++)
     782         [ #  # ]:          0 :                     if (on_left(r->i_cm.map[ic]))
     783                 :          0 :                         n++;
     784                 :            : 
     785         [ #  # ]:          0 :                 if (n > 0)
     786         [ #  # ]:          0 :                     for (ic = 0; ic < n_ic; ic++)
     787         [ #  # ]:          0 :                         if (on_left(r->i_cm.map[ic])) {
     788                 :          0 :                             m->map_table_f[oc][ic] = 1.0f / (float) n;
     789                 :          0 :                             ic_connected[ic] = TRUE;
     790                 :            :                         }
     791                 :            : 
     792                 :            :                 /* We ignore the case where there is no left input
     793                 :            :                  * channel. Something is really wrong in this case
     794                 :            :                  * anyway. */
     795                 :            : 
     796         [ #  # ]:          0 :             } else if (on_right(b)) {
     797                 :            :                 unsigned n = 0;
     798                 :            : 
     799                 :            :                 /* We are not connected and on the right side, let's
     800                 :            :                  * average all right side input channels. */
     801                 :            : 
     802         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++)
     803         [ #  # ]:          0 :                     if (on_right(r->i_cm.map[ic]))
     804                 :          0 :                         n++;
     805                 :            : 
     806         [ #  # ]:          0 :                 if (n > 0)
     807         [ #  # ]:          0 :                     for (ic = 0; ic < n_ic; ic++)
     808         [ #  # ]:          0 :                         if (on_right(r->i_cm.map[ic])) {
     809                 :          0 :                             m->map_table_f[oc][ic] = 1.0f / (float) n;
     810                 :          0 :                             ic_connected[ic] = TRUE;
     811                 :            :                         }
     812                 :            : 
     813                 :            :                 /* We ignore the case where there is no right input
     814                 :            :                  * channel. Something is really wrong in this case
     815                 :            :                  * anyway. */
     816                 :            : 
     817         [ #  # ]:          0 :             } else if (on_center(b)) {
     818                 :            :                 unsigned n = 0;
     819                 :            : 
     820                 :            :                 /* We are not connected and at the center. Let's
     821                 :            :                  * average all center input channels. */
     822                 :            : 
     823         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++)
     824         [ #  # ]:          0 :                     if (on_center(r->i_cm.map[ic]))
     825                 :          0 :                         n++;
     826                 :            : 
     827         [ #  # ]:          0 :                 if (n > 0) {
     828         [ #  # ]:          0 :                     for (ic = 0; ic < n_ic; ic++)
     829         [ #  # ]:          0 :                         if (on_center(r->i_cm.map[ic])) {
     830                 :          0 :                             m->map_table_f[oc][ic] = 1.0f / (float) n;
     831                 :          0 :                             ic_connected[ic] = TRUE;
     832                 :            :                         }
     833                 :            :                 } else {
     834                 :            : 
     835                 :            :                     /* Hmm, no center channel around, let's synthesize
     836                 :            :                      * it by mixing L and R.*/
     837                 :            : 
     838                 :            :                     n = 0;
     839                 :            : 
     840         [ #  # ]:          0 :                     for (ic = 0; ic < n_ic; ic++)
     841 [ #  # ][ #  # ]:          0 :                         if (on_left(r->i_cm.map[ic]) || on_right(r->i_cm.map[ic]))
     842                 :          0 :                             n++;
     843                 :            : 
     844         [ #  # ]:          0 :                     if (n > 0)
     845         [ #  # ]:          0 :                         for (ic = 0; ic < n_ic; ic++)
     846 [ #  # ][ #  # ]:          0 :                             if (on_left(r->i_cm.map[ic]) || on_right(r->i_cm.map[ic])) {
     847                 :          0 :                                 m->map_table_f[oc][ic] = 1.0f / (float) n;
     848                 :          0 :                                 ic_connected[ic] = TRUE;
     849                 :            :                             }
     850                 :            : 
     851                 :            :                     /* We ignore the case where there is not even a
     852                 :            :                      * left or right input channel. Something is
     853                 :            :                      * really wrong in this case anyway. */
     854                 :            :                 }
     855                 :            : 
     856         [ #  # ]:          0 :             } else if (on_lfe(b)) {
     857                 :            : 
     858                 :            :                 /* We are not connected and an LFE. Let's average all
     859                 :            :                  * channels for LFE. */
     860                 :            : 
     861         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++) {
     862                 :            : 
     863         [ #  # ]:          0 :                     if (!(r->flags & PA_RESAMPLER_NO_LFE))
     864                 :          0 :                         m->map_table_f[oc][ic] = 1.0f / (float) n_ic;
     865                 :            :                     else
     866                 :          0 :                         m->map_table_f[oc][ic] = 0;
     867                 :            : 
     868                 :            :                     /* Please note that a channel connected to LFE
     869                 :            :                      * doesn't really count as connected. */
     870                 :            :                 }
     871                 :            :             }
     872                 :            :         }
     873                 :            :     }
     874                 :            : 
     875         [ #  # ]:          0 :     if (remix) {
     876                 :            :         unsigned
     877                 :            :             ic_unconnected_left = 0,
     878                 :            :             ic_unconnected_right = 0,
     879                 :            :             ic_unconnected_center = 0,
     880                 :            :             ic_unconnected_lfe = 0;
     881                 :            : 
     882         [ #  # ]:          0 :         for (ic = 0; ic < n_ic; ic++) {
     883                 :          0 :             pa_channel_position_t a = r->i_cm.map[ic];
     884                 :            : 
     885         [ #  # ]:          0 :             if (ic_connected[ic])
     886                 :          0 :                 continue;
     887                 :            : 
     888         [ #  # ]:          0 :             if (on_left(a))
     889                 :          0 :                 ic_unconnected_left++;
     890         [ #  # ]:          0 :             else if (on_right(a))
     891                 :          0 :                 ic_unconnected_right++;
     892         [ #  # ]:          0 :             else if (on_center(a))
     893                 :          0 :                 ic_unconnected_center++;
     894         [ #  # ]:          0 :             else if (on_lfe(a))
     895                 :          0 :                 ic_unconnected_lfe++;
     896                 :            :         }
     897                 :            : 
     898         [ #  # ]:          0 :         if (ic_unconnected_left > 0) {
     899                 :            : 
     900                 :            :             /* OK, so there are unconnected input channels on the
     901                 :            :              * left. Let's multiply all already connected channels on
     902                 :            :              * the left side by .9 and add in our averaged unconnected
     903                 :            :              * channels multiplied by .1 */
     904                 :            : 
     905         [ #  # ]:          0 :             for (oc = 0; oc < n_oc; oc++) {
     906                 :            : 
     907         [ #  # ]:          0 :                 if (!on_left(r->o_cm.map[oc]))
     908                 :          0 :                     continue;
     909                 :            : 
     910         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++) {
     911                 :            : 
     912         [ #  # ]:          0 :                     if (ic_connected[ic]) {
     913                 :          0 :                         m->map_table_f[oc][ic] *= .9f;
     914                 :          0 :                         continue;
     915                 :            :                     }
     916                 :            : 
     917         [ #  # ]:          0 :                     if (on_left(r->i_cm.map[ic]))
     918                 :          0 :                         m->map_table_f[oc][ic] = .1f / (float) ic_unconnected_left;
     919                 :            :                 }
     920                 :            :             }
     921                 :            :         }
     922                 :            : 
     923         [ #  # ]:          0 :         if (ic_unconnected_right > 0) {
     924                 :            : 
     925                 :            :             /* OK, so there are unconnected input channels on the
     926                 :            :              * right. Let's multiply all already connected channels on
     927                 :            :              * the right side by .9 and add in our averaged unconnected
     928                 :            :              * channels multiplied by .1 */
     929                 :            : 
     930         [ #  # ]:          0 :             for (oc = 0; oc < n_oc; oc++) {
     931                 :            : 
     932         [ #  # ]:          0 :                 if (!on_right(r->o_cm.map[oc]))
     933                 :          0 :                     continue;
     934                 :            : 
     935         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++) {
     936                 :            : 
     937         [ #  # ]:          0 :                     if (ic_connected[ic]) {
     938                 :          0 :                         m->map_table_f[oc][ic] *= .9f;
     939                 :          0 :                         continue;
     940                 :            :                     }
     941                 :            : 
     942         [ #  # ]:          0 :                     if (on_right(r->i_cm.map[ic]))
     943                 :          0 :                         m->map_table_f[oc][ic] = .1f / (float) ic_unconnected_right;
     944                 :            :                 }
     945                 :            :             }
     946                 :            :         }
     947                 :            : 
     948         [ #  # ]:          0 :         if (ic_unconnected_center > 0) {
     949                 :            :             pa_bool_t mixed_in = FALSE;
     950                 :            : 
     951                 :            :             /* OK, so there are unconnected input channels on the
     952                 :            :              * center. Let's multiply all already connected channels on
     953                 :            :              * the center side by .9 and add in our averaged unconnected
     954                 :            :              * channels multiplied by .1 */
     955                 :            : 
     956         [ #  # ]:          0 :             for (oc = 0; oc < n_oc; oc++) {
     957                 :            : 
     958         [ #  # ]:          0 :                 if (!on_center(r->o_cm.map[oc]))
     959                 :          0 :                     continue;
     960                 :            : 
     961         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++) {
     962                 :            : 
     963         [ #  # ]:          0 :                     if (ic_connected[ic]) {
     964                 :          0 :                         m->map_table_f[oc][ic] *= .9f;
     965                 :          0 :                         continue;
     966                 :            :                     }
     967                 :            : 
     968         [ #  # ]:          0 :                     if (on_center(r->i_cm.map[ic])) {
     969                 :          0 :                         m->map_table_f[oc][ic] = .1f / (float) ic_unconnected_center;
     970                 :          0 :                         mixed_in = TRUE;
     971                 :            :                     }
     972                 :            :                 }
     973                 :            :             }
     974                 :            : 
     975         [ #  # ]:          0 :             if (!mixed_in) {
     976                 :            :                 unsigned ncenter[PA_CHANNELS_MAX];
     977                 :            :                 pa_bool_t found_frs[PA_CHANNELS_MAX];
     978                 :            : 
     979                 :            :                 memset(ncenter, 0, sizeof(ncenter));
     980                 :            :                 memset(found_frs, 0, sizeof(found_frs));
     981                 :            : 
     982                 :            :                 /* Hmm, as it appears there was no center channel we
     983                 :            :                    could mix our center channel in. In this case, mix
     984                 :            :                    it into left and right. Using .375 and 0.75 as
     985                 :            :                    factors. */
     986                 :            : 
     987         [ #  # ]:          0 :                 for (ic = 0; ic < n_ic; ic++) {
     988                 :            : 
     989         [ #  # ]:          0 :                     if (ic_connected[ic])
     990                 :          0 :                         continue;
     991                 :            : 
     992         [ #  # ]:          0 :                     if (!on_center(r->i_cm.map[ic]))
     993                 :          0 :                         continue;
     994                 :            : 
     995         [ #  # ]:          0 :                     for (oc = 0; oc < n_oc; oc++) {
     996                 :            : 
     997 [ #  # ][ #  # ]:          0 :                         if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc]))
     998                 :          0 :                             continue;
     999                 :            : 
    1000         [ #  # ]:          0 :                         if (front_rear_side(r->i_cm.map[ic]) == front_rear_side(r->o_cm.map[oc])) {
    1001                 :          0 :                             found_frs[ic] = TRUE;
    1002                 :          0 :                             break;
    1003                 :            :                         }
    1004                 :            :                     }
    1005                 :            : 
    1006         [ #  # ]:          0 :                     for (oc = 0; oc < n_oc; oc++) {
    1007                 :            : 
    1008 [ #  # ][ #  # ]:          0 :                         if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc]))
    1009                 :          0 :                             continue;
    1010                 :            : 
    1011 [ #  # ][ #  # ]:          0 :                         if (!found_frs[ic] || front_rear_side(r->i_cm.map[ic]) == front_rear_side(r->o_cm.map[oc]))
    1012                 :          0 :                             ncenter[oc]++;
    1013                 :            :                     }
    1014                 :            :                 }
    1015                 :            : 
    1016         [ #  # ]:          0 :                 for (oc = 0; oc < n_oc; oc++) {
    1017                 :            : 
    1018 [ #  # ][ #  # ]:          0 :                     if (!on_left(r->o_cm.map[oc]) && !on_right(r->o_cm.map[oc]))
    1019                 :          0 :                         continue;
    1020                 :            : 
    1021         [ #  # ]:          0 :                     if (ncenter[oc] <= 0)
    1022                 :          0 :                         continue;
    1023                 :            : 
    1024         [ #  # ]:          0 :                     for (ic = 0; ic < n_ic; ic++) {
    1025                 :            : 
    1026         [ #  # ]:          0 :                         if (ic_connected[ic]) {
    1027                 :          0 :                             m->map_table_f[oc][ic] *= .75f;
    1028                 :          0 :                             continue;
    1029                 :            :                         }
    1030                 :            : 
    1031         [ #  # ]:          0 :                         if (!on_center(r->i_cm.map[ic]))
    1032                 :          0 :                             continue;
    1033                 :            : 
    1034 [ #  # ][ #  # ]:          0 :                         if (!found_frs[ic] || front_rear_side(r->i_cm.map[ic]) == front_rear_side(r->o_cm.map[oc]))
    1035                 :          0 :                             m->map_table_f[oc][ic] = .375f / (float) ncenter[oc];
    1036                 :            :                     }
    1037                 :            :                 }
    1038                 :            :             }
    1039                 :            :         }
    1040                 :            : 
    1041 [ #  # ][ #  # ]:          0 :         if (ic_unconnected_lfe > 0 && !(r->flags & PA_RESAMPLER_NO_LFE)) {
    1042                 :            : 
    1043                 :            :             /* OK, so there is an unconnected LFE channel. Let's mix
    1044                 :            :              * it into all channels, with factor 0.375 */
    1045                 :            : 
    1046         [ #  # ]:          0 :             for (ic = 0; ic < n_ic; ic++) {
    1047                 :            : 
    1048         [ #  # ]:          0 :                 if (!on_lfe(r->i_cm.map[ic]))
    1049                 :          0 :                     continue;
    1050                 :            : 
    1051         [ #  # ]:          0 :                 for (oc = 0; oc < n_oc; oc++)
    1052                 :          0 :                     m->map_table_f[oc][ic] = 0.375f / (float) ic_unconnected_lfe;
    1053                 :            :             }
    1054                 :            :         }
    1055                 :            :     }
    1056                 :            :     /* make an 16:16 int version of the matrix */
    1057         [ #  # ]:          0 :     for (oc = 0; oc < n_oc; oc++)
    1058         [ #  # ]:          0 :         for (ic = 0; ic < n_ic; ic++)
    1059                 :          0 :             m->map_table_i[oc][ic] = (int32_t) (m->map_table_f[oc][ic] * 0x10000);
    1060                 :            : 
    1061                 :          0 :     s = pa_strbuf_new();
    1062                 :            : 
    1063                 :          0 :     pa_strbuf_printf(s, "     ");
    1064         [ #  # ]:          0 :     for (ic = 0; ic < n_ic; ic++)
    1065                 :          0 :         pa_strbuf_printf(s, "  I%02u ", ic);
    1066                 :          0 :     pa_strbuf_puts(s, "\n    +");
    1067                 :            : 
    1068         [ #  # ]:          0 :     for (ic = 0; ic < n_ic; ic++)
    1069                 :          0 :         pa_strbuf_printf(s, "------");
    1070                 :          0 :     pa_strbuf_puts(s, "\n");
    1071                 :            : 
    1072         [ #  # ]:          0 :     for (oc = 0; oc < n_oc; oc++) {
    1073                 :          0 :         pa_strbuf_printf(s, "O%02u |", oc);
    1074                 :            : 
    1075         [ #  # ]:          0 :         for (ic = 0; ic < n_ic; ic++)
    1076                 :          0 :             pa_strbuf_printf(s, " %1.3f", m->map_table_f[oc][ic]);
    1077                 :            : 
    1078                 :          0 :         pa_strbuf_puts(s, "\n");
    1079                 :            :     }
    1080                 :            : 
    1081                 :          0 :     pa_log_debug("Channel matrix:\n%s", t = pa_strbuf_tostring_free(s));
    1082                 :          0 :     pa_xfree(t);
    1083                 :            : 
    1084                 :            :     /* initialize the remapping function */
    1085                 :          0 :     pa_init_remap(m);
    1086                 :            : }
    1087                 :            : 
    1088                 :        338 : static pa_memchunk* convert_to_work_format(pa_resampler *r, pa_memchunk *input) {
    1089                 :            :     unsigned n_samples;
    1090                 :            :     void *src, *dst;
    1091                 :            : 
    1092         [ -  + ]:        338 :     pa_assert(r);
    1093         [ -  + ]:        338 :     pa_assert(input);
    1094         [ -  + ]:        338 :     pa_assert(input->memblock);
    1095                 :            : 
    1096                 :            :     /* Convert the incoming sample into the work sample format and place them
    1097                 :            :      * in to_work_format_buf. */
    1098                 :            : 
    1099 [ +  + ][ +  - ]:        338 :     if (!r->to_work_format_func || !input->length)
    1100                 :            :         return input;
    1101                 :            : 
    1102                 :        280 :     n_samples = (unsigned) ((input->length / r->i_fz) * r->i_ss.channels);
    1103                 :            : 
    1104                 :        280 :     r->to_work_format_buf.index = 0;
    1105                 :        280 :     r->to_work_format_buf.length = r->w_sz * n_samples;
    1106                 :            : 
    1107 [ -  + ][ #  # ]:        280 :     if (!r->to_work_format_buf.memblock || r->to_work_format_buf_samples < n_samples) {
    1108         [ -  + ]:        280 :         if (r->to_work_format_buf.memblock)
    1109                 :          0 :             pa_memblock_unref(r->to_work_format_buf.memblock);
    1110                 :            : 
    1111                 :        280 :         r->to_work_format_buf_samples = n_samples;
    1112                 :        280 :         r->to_work_format_buf.memblock = pa_memblock_new(r->mempool, r->to_work_format_buf.length);
    1113                 :            :     }
    1114                 :            : 
    1115                 :        280 :     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
    1116                 :        280 :     dst = (uint8_t*) pa_memblock_acquire(r->to_work_format_buf.memblock);
    1117                 :            : 
    1118                 :        280 :     r->to_work_format_func(n_samples, src, dst);
    1119                 :            : 
    1120                 :        280 :     pa_memblock_release(input->memblock);
    1121                 :        280 :     pa_memblock_release(r->to_work_format_buf.memblock);
    1122                 :            : 
    1123                 :        338 :     return &r->to_work_format_buf;
    1124                 :            : }
    1125                 :            : 
    1126                 :        338 : static pa_memchunk *remap_channels(pa_resampler *r, pa_memchunk *input) {
    1127                 :            :     unsigned in_n_samples, out_n_samples, in_n_frames, out_n_frames;
    1128                 :            :     void *src, *dst;
    1129                 :        338 :     size_t leftover_length = 0;
    1130                 :            :     pa_bool_t have_leftover;
    1131                 :            : 
    1132         [ -  + ]:        338 :     pa_assert(r);
    1133         [ -  + ]:        338 :     pa_assert(input);
    1134         [ -  + ]:        338 :     pa_assert(input->memblock);
    1135                 :            : 
    1136                 :            :     /* Remap channels and place the result in remap_buf. There may be leftover
    1137                 :            :      * data in the beginning of remap_buf. The leftover data is already
    1138                 :            :      * remapped, so it's not part of the input, it's part of the output. */
    1139                 :            : 
    1140                 :        338 :     have_leftover = r->remap_buf_contains_leftover_data;
    1141                 :        338 :     r->remap_buf_contains_leftover_data = FALSE;
    1142                 :            : 
    1143 [ +  - ][ -  + ]:        338 :     if (!have_leftover && (!r->map_required || input->length <= 0))
                 [ #  # ]
    1144                 :            :         return input;
    1145         [ #  # ]:          0 :     else if (input->length <= 0)
    1146                 :          0 :         return &r->remap_buf;
    1147                 :            : 
    1148                 :          0 :     in_n_samples = (unsigned) (input->length / r->w_sz);
    1149                 :          0 :     in_n_frames = out_n_frames = in_n_samples / r->i_ss.channels;
    1150                 :            : 
    1151         [ #  # ]:          0 :     if (have_leftover) {
    1152                 :          0 :         leftover_length = r->remap_buf.length;
    1153                 :          0 :         out_n_frames += leftover_length / (r->w_sz * r->o_ss.channels);
    1154                 :            :     }
    1155                 :            : 
    1156                 :          0 :     out_n_samples = out_n_frames * r->o_ss.channels;
    1157                 :          0 :     r->remap_buf.length = out_n_samples * r->w_sz;
    1158                 :            : 
    1159         [ #  # ]:          0 :     if (have_leftover) {
    1160         [ #  # ]:          0 :         if (r->remap_buf_size < r->remap_buf.length) {
    1161                 :          0 :             pa_memblock *new_block = pa_memblock_new(r->mempool, r->remap_buf.length);
    1162                 :            : 
    1163                 :          0 :             src = pa_memblock_acquire(r->remap_buf.memblock);
    1164                 :          0 :             dst = pa_memblock_acquire(new_block);
    1165                 :          0 :             memcpy(dst, src, leftover_length);
    1166                 :          0 :             pa_memblock_release(r->remap_buf.memblock);
    1167                 :          0 :             pa_memblock_release(new_block);
    1168                 :            : 
    1169                 :          0 :             pa_memblock_unref(r->remap_buf.memblock);
    1170                 :          0 :             r->remap_buf.memblock = new_block;
    1171                 :          0 :             r->remap_buf_size = r->remap_buf.length;
    1172                 :            :         }
    1173                 :            : 
    1174                 :            :     } else {
    1175 [ #  # ][ #  # ]:          0 :         if (!r->remap_buf.memblock || r->remap_buf_size < r->remap_buf.length) {
    1176         [ #  # ]:          0 :             if (r->remap_buf.memblock)
    1177                 :          0 :                 pa_memblock_unref(r->remap_buf.memblock);
    1178                 :            : 
    1179                 :          0 :             r->remap_buf_size = r->remap_buf.length;
    1180                 :          0 :             r->remap_buf.memblock = pa_memblock_new(r->mempool, r->remap_buf.length);
    1181                 :            :         }
    1182                 :            :     }
    1183                 :            : 
    1184                 :          0 :     src = (uint8_t *) pa_memblock_acquire(input->memblock) + input->index;
    1185                 :          0 :     dst = (uint8_t *) pa_memblock_acquire(r->remap_buf.memblock) + leftover_length;
    1186                 :            : 
    1187         [ #  # ]:          0 :     if (r->map_required) {
    1188                 :          0 :         pa_remap_t *remap = &r->remap;
    1189                 :            : 
    1190         [ #  # ]:          0 :         pa_assert(remap->do_remap);
    1191                 :          0 :         remap->do_remap(remap, dst, src, in_n_frames);
    1192                 :            : 
    1193                 :            :     } else
    1194                 :          0 :         memcpy(dst, src, input->length);
    1195                 :            : 
    1196                 :          0 :     pa_memblock_release(input->memblock);
    1197                 :          0 :     pa_memblock_release(r->remap_buf.memblock);
    1198                 :            : 
    1199                 :        338 :     return &r->remap_buf;
    1200                 :            : }
    1201                 :            : 
    1202                 :        338 : static pa_memchunk *resample(pa_resampler *r, pa_memchunk *input) {
    1203                 :            :     unsigned in_n_frames, in_n_samples;
    1204                 :            :     unsigned out_n_frames, out_n_samples;
    1205                 :            : 
    1206         [ -  + ]:        338 :     pa_assert(r);
    1207         [ -  + ]:        338 :     pa_assert(input);
    1208                 :            : 
    1209                 :            :     /* Resample the data and place the result in resample_buf. */
    1210                 :            : 
    1211 [ -  + ][ #  # ]:        338 :     if (!r->impl_resample || !input->length)
    1212                 :            :         return input;
    1213                 :            : 
    1214                 :          0 :     in_n_samples = (unsigned) (input->length / r->w_sz);
    1215                 :          0 :     in_n_frames = (unsigned) (in_n_samples / r->o_ss.channels);
    1216                 :            : 
    1217                 :          0 :     out_n_frames = ((in_n_frames*r->o_ss.rate)/r->i_ss.rate)+EXTRA_FRAMES;
    1218                 :          0 :     out_n_samples = out_n_frames * r->o_ss.channels;
    1219                 :            : 
    1220                 :          0 :     r->resample_buf.index = 0;
    1221                 :          0 :     r->resample_buf.length = r->w_sz * out_n_samples;
    1222                 :            : 
    1223 [ #  # ][ #  # ]:          0 :     if (!r->resample_buf.memblock || r->resample_buf_samples < out_n_samples) {
    1224         [ #  # ]:          0 :         if (r->resample_buf.memblock)
    1225                 :          0 :             pa_memblock_unref(r->resample_buf.memblock);
    1226                 :            : 
    1227                 :          0 :         r->resample_buf_samples = out_n_samples;
    1228                 :          0 :         r->resample_buf.memblock = pa_memblock_new(r->mempool, r->resample_buf.length);
    1229                 :            :     }
    1230                 :            : 
    1231                 :          0 :     r->impl_resample(r, input, in_n_frames, &r->resample_buf, &out_n_frames);
    1232                 :          0 :     r->resample_buf.length = out_n_frames * r->w_sz * r->o_ss.channels;
    1233                 :            : 
    1234                 :        338 :     return &r->resample_buf;
    1235                 :            : }
    1236                 :            : 
    1237                 :        338 : static pa_memchunk *convert_from_work_format(pa_resampler *r, pa_memchunk *input) {
    1238                 :            :     unsigned n_samples, n_frames;
    1239                 :            :     void *src, *dst;
    1240                 :            : 
    1241         [ -  + ]:        338 :     pa_assert(r);
    1242         [ -  + ]:        338 :     pa_assert(input);
    1243                 :            : 
    1244                 :            :     /* Convert the data into the correct sample type and place the result in
    1245                 :            :      * from_work_format_buf. */
    1246                 :            : 
    1247 [ +  + ][ +  - ]:        338 :     if (!r->from_work_format_func || !input->length)
    1248                 :            :         return input;
    1249                 :            : 
    1250                 :        280 :     n_samples = (unsigned) (input->length / r->w_sz);
    1251                 :        280 :     n_frames = n_samples / r->o_ss.channels;
    1252                 :            : 
    1253                 :        280 :     r->from_work_format_buf.index = 0;
    1254                 :        280 :     r->from_work_format_buf.length = r->o_fz * n_frames;
    1255                 :            : 
    1256 [ -  + ][ #  # ]:        280 :     if (!r->from_work_format_buf.memblock || r->from_work_format_buf_samples < n_samples) {
    1257         [ -  + ]:        280 :         if (r->from_work_format_buf.memblock)
    1258                 :          0 :             pa_memblock_unref(r->from_work_format_buf.memblock);
    1259                 :            : 
    1260                 :        280 :         r->from_work_format_buf_samples = n_samples;
    1261                 :        280 :         r->from_work_format_buf.memblock = pa_memblock_new(r->mempool, r->from_work_format_buf.length);
    1262                 :            :     }
    1263                 :            : 
    1264                 :        280 :     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
    1265                 :        280 :     dst = pa_memblock_acquire(r->from_work_format_buf.memblock);
    1266                 :        280 :     r->from_work_format_func(n_samples, src, dst);
    1267                 :        280 :     pa_memblock_release(input->memblock);
    1268                 :        280 :     pa_memblock_release(r->from_work_format_buf.memblock);
    1269                 :            : 
    1270                 :        280 :     r->from_work_format_buf.length = r->o_fz * n_frames;
    1271                 :            : 
    1272                 :        338 :     return &r->from_work_format_buf;
    1273                 :            : }
    1274                 :            : 
    1275                 :        338 : void pa_resampler_run(pa_resampler *r, const pa_memchunk *in, pa_memchunk *out) {
    1276                 :            :     pa_memchunk *buf;
    1277                 :            : 
    1278         [ -  + ]:        338 :     pa_assert(r);
    1279         [ -  + ]:        338 :     pa_assert(in);
    1280         [ -  + ]:        338 :     pa_assert(out);
    1281         [ -  + ]:        338 :     pa_assert(in->length);
    1282         [ -  + ]:        338 :     pa_assert(in->memblock);
    1283         [ -  + ]:        338 :     pa_assert(in->length % r->i_fz == 0);
    1284                 :            : 
    1285                 :        338 :     buf = (pa_memchunk*) in;
    1286                 :        338 :     buf = convert_to_work_format(r, buf);
    1287                 :        338 :     buf = remap_channels(r, buf);
    1288                 :        338 :     buf = resample(r, buf);
    1289                 :            : 
    1290         [ +  - ]:        338 :     if (buf->length) {
    1291                 :        338 :         buf = convert_from_work_format(r, buf);
    1292                 :        338 :         *out = *buf;
    1293                 :            : 
    1294         [ +  + ]:        338 :         if (buf == in)
    1295                 :         26 :             pa_memblock_ref(buf->memblock);
    1296                 :            :         else
    1297                 :        312 :             pa_memchunk_reset(buf);
    1298                 :            :     } else
    1299                 :          0 :         pa_memchunk_reset(out);
    1300                 :        338 : }
    1301                 :            : 
    1302                 :          0 : static void save_leftover(pa_resampler *r, void *buf, size_t len) {
    1303                 :            :     void *dst;
    1304                 :            : 
    1305         [ #  # ]:          0 :     pa_assert(r);
    1306         [ #  # ]:          0 :     pa_assert(buf);
    1307         [ #  # ]:          0 :     pa_assert(len > 0);
    1308                 :            : 
    1309                 :            :     /* Store the leftover to remap_buf. */
    1310                 :            : 
    1311                 :          0 :     r->remap_buf.length = len;
    1312                 :            : 
    1313 [ #  # ][ #  # ]:          0 :     if (!r->remap_buf.memblock || r->remap_buf_size < r->remap_buf.length) {
    1314         [ #  # ]:          0 :         if (r->remap_buf.memblock)
    1315                 :          0 :             pa_memblock_unref(r->remap_buf.memblock);
    1316                 :            : 
    1317                 :          0 :         r->remap_buf_size = r->remap_buf.length;
    1318                 :          0 :         r->remap_buf.memblock = pa_memblock_new(r->mempool, r->remap_buf.length);
    1319                 :            :     }
    1320                 :            : 
    1321                 :          0 :     dst = pa_memblock_acquire(r->remap_buf.memblock);
    1322                 :          0 :     memcpy(dst, buf, r->remap_buf.length);
    1323                 :          0 :     pa_memblock_release(r->remap_buf.memblock);
    1324                 :            : 
    1325                 :          0 :     r->remap_buf_contains_leftover_data = TRUE;
    1326                 :          0 : }
    1327                 :            : 
    1328                 :            : /*** libsamplerate based implementation ***/
    1329                 :            : 
    1330                 :            : #ifdef HAVE_LIBSAMPLERATE
    1331                 :          0 : static void libsamplerate_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    1332                 :            :     SRC_DATA data;
    1333                 :            : 
    1334         [ #  # ]:          0 :     pa_assert(r);
    1335         [ #  # ]:          0 :     pa_assert(input);
    1336         [ #  # ]:          0 :     pa_assert(output);
    1337         [ #  # ]:          0 :     pa_assert(out_n_frames);
    1338                 :            : 
    1339                 :            :     memset(&data, 0, sizeof(data));
    1340                 :            : 
    1341                 :          0 :     data.data_in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
    1342                 :          0 :     data.input_frames = (long int) in_n_frames;
    1343                 :            : 
    1344                 :          0 :     data.data_out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
    1345                 :          0 :     data.output_frames = (long int) *out_n_frames;
    1346                 :            : 
    1347                 :          0 :     data.src_ratio = (double) r->o_ss.rate / r->i_ss.rate;
    1348                 :          0 :     data.end_of_input = 0;
    1349                 :            : 
    1350         [ #  # ]:          0 :     pa_assert_se(src_process(r->src.state, &data) == 0);
    1351                 :            : 
    1352         [ #  # ]:          0 :     if (data.input_frames_used < in_n_frames) {
    1353                 :          0 :         void *leftover_data = data.data_in + data.input_frames_used * r->o_ss.channels;
    1354                 :          0 :         size_t leftover_length = (in_n_frames - data.input_frames_used) * sizeof(float) * r->o_ss.channels;
    1355                 :            : 
    1356                 :          0 :         save_leftover(r, leftover_data, leftover_length);
    1357                 :            :     }
    1358                 :            : 
    1359                 :          0 :     pa_memblock_release(input->memblock);
    1360                 :          0 :     pa_memblock_release(output->memblock);
    1361                 :            : 
    1362                 :          0 :     *out_n_frames = (unsigned) data.output_frames_gen;
    1363                 :          0 : }
    1364                 :            : 
    1365                 :          0 : static void libsamplerate_update_rates(pa_resampler *r) {
    1366         [ #  # ]:          0 :     pa_assert(r);
    1367                 :            : 
    1368         [ #  # ]:          0 :     pa_assert_se(src_set_ratio(r->src.state, (double) r->o_ss.rate / r->i_ss.rate) == 0);
    1369                 :          0 : }
    1370                 :            : 
    1371                 :          0 : static void libsamplerate_reset(pa_resampler *r) {
    1372         [ #  # ]:          0 :     pa_assert(r);
    1373                 :            : 
    1374         [ #  # ]:          0 :     pa_assert_se(src_reset(r->src.state) == 0);
    1375                 :          0 : }
    1376                 :            : 
    1377                 :          0 : static void libsamplerate_free(pa_resampler *r) {
    1378         [ #  # ]:          0 :     pa_assert(r);
    1379                 :            : 
    1380         [ #  # ]:          0 :     if (r->src.state)
    1381                 :          0 :         src_delete(r->src.state);
    1382                 :          0 : }
    1383                 :            : 
    1384                 :          0 : static int libsamplerate_init(pa_resampler *r) {
    1385                 :            :     int err;
    1386                 :            : 
    1387         [ #  # ]:          0 :     pa_assert(r);
    1388                 :            : 
    1389         [ #  # ]:          0 :     if (!(r->src.state = src_new(r->method, r->o_ss.channels, &err)))
    1390                 :            :         return -1;
    1391                 :            : 
    1392                 :          0 :     r->impl_free = libsamplerate_free;
    1393                 :          0 :     r->impl_update_rates = libsamplerate_update_rates;
    1394                 :          0 :     r->impl_resample = libsamplerate_resample;
    1395                 :          0 :     r->impl_reset = libsamplerate_reset;
    1396                 :            : 
    1397                 :          0 :     return 0;
    1398                 :            : }
    1399                 :            : #endif
    1400                 :            : 
    1401                 :            : #ifdef HAVE_SPEEX
    1402                 :            : /*** speex based implementation ***/
    1403                 :            : 
    1404                 :          0 : static void speex_resample_float(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    1405                 :            :     float *in, *out;
    1406                 :          0 :     uint32_t inf = in_n_frames, outf = *out_n_frames;
    1407                 :            : 
    1408         [ #  # ]:          0 :     pa_assert(r);
    1409         [ #  # ]:          0 :     pa_assert(input);
    1410         [ #  # ]:          0 :     pa_assert(output);
    1411         [ #  # ]:          0 :     pa_assert(out_n_frames);
    1412                 :            : 
    1413                 :          0 :     in = (float*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
    1414                 :          0 :     out = (float*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
    1415                 :            : 
    1416         [ #  # ]:          0 :     pa_assert_se(speex_resampler_process_interleaved_float(r->speex.state, in, &inf, out, &outf) == 0);
    1417                 :            : 
    1418                 :          0 :     pa_memblock_release(input->memblock);
    1419                 :          0 :     pa_memblock_release(output->memblock);
    1420                 :            : 
    1421         [ #  # ]:          0 :     pa_assert(inf == in_n_frames);
    1422                 :          0 :     *out_n_frames = outf;
    1423                 :          0 : }
    1424                 :            : 
    1425                 :          0 : static void speex_resample_int(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    1426                 :            :     int16_t *in, *out;
    1427                 :          0 :     uint32_t inf = in_n_frames, outf = *out_n_frames;
    1428                 :            : 
    1429         [ #  # ]:          0 :     pa_assert(r);
    1430         [ #  # ]:          0 :     pa_assert(input);
    1431         [ #  # ]:          0 :     pa_assert(output);
    1432         [ #  # ]:          0 :     pa_assert(out_n_frames);
    1433                 :            : 
    1434                 :          0 :     in = (int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index);
    1435                 :          0 :     out = (int16_t*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index);
    1436                 :            : 
    1437         [ #  # ]:          0 :     pa_assert_se(speex_resampler_process_interleaved_int(r->speex.state, in, &inf, out, &outf) == 0);
    1438                 :            : 
    1439                 :          0 :     pa_memblock_release(input->memblock);
    1440                 :          0 :     pa_memblock_release(output->memblock);
    1441                 :            : 
    1442         [ #  # ]:          0 :     pa_assert(inf == in_n_frames);
    1443                 :          0 :     *out_n_frames = outf;
    1444                 :          0 : }
    1445                 :            : 
    1446                 :          0 : static void speex_update_rates(pa_resampler *r) {
    1447         [ #  # ]:          0 :     pa_assert(r);
    1448                 :            : 
    1449         [ #  # ]:          0 :     pa_assert_se(speex_resampler_set_rate(r->speex.state, r->i_ss.rate, r->o_ss.rate) == 0);
    1450                 :          0 : }
    1451                 :            : 
    1452                 :          0 : static void speex_reset(pa_resampler *r) {
    1453         [ #  # ]:          0 :     pa_assert(r);
    1454                 :            : 
    1455         [ #  # ]:          0 :     pa_assert_se(speex_resampler_reset_mem(r->speex.state) == 0);
    1456                 :          0 : }
    1457                 :            : 
    1458                 :          0 : static void speex_free(pa_resampler *r) {
    1459         [ #  # ]:          0 :     pa_assert(r);
    1460                 :            : 
    1461         [ #  # ]:          0 :     if (!r->speex.state)
    1462                 :          0 :         return;
    1463                 :            : 
    1464                 :          0 :     speex_resampler_destroy(r->speex.state);
    1465                 :            : }
    1466                 :            : 
    1467                 :          0 : static int speex_init(pa_resampler *r) {
    1468                 :            :     int q, err;
    1469                 :            : 
    1470         [ #  # ]:          0 :     pa_assert(r);
    1471                 :            : 
    1472                 :          0 :     r->impl_free = speex_free;
    1473                 :          0 :     r->impl_update_rates = speex_update_rates;
    1474                 :          0 :     r->impl_reset = speex_reset;
    1475                 :            : 
    1476         [ #  # ]:          0 :     if (r->method >= PA_RESAMPLER_SPEEX_FIXED_BASE && r->method <= PA_RESAMPLER_SPEEX_FIXED_MAX) {
    1477                 :            : 
    1478                 :          0 :         q = r->method - PA_RESAMPLER_SPEEX_FIXED_BASE;
    1479                 :          0 :         r->impl_resample = speex_resample_int;
    1480                 :            : 
    1481                 :            :     } else {
    1482         [ #  # ]:          0 :         pa_assert(r->method >= PA_RESAMPLER_SPEEX_FLOAT_BASE && r->method <= PA_RESAMPLER_SPEEX_FLOAT_MAX);
    1483                 :            : 
    1484                 :          0 :         q = r->method - PA_RESAMPLER_SPEEX_FLOAT_BASE;
    1485                 :          0 :         r->impl_resample = speex_resample_float;
    1486                 :            :     }
    1487                 :            : 
    1488                 :          0 :     pa_log_info("Choosing speex quality setting %i.", q);
    1489                 :            : 
    1490         [ #  # ]:          0 :     if (!(r->speex.state = speex_resampler_init(r->o_ss.channels, r->i_ss.rate, r->o_ss.rate, q, &err)))
    1491                 :            :         return -1;
    1492                 :            : 
    1493                 :          0 :     return 0;
    1494                 :            : }
    1495                 :            : #endif
    1496                 :            : 
    1497                 :            : /* Trivial implementation */
    1498                 :            : 
    1499                 :          0 : static void trivial_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    1500                 :            :     size_t fz;
    1501                 :            :     unsigned i_index, o_index;
    1502                 :            :     void *src, *dst;
    1503                 :            : 
    1504         [ #  # ]:          0 :     pa_assert(r);
    1505         [ #  # ]:          0 :     pa_assert(input);
    1506         [ #  # ]:          0 :     pa_assert(output);
    1507         [ #  # ]:          0 :     pa_assert(out_n_frames);
    1508                 :            : 
    1509                 :          0 :     fz = r->w_sz * r->o_ss.channels;
    1510                 :            : 
    1511                 :          0 :     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
    1512                 :          0 :     dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
    1513                 :            : 
    1514                 :          0 :     for (o_index = 0;; o_index++, r->trivial.o_counter++) {
    1515                 :          0 :         i_index = (r->trivial.o_counter * r->i_ss.rate) / r->o_ss.rate;
    1516         [ #  # ]:          0 :         i_index = i_index > r->trivial.i_counter ? i_index - r->trivial.i_counter : 0;
    1517                 :            : 
    1518         [ #  # ]:          0 :         if (i_index >= in_n_frames)
    1519                 :            :             break;
    1520                 :            : 
    1521                 :            :         pa_assert_fp(o_index * fz < pa_memblock_get_length(output->memblock));
    1522                 :            : 
    1523                 :          0 :         memcpy((uint8_t*) dst + fz * o_index, (uint8_t*) src + fz * i_index, (int) fz);
    1524                 :          0 :     }
    1525                 :            : 
    1526                 :          0 :     pa_memblock_release(input->memblock);
    1527                 :          0 :     pa_memblock_release(output->memblock);
    1528                 :            : 
    1529                 :          0 :     *out_n_frames = o_index;
    1530                 :            : 
    1531                 :          0 :     r->trivial.i_counter += in_n_frames;
    1532                 :            : 
    1533                 :            :     /* Normalize counters */
    1534         [ #  # ]:          0 :     while (r->trivial.i_counter >= r->i_ss.rate) {
    1535         [ #  # ]:          0 :         pa_assert(r->trivial.o_counter >= r->o_ss.rate);
    1536                 :            : 
    1537                 :          0 :         r->trivial.i_counter -= r->i_ss.rate;
    1538                 :          0 :         r->trivial.o_counter -= r->o_ss.rate;
    1539                 :            :     }
    1540                 :          0 : }
    1541                 :            : 
    1542                 :          0 : static void trivial_update_rates_or_reset(pa_resampler *r) {
    1543         [ #  # ]:          0 :     pa_assert(r);
    1544                 :            : 
    1545                 :          0 :     r->trivial.i_counter = 0;
    1546                 :          0 :     r->trivial.o_counter = 0;
    1547                 :          0 : }
    1548                 :            : 
    1549                 :          0 : static int trivial_init(pa_resampler*r) {
    1550         [ #  # ]:          0 :     pa_assert(r);
    1551                 :            : 
    1552                 :          0 :     r->trivial.o_counter = r->trivial.i_counter = 0;
    1553                 :            : 
    1554                 :          0 :     r->impl_resample = trivial_resample;
    1555                 :          0 :     r->impl_update_rates = trivial_update_rates_or_reset;
    1556                 :          0 :     r->impl_reset = trivial_update_rates_or_reset;
    1557                 :            : 
    1558                 :          0 :     return 0;
    1559                 :            : }
    1560                 :            : 
    1561                 :            : /* Peak finder implementation */
    1562                 :            : 
    1563                 :          0 : static void peaks_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    1564                 :          0 :     unsigned c, o_index = 0;
    1565                 :          0 :     unsigned i, i_end = 0;
    1566                 :            :     void *src, *dst;
    1567                 :            : 
    1568         [ #  # ]:          0 :     pa_assert(r);
    1569         [ #  # ]:          0 :     pa_assert(input);
    1570         [ #  # ]:          0 :     pa_assert(output);
    1571         [ #  # ]:          0 :     pa_assert(out_n_frames);
    1572                 :            : 
    1573                 :          0 :     src = (uint8_t*) pa_memblock_acquire(input->memblock) + input->index;
    1574                 :          0 :     dst = (uint8_t*) pa_memblock_acquire(output->memblock) + output->index;
    1575                 :            : 
    1576                 :          0 :     i = (r->peaks.o_counter * r->i_ss.rate) / r->o_ss.rate;
    1577         [ #  # ]:          0 :     i = i > r->peaks.i_counter ? i - r->peaks.i_counter : 0;
    1578                 :            : 
    1579         [ #  # ]:          0 :     while (i_end < in_n_frames) {
    1580                 :          0 :         i_end = ((r->peaks.o_counter+1) * r->i_ss.rate) / r->o_ss.rate;
    1581         [ #  # ]:          0 :         i_end = i_end > r->peaks.i_counter ? i_end - r->peaks.i_counter : 0;
    1582                 :            : 
    1583                 :            :         pa_assert_fp(o_index * r->w_sz * r->o_ss.channels < pa_memblock_get_length(output->memblock));
    1584                 :            : 
    1585                 :            :         /* 1ch float is treated separately, because that is the common case */
    1586 [ #  # ][ #  # ]:          0 :         if (r->o_ss.channels == 1 && r->work_format == PA_SAMPLE_FLOAT32NE) {
    1587                 :          0 :             float *s = (float*) src + i;
    1588                 :          0 :             float *d = (float*) dst + o_index;
    1589                 :            : 
    1590         [ #  # ]:          0 :             for (; i < i_end && i < in_n_frames; i++) {
    1591                 :          0 :                 float n = fabsf(*s++);
    1592                 :            : 
    1593         [ #  # ]:          0 :                 if (n > r->peaks.max_f[0])
    1594                 :          0 :                     r->peaks.max_f[0] = n;
    1595                 :            :             }
    1596                 :            : 
    1597         [ #  # ]:          0 :             if (i == i_end) {
    1598                 :          0 :                 *d = r->peaks.max_f[0];
    1599                 :          0 :                 r->peaks.max_f[0] = 0;
    1600                 :          0 :                 o_index++, r->peaks.o_counter++;
    1601                 :            :             }
    1602         [ #  # ]:          0 :         } else if (r->work_format == PA_SAMPLE_S16NE) {
    1603                 :          0 :             int16_t *s = (int16_t*) src + r->i_ss.channels * i;
    1604                 :          0 :             int16_t *d = (int16_t*) dst + r->o_ss.channels * o_index;
    1605                 :            : 
    1606         [ #  # ]:          0 :             for (; i < i_end && i < in_n_frames; i++)
    1607         [ #  # ]:          0 :                 for (c = 0; c < r->o_ss.channels; c++) {
    1608                 :          0 :                     int16_t n = abs(*s++);
    1609                 :            : 
    1610         [ #  # ]:          0 :                     if (n > r->peaks.max_i[c])
    1611                 :          0 :                         r->peaks.max_i[c] = n;
    1612                 :            :                 }
    1613                 :            : 
    1614         [ #  # ]:          0 :             if (i == i_end) {
    1615         [ #  # ]:          0 :                 for (c = 0; c < r->o_ss.channels; c++, d++) {
    1616                 :          0 :                     *d = r->peaks.max_i[c];
    1617                 :          0 :                     r->peaks.max_i[c] = 0;
    1618                 :            :                 }
    1619                 :          0 :                 o_index++, r->peaks.o_counter++;
    1620                 :            :             }
    1621                 :            :         } else {
    1622                 :          0 :             float *s = (float*) src + r->i_ss.channels * i;
    1623                 :          0 :             float *d = (float*) dst + r->o_ss.channels * o_index;
    1624                 :            : 
    1625         [ #  # ]:          0 :             for (; i < i_end && i < in_n_frames; i++)
    1626         [ #  # ]:          0 :                 for (c = 0; c < r->o_ss.channels; c++) {
    1627                 :          0 :                     float n = fabsf(*s++);
    1628                 :            : 
    1629         [ #  # ]:          0 :                     if (n > r->peaks.max_f[c])
    1630                 :          0 :                         r->peaks.max_f[c] = n;
    1631                 :            :                 }
    1632                 :            : 
    1633         [ #  # ]:          0 :             if (i == i_end) {
    1634         [ #  # ]:          0 :                 for (c = 0; c < r->o_ss.channels; c++, d++) {
    1635                 :          0 :                     *d = r->peaks.max_f[c];
    1636                 :          0 :                     r->peaks.max_f[c] = 0;
    1637                 :            :                 }
    1638                 :          0 :                 o_index++, r->peaks.o_counter++;
    1639                 :            :             }
    1640                 :            :         }
    1641                 :            :     }
    1642                 :            : 
    1643                 :          0 :     pa_memblock_release(input->memblock);
    1644                 :          0 :     pa_memblock_release(output->memblock);
    1645                 :            : 
    1646                 :          0 :     *out_n_frames = o_index;
    1647                 :            : 
    1648                 :          0 :     r->peaks.i_counter += in_n_frames;
    1649                 :            : 
    1650                 :            :     /* Normalize counters */
    1651         [ #  # ]:          0 :     while (r->peaks.i_counter >= r->i_ss.rate) {
    1652         [ #  # ]:          0 :         pa_assert(r->peaks.o_counter >= r->o_ss.rate);
    1653                 :            : 
    1654                 :          0 :         r->peaks.i_counter -= r->i_ss.rate;
    1655                 :          0 :         r->peaks.o_counter -= r->o_ss.rate;
    1656                 :            :     }
    1657                 :          0 : }
    1658                 :            : 
    1659                 :          0 : static void peaks_update_rates_or_reset(pa_resampler *r) {
    1660         [ #  # ]:          0 :     pa_assert(r);
    1661                 :            : 
    1662                 :          0 :     r->peaks.i_counter = 0;
    1663                 :          0 :     r->peaks.o_counter = 0;
    1664                 :          0 : }
    1665                 :            : 
    1666                 :          0 : static int peaks_init(pa_resampler*r) {
    1667         [ #  # ]:          0 :     pa_assert(r);
    1668         [ #  # ]:          0 :     pa_assert(r->i_ss.rate >= r->o_ss.rate);
    1669         [ #  # ]:          0 :     pa_assert(r->work_format == PA_SAMPLE_S16NE || r->work_format == PA_SAMPLE_FLOAT32NE);
    1670                 :            : 
    1671                 :          0 :     r->peaks.o_counter = r->peaks.i_counter = 0;
    1672                 :          0 :     memset(r->peaks.max_i, 0, sizeof(r->peaks.max_i));
    1673                 :          0 :     memset(r->peaks.max_f, 0, sizeof(r->peaks.max_f));
    1674                 :            : 
    1675                 :          0 :     r->impl_resample = peaks_resample;
    1676                 :          0 :     r->impl_update_rates = peaks_update_rates_or_reset;
    1677                 :          0 :     r->impl_reset = peaks_update_rates_or_reset;
    1678                 :            : 
    1679                 :          0 :     return 0;
    1680                 :            : }
    1681                 :            : 
    1682                 :            : /*** ffmpeg based implementation ***/
    1683                 :            : 
    1684                 :          0 : static void ffmpeg_resample(pa_resampler *r, const pa_memchunk *input, unsigned in_n_frames, pa_memchunk *output, unsigned *out_n_frames) {
    1685                 :          0 :     unsigned used_frames = 0, c;
    1686                 :          0 :     int previous_consumed_frames = -1;
    1687                 :            : 
    1688         [ #  # ]:          0 :     pa_assert(r);
    1689         [ #  # ]:          0 :     pa_assert(input);
    1690         [ #  # ]:          0 :     pa_assert(output);
    1691         [ #  # ]:          0 :     pa_assert(out_n_frames);
    1692                 :            : 
    1693         [ #  # ]:          0 :     for (c = 0; c < r->o_ss.channels; c++) {
    1694                 :            :         unsigned u;
    1695                 :            :         pa_memblock *b, *w;
    1696                 :            :         int16_t *p, *t, *k, *q, *s;
    1697                 :            :         int consumed_frames;
    1698                 :            : 
    1699                 :            :         /* Allocate a new block */
    1700                 :          0 :         b = pa_memblock_new(r->mempool, r->ffmpeg.buf[c].length + in_n_frames * sizeof(int16_t));
    1701                 :          0 :         p = pa_memblock_acquire(b);
    1702                 :            : 
    1703                 :            :         /* Now copy the input data, splitting up channels */
    1704                 :          0 :         t = ((int16_t*) ((uint8_t*) pa_memblock_acquire(input->memblock) + input->index)) + c;
    1705                 :          0 :         k = (int16_t*) ((uint8_t*) p);
    1706         [ #  # ]:          0 :         for (u = 0; u < in_n_frames; u++) {
    1707                 :          0 :             *k = *t;
    1708                 :          0 :             t += r->o_ss.channels;
    1709                 :          0 :             k ++;
    1710                 :            :         }
    1711                 :          0 :         pa_memblock_release(input->memblock);
    1712                 :            : 
    1713                 :            :         /* Allocate buffer for the result */
    1714                 :          0 :         w = pa_memblock_new(r->mempool, *out_n_frames * sizeof(int16_t));
    1715                 :          0 :         q = pa_memblock_acquire(w);
    1716                 :            : 
    1717                 :            :         /* Now, resample */
    1718                 :          0 :         used_frames = (unsigned) av_resample(r->ffmpeg.state,
    1719                 :            :                                              q, p,
    1720                 :            :                                              &consumed_frames,
    1721                 :          0 :                                              (int) in_n_frames, (int) *out_n_frames,
    1722                 :          0 :                                              c >= (unsigned) (r->o_ss.channels-1));
    1723                 :            : 
    1724                 :          0 :         pa_memblock_release(b);
    1725                 :          0 :         pa_memblock_unref(b);
    1726                 :            : 
    1727         [ #  # ]:          0 :         pa_assert(consumed_frames <= (int) in_n_frames);
    1728 [ #  # ][ #  # ]:          0 :         pa_assert(previous_consumed_frames == -1 || consumed_frames == previous_consumed_frames);
    1729                 :          0 :         previous_consumed_frames = consumed_frames;
    1730                 :            : 
    1731                 :            :         /* And place the results in the output buffer */
    1732                 :          0 :         s = (short*) ((uint8_t*) pa_memblock_acquire(output->memblock) + output->index) + c;
    1733         [ #  # ]:          0 :         for (u = 0; u < used_frames; u++) {
    1734                 :          0 :             *s = *q;
    1735                 :          0 :             q++;
    1736                 :          0 :             s += r->o_ss.channels;
    1737                 :            :         }
    1738                 :          0 :         pa_memblock_release(output->memblock);
    1739                 :          0 :         pa_memblock_release(w);
    1740                 :          0 :         pa_memblock_unref(w);
    1741                 :            :     }
    1742                 :            : 
    1743         [ #  # ]:          0 :     if (previous_consumed_frames < (int) in_n_frames) {
    1744                 :          0 :         void *leftover_data = (int16_t *) ((uint8_t *) pa_memblock_acquire(input->memblock) + output->index) + previous_consumed_frames * r->o_ss.channels;
    1745                 :          0 :         size_t leftover_length = (in_n_frames - previous_consumed_frames) * r->o_ss.channels * sizeof(int16_t);
    1746                 :            : 
    1747                 :          0 :         save_leftover(r, leftover_data, leftover_length);
    1748                 :          0 :         pa_memblock_release(input->memblock);
    1749                 :            :     }
    1750                 :            : 
    1751                 :          0 :     *out_n_frames = used_frames;
    1752                 :          0 : }
    1753                 :            : 
    1754                 :          0 : static void ffmpeg_free(pa_resampler *r) {
    1755                 :            :     unsigned c;
    1756                 :            : 
    1757         [ #  # ]:          0 :     pa_assert(r);
    1758                 :            : 
    1759         [ #  # ]:          0 :     if (r->ffmpeg.state)
    1760                 :          0 :         av_resample_close(r->ffmpeg.state);
    1761                 :            : 
    1762         [ #  # ]:          0 :     for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
    1763         [ #  # ]:          0 :         if (r->ffmpeg.buf[c].memblock)
    1764                 :          0 :             pa_memblock_unref(r->ffmpeg.buf[c].memblock);
    1765                 :          0 : }
    1766                 :            : 
    1767                 :          0 : static int ffmpeg_init(pa_resampler *r) {
    1768                 :            :     unsigned c;
    1769                 :            : 
    1770         [ #  # ]:          0 :     pa_assert(r);
    1771                 :            : 
    1772                 :            :     /* We could probably implement different quality levels by
    1773                 :            :      * adjusting the filter parameters here. However, ffmpeg
    1774                 :            :      * internally only uses these hardcoded values, so let's use them
    1775                 :            :      * here for now as well until ffmpeg makes this configurable. */
    1776                 :            : 
    1777         [ #  # ]:          0 :     if (!(r->ffmpeg.state = av_resample_init((int) r->o_ss.rate, (int) r->i_ss.rate, 16, 10, 0, 0.8)))
    1778                 :            :         return -1;
    1779                 :            : 
    1780                 :          0 :     r->impl_free = ffmpeg_free;
    1781                 :          0 :     r->impl_resample = ffmpeg_resample;
    1782                 :            : 
    1783         [ #  # ]:          0 :     for (c = 0; c < PA_ELEMENTSOF(r->ffmpeg.buf); c++)
    1784                 :          0 :         pa_memchunk_reset(&r->ffmpeg.buf[c]);
    1785                 :            : 
    1786                 :            :     return 0;
    1787                 :            : }
    1788                 :            : 
    1789                 :            : /*** copy (noop) implementation ***/
    1790                 :            : 
    1791                 :        338 : static int copy_init(pa_resampler *r) {
    1792         [ -  + ]:        338 :     pa_assert(r);
    1793                 :            : 
    1794         [ -  + ]:        338 :     pa_assert(r->o_ss.rate == r->i_ss.rate);
    1795                 :            : 
    1796                 :        338 :     return 0;
    1797                 :            : }

Generated by: LCOV version 1.9