1/*
2 *  Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
3 *
4 *  Use of this source code is governed by a BSD-style license
5 *  that can be found in the LICENSE file in the root of the source
6 *  tree. An additional intellectual property rights grant can be found
7 *  in the file PATENTS.  All contributing project authors may
8 *  be found in the AUTHORS file in the root of the source tree.
9 */
10
11
12/*
13 * A wrapper for resampling a numerous amount of sampling combinations.
14 */
15
16#include <stdlib.h>
17#include <string.h>
18
19#include "signal_processing_library.h"
20#include "resampler.h"
21
22
23namespace webrtc
24{
25
26Resampler::Resampler()
27{
28    state1_ = NULL;
29    state2_ = NULL;
30    state3_ = NULL;
31    in_buffer_ = NULL;
32    out_buffer_ = NULL;
33    in_buffer_size_ = 0;
34    out_buffer_size_ = 0;
35    in_buffer_size_max_ = 0;
36    out_buffer_size_max_ = 0;
37    // we need a reset before we will work
38    my_in_frequency_khz_ = 0;
39    my_out_frequency_khz_ = 0;
40    my_mode_ = kResamplerMode1To1;
41    my_type_ = kResamplerInvalid;
42    slave_left_ = NULL;
43    slave_right_ = NULL;
44}
45
46Resampler::Resampler(int inFreq, int outFreq, ResamplerType type)
47{
48    state1_ = NULL;
49    state2_ = NULL;
50    state3_ = NULL;
51    in_buffer_ = NULL;
52    out_buffer_ = NULL;
53    in_buffer_size_ = 0;
54    out_buffer_size_ = 0;
55    in_buffer_size_max_ = 0;
56    out_buffer_size_max_ = 0;
57    // we need a reset before we will work
58    my_in_frequency_khz_ = 0;
59    my_out_frequency_khz_ = 0;
60    my_mode_ = kResamplerMode1To1;
61    my_type_ = kResamplerInvalid;
62    slave_left_ = NULL;
63    slave_right_ = NULL;
64
65    Reset(inFreq, outFreq, type);
66}
67
68Resampler::~Resampler()
69{
70    if (state1_)
71    {
72        free(state1_);
73    }
74    if (state2_)
75    {
76        free(state2_);
77    }
78    if (state3_)
79    {
80        free(state3_);
81    }
82    if (in_buffer_)
83    {
84        free(in_buffer_);
85    }
86    if (out_buffer_)
87    {
88        free(out_buffer_);
89    }
90    if (slave_left_)
91    {
92        delete slave_left_;
93    }
94    if (slave_right_)
95    {
96        delete slave_right_;
97    }
98}
99
100int Resampler::ResetIfNeeded(int inFreq, int outFreq, ResamplerType type)
101{
102    int tmpInFreq_kHz = inFreq / 1000;
103    int tmpOutFreq_kHz = outFreq / 1000;
104
105    if ((tmpInFreq_kHz != my_in_frequency_khz_) || (tmpOutFreq_kHz != my_out_frequency_khz_)
106            || (type != my_type_))
107    {
108        return Reset(inFreq, outFreq, type);
109    } else
110    {
111        return 0;
112    }
113}
114
115int Resampler::Reset(int inFreq, int outFreq, ResamplerType type)
116{
117
118    if (state1_)
119    {
120        free(state1_);
121        state1_ = NULL;
122    }
123    if (state2_)
124    {
125        free(state2_);
126        state2_ = NULL;
127    }
128    if (state3_)
129    {
130        free(state3_);
131        state3_ = NULL;
132    }
133    if (in_buffer_)
134    {
135        free(in_buffer_);
136        in_buffer_ = NULL;
137    }
138    if (out_buffer_)
139    {
140        free(out_buffer_);
141        out_buffer_ = NULL;
142    }
143    if (slave_left_)
144    {
145        delete slave_left_;
146        slave_left_ = NULL;
147    }
148    if (slave_right_)
149    {
150        delete slave_right_;
151        slave_right_ = NULL;
152    }
153
154    in_buffer_size_ = 0;
155    out_buffer_size_ = 0;
156    in_buffer_size_max_ = 0;
157    out_buffer_size_max_ = 0;
158
159    // This might be overridden if parameters are not accepted.
160    my_type_ = type;
161
162    // Start with a math exercise, Euclid's algorithm to find the gcd:
163
164    int a = inFreq;
165    int b = outFreq;
166    int c = a % b;
167    while (c != 0)
168    {
169        a = b;
170        b = c;
171        c = a % b;
172    }
173    // b is now the gcd;
174
175    // We need to track what domain we're in.
176    my_in_frequency_khz_ = inFreq / 1000;
177    my_out_frequency_khz_ = outFreq / 1000;
178
179    // Scale with GCD
180    inFreq = inFreq / b;
181    outFreq = outFreq / b;
182
183    // Do we need stereo?
184    if ((my_type_ & 0xf0) == 0x20)
185    {
186        // Change type to mono
187        type = static_cast<ResamplerType>(
188            ((static_cast<int>(type) & 0x0f) + 0x10));
189        slave_left_ = new Resampler(inFreq, outFreq, type);
190        slave_right_ = new Resampler(inFreq, outFreq, type);
191    }
192
193    if (inFreq == outFreq)
194    {
195        my_mode_ = kResamplerMode1To1;
196    } else if (inFreq == 1)
197    {
198        switch (outFreq)
199        {
200            case 2:
201                my_mode_ = kResamplerMode1To2;
202                break;
203            case 3:
204                my_mode_ = kResamplerMode1To3;
205                break;
206            case 4:
207                my_mode_ = kResamplerMode1To4;
208                break;
209            case 6:
210                my_mode_ = kResamplerMode1To6;
211                break;
212            case 12:
213                my_mode_ = kResamplerMode1To12;
214                break;
215            default:
216                my_type_ = kResamplerInvalid;
217                return -1;
218        }
219    } else if (outFreq == 1)
220    {
221        switch (inFreq)
222        {
223            case 2:
224                my_mode_ = kResamplerMode2To1;
225                break;
226            case 3:
227                my_mode_ = kResamplerMode3To1;
228                break;
229            case 4:
230                my_mode_ = kResamplerMode4To1;
231                break;
232            case 6:
233                my_mode_ = kResamplerMode6To1;
234                break;
235            case 12:
236                my_mode_ = kResamplerMode12To1;
237                break;
238            default:
239                my_type_ = kResamplerInvalid;
240                return -1;
241        }
242    } else if ((inFreq == 2) && (outFreq == 3))
243    {
244        my_mode_ = kResamplerMode2To3;
245    } else if ((inFreq == 2) && (outFreq == 11))
246    {
247        my_mode_ = kResamplerMode2To11;
248    } else if ((inFreq == 4) && (outFreq == 11))
249    {
250        my_mode_ = kResamplerMode4To11;
251    } else if ((inFreq == 8) && (outFreq == 11))
252    {
253        my_mode_ = kResamplerMode8To11;
254    } else if ((inFreq == 3) && (outFreq == 2))
255    {
256        my_mode_ = kResamplerMode3To2;
257    } else if ((inFreq == 11) && (outFreq == 2))
258    {
259        my_mode_ = kResamplerMode11To2;
260    } else if ((inFreq == 11) && (outFreq == 4))
261    {
262        my_mode_ = kResamplerMode11To4;
263    } else if ((inFreq == 11) && (outFreq == 16))
264    {
265        my_mode_ = kResamplerMode11To16;
266    } else if ((inFreq == 11) && (outFreq == 32))
267    {
268        my_mode_ = kResamplerMode11To32;
269    } else if ((inFreq == 11) && (outFreq == 8))
270    {
271        my_mode_ = kResamplerMode11To8;
272    } else
273    {
274        my_type_ = kResamplerInvalid;
275        return -1;
276    }
277
278    // Now create the states we need
279    switch (my_mode_)
280    {
281        case kResamplerMode1To1:
282            // No state needed;
283            break;
284        case kResamplerMode1To2:
285            state1_ = malloc(8 * sizeof(WebRtc_Word32));
286            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
287            break;
288        case kResamplerMode1To3:
289            state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
290            WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_);
291            break;
292        case kResamplerMode1To4:
293            // 1:2
294            state1_ = malloc(8 * sizeof(WebRtc_Word32));
295            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
296            // 2:4
297            state2_ = malloc(8 * sizeof(WebRtc_Word32));
298            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
299            break;
300        case kResamplerMode1To6:
301            // 1:2
302            state1_ = malloc(8 * sizeof(WebRtc_Word32));
303            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
304            // 2:6
305            state2_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
306            WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state2_);
307            break;
308        case kResamplerMode1To12:
309            // 1:2
310            state1_ = malloc(8 * sizeof(WebRtc_Word32));
311            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
312            // 2:4
313            state2_ = malloc(8 * sizeof(WebRtc_Word32));
314            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
315            // 4:12
316            state3_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
317            WebRtcSpl_ResetResample16khzTo48khz(
318                (WebRtcSpl_State16khzTo48khz*) state3_);
319            break;
320        case kResamplerMode2To3:
321            // 2:6
322            state1_ = malloc(sizeof(WebRtcSpl_State16khzTo48khz));
323            WebRtcSpl_ResetResample16khzTo48khz((WebRtcSpl_State16khzTo48khz *)state1_);
324            // 6:3
325            state2_ = malloc(8 * sizeof(WebRtc_Word32));
326            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
327            break;
328        case kResamplerMode2To11:
329            state1_ = malloc(8 * sizeof(WebRtc_Word32));
330            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
331
332            state2_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz));
333            WebRtcSpl_ResetResample8khzTo22khz((WebRtcSpl_State8khzTo22khz *)state2_);
334            break;
335        case kResamplerMode4To11:
336            state1_ = malloc(sizeof(WebRtcSpl_State8khzTo22khz));
337            WebRtcSpl_ResetResample8khzTo22khz((WebRtcSpl_State8khzTo22khz *)state1_);
338            break;
339        case kResamplerMode8To11:
340            state1_ = malloc(sizeof(WebRtcSpl_State16khzTo22khz));
341            WebRtcSpl_ResetResample16khzTo22khz((WebRtcSpl_State16khzTo22khz *)state1_);
342            break;
343        case kResamplerMode11To16:
344            state1_ = malloc(8 * sizeof(WebRtc_Word32));
345            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
346
347            state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
348            WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_);
349            break;
350        case kResamplerMode11To32:
351            // 11 -> 22
352            state1_ = malloc(8 * sizeof(WebRtc_Word32));
353            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
354
355            // 22 -> 16
356            state2_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
357            WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state2_);
358
359            // 16 -> 32
360            state3_ = malloc(8 * sizeof(WebRtc_Word32));
361            memset(state3_, 0, 8 * sizeof(WebRtc_Word32));
362
363            break;
364        case kResamplerMode2To1:
365            state1_ = malloc(8 * sizeof(WebRtc_Word32));
366            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
367            break;
368        case kResamplerMode3To1:
369            state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
370            WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_);
371            break;
372        case kResamplerMode4To1:
373            // 4:2
374            state1_ = malloc(8 * sizeof(WebRtc_Word32));
375            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
376            // 2:1
377            state2_ = malloc(8 * sizeof(WebRtc_Word32));
378            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
379            break;
380        case kResamplerMode6To1:
381            // 6:2
382            state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
383            WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state1_);
384            // 2:1
385            state2_ = malloc(8 * sizeof(WebRtc_Word32));
386            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
387            break;
388        case kResamplerMode12To1:
389            // 12:4
390            state1_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
391            WebRtcSpl_ResetResample48khzTo16khz(
392                (WebRtcSpl_State48khzTo16khz*) state1_);
393            // 4:2
394            state2_ = malloc(8 * sizeof(WebRtc_Word32));
395            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
396            // 2:1
397            state3_ = malloc(8 * sizeof(WebRtc_Word32));
398            memset(state3_, 0, 8 * sizeof(WebRtc_Word32));
399            break;
400        case kResamplerMode3To2:
401            // 3:6
402            state1_ = malloc(8 * sizeof(WebRtc_Word32));
403            memset(state1_, 0, 8 * sizeof(WebRtc_Word32));
404            // 6:2
405            state2_ = malloc(sizeof(WebRtcSpl_State48khzTo16khz));
406            WebRtcSpl_ResetResample48khzTo16khz((WebRtcSpl_State48khzTo16khz *)state2_);
407            break;
408        case kResamplerMode11To2:
409            state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz));
410            WebRtcSpl_ResetResample22khzTo8khz((WebRtcSpl_State22khzTo8khz *)state1_);
411
412            state2_ = malloc(8 * sizeof(WebRtc_Word32));
413            memset(state2_, 0, 8 * sizeof(WebRtc_Word32));
414
415            break;
416        case kResamplerMode11To4:
417            state1_ = malloc(sizeof(WebRtcSpl_State22khzTo8khz));
418            WebRtcSpl_ResetResample22khzTo8khz((WebRtcSpl_State22khzTo8khz *)state1_);
419            break;
420        case kResamplerMode11To8:
421            state1_ = malloc(sizeof(WebRtcSpl_State22khzTo16khz));
422            WebRtcSpl_ResetResample22khzTo16khz((WebRtcSpl_State22khzTo16khz *)state1_);
423            break;
424
425    }
426
427    return 0;
428}
429
430// Synchronous resampling, all output samples are written to samplesOut
431int Resampler::Push(const WebRtc_Word16 * samplesIn, int lengthIn, WebRtc_Word16* samplesOut,
432                    int maxLen, int &outLen)
433{
434    // Check that the resampler is not in asynchronous mode
435    if (my_type_ & 0x0f)
436    {
437        return -1;
438    }
439
440    // Do we have a stereo signal?
441    if ((my_type_ & 0xf0) == 0x20)
442    {
443
444        // Split up the signal and call the slave object for each channel
445
446        WebRtc_Word16* left = (WebRtc_Word16*)malloc(lengthIn * sizeof(WebRtc_Word16) / 2);
447        WebRtc_Word16* right = (WebRtc_Word16*)malloc(lengthIn * sizeof(WebRtc_Word16) / 2);
448        WebRtc_Word16* out_left = (WebRtc_Word16*)malloc(maxLen / 2 * sizeof(WebRtc_Word16));
449        WebRtc_Word16* out_right =
450                (WebRtc_Word16*)malloc(maxLen / 2 * sizeof(WebRtc_Word16));
451        int res = 0;
452        for (int i = 0; i < lengthIn; i += 2)
453        {
454            left[i >> 1] = samplesIn[i];
455            right[i >> 1] = samplesIn[i + 1];
456        }
457
458        // It's OK to overwrite the local parameter, since it's just a copy
459        lengthIn = lengthIn / 2;
460
461        int actualOutLen_left = 0;
462        int actualOutLen_right = 0;
463        // Do resampling for right channel
464        res |= slave_left_->Push(left, lengthIn, out_left, maxLen / 2, actualOutLen_left);
465        res |= slave_right_->Push(right, lengthIn, out_right, maxLen / 2, actualOutLen_right);
466        if (res || (actualOutLen_left != actualOutLen_right))
467        {
468            free(left);
469            free(right);
470            free(out_left);
471            free(out_right);
472            return -1;
473        }
474
475        // Reassemble the signal
476        for (int i = 0; i < actualOutLen_left; i++)
477        {
478            samplesOut[i * 2] = out_left[i];
479            samplesOut[i * 2 + 1] = out_right[i];
480        }
481        outLen = 2 * actualOutLen_left;
482
483        free(left);
484        free(right);
485        free(out_left);
486        free(out_right);
487
488        return 0;
489    }
490
491    // Containers for temp samples
492    WebRtc_Word16* tmp;
493    WebRtc_Word16* tmp_2;
494    // tmp data for resampling routines
495    WebRtc_Word32* tmp_mem;
496
497    switch (my_mode_)
498    {
499        case kResamplerMode1To1:
500            memcpy(samplesOut, samplesIn, lengthIn * sizeof(WebRtc_Word16));
501            outLen = lengthIn;
502            break;
503        case kResamplerMode1To2:
504            if (maxLen < (lengthIn * 2))
505            {
506                return -1;
507            }
508            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)state1_);
509            outLen = lengthIn * 2;
510            return 0;
511        case kResamplerMode1To3:
512
513            // We can only handle blocks of 160 samples
514            // Can be fixed, but I don't think it's needed
515            if ((lengthIn % 160) != 0)
516            {
517                return -1;
518            }
519            if (maxLen < (lengthIn * 3))
520            {
521                return -1;
522            }
523            tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32));
524
525            for (int i = 0; i < lengthIn; i += 160)
526            {
527                WebRtcSpl_Resample16khzTo48khz(samplesIn + i, samplesOut + i * 3,
528                                               (WebRtcSpl_State16khzTo48khz *)state1_,
529                                               tmp_mem);
530            }
531            outLen = lengthIn * 3;
532            free(tmp_mem);
533            return 0;
534        case kResamplerMode1To4:
535            if (maxLen < (lengthIn * 4))
536            {
537                return -1;
538            }
539
540            tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn);
541            // 1:2
542            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
543            // 2:4
544            WebRtcSpl_UpsampleBy2(tmp, lengthIn * 2, samplesOut, (WebRtc_Word32*)state2_);
545            outLen = lengthIn * 4;
546            free(tmp);
547            return 0;
548        case kResamplerMode1To6:
549            // We can only handle blocks of 80 samples
550            // Can be fixed, but I don't think it's needed
551            if ((lengthIn % 80) != 0)
552            {
553                return -1;
554            }
555            if (maxLen < (lengthIn * 6))
556            {
557                return -1;
558            }
559
560            //1:2
561
562            tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32));
563            tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn);
564
565            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
566            outLen = lengthIn * 2;
567
568            for (int i = 0; i < outLen; i += 160)
569            {
570                WebRtcSpl_Resample16khzTo48khz(tmp + i, samplesOut + i * 3,
571                                               (WebRtcSpl_State16khzTo48khz *)state2_,
572                                               tmp_mem);
573            }
574            outLen = outLen * 3;
575            free(tmp_mem);
576            free(tmp);
577
578            return 0;
579        case kResamplerMode1To12:
580            // We can only handle blocks of 40 samples
581            // Can be fixed, but I don't think it's needed
582            if ((lengthIn % 40) != 0) {
583              return -1;
584            }
585            if (maxLen < (lengthIn * 12)) {
586              return -1;
587            }
588
589            tmp_mem = (WebRtc_Word32*) malloc(336 * sizeof(WebRtc_Word32));
590            tmp = (WebRtc_Word16*) malloc(sizeof(WebRtc_Word16) * 4 * lengthIn);
591            //1:2
592            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut,
593                                  (WebRtc_Word32*) state1_);
594            outLen = lengthIn * 2;
595            //2:4
596            WebRtcSpl_UpsampleBy2(samplesOut, outLen, tmp, (WebRtc_Word32*) state2_);
597            outLen = outLen * 2;
598            // 4:12
599            for (int i = 0; i < outLen; i += 160) {
600              // WebRtcSpl_Resample16khzTo48khz() takes a block of 160 samples
601              // as input and outputs a resampled block of 480 samples. The
602              // data is now actually in 32 kHz sampling rate, despite the
603              // function name, and with a resampling factor of three becomes
604              // 96 kHz.
605              WebRtcSpl_Resample16khzTo48khz(tmp + i, samplesOut + i * 3,
606                                             (WebRtcSpl_State16khzTo48khz*) state3_,
607                                             tmp_mem);
608            }
609            outLen = outLen * 3;
610            free(tmp_mem);
611            free(tmp);
612
613            return 0;
614        case kResamplerMode2To3:
615            if (maxLen < (lengthIn * 3 / 2))
616            {
617                return -1;
618            }
619            // 2:6
620            // We can only handle blocks of 160 samples
621            // Can be fixed, but I don't think it's needed
622            if ((lengthIn % 160) != 0)
623            {
624                return -1;
625            }
626            tmp = static_cast<WebRtc_Word16*> (malloc(sizeof(WebRtc_Word16) * lengthIn * 3));
627            tmp_mem = (WebRtc_Word32*)malloc(336 * sizeof(WebRtc_Word32));
628            for (int i = 0; i < lengthIn; i += 160)
629            {
630                WebRtcSpl_Resample16khzTo48khz(samplesIn + i, tmp + i * 3,
631                                               (WebRtcSpl_State16khzTo48khz *)state1_,
632                                               tmp_mem);
633            }
634            lengthIn = lengthIn * 3;
635            // 6:3
636            WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, (WebRtc_Word32*)state2_);
637            outLen = lengthIn / 2;
638            free(tmp);
639            free(tmp_mem);
640            return 0;
641        case kResamplerMode2To11:
642
643            // We can only handle blocks of 80 samples
644            // Can be fixed, but I don't think it's needed
645            if ((lengthIn % 80) != 0)
646            {
647                return -1;
648            }
649            if (maxLen < ((lengthIn * 11) / 2))
650            {
651                return -1;
652            }
653            tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * 2 * lengthIn);
654            // 1:2
655            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
656            lengthIn *= 2;
657
658            tmp_mem = (WebRtc_Word32*)malloc(98 * sizeof(WebRtc_Word32));
659
660            for (int i = 0; i < lengthIn; i += 80)
661            {
662                WebRtcSpl_Resample8khzTo22khz(tmp + i, samplesOut + (i * 11) / 4,
663                                              (WebRtcSpl_State8khzTo22khz *)state2_,
664                                              tmp_mem);
665            }
666            outLen = (lengthIn * 11) / 4;
667            free(tmp_mem);
668            free(tmp);
669            return 0;
670        case kResamplerMode4To11:
671
672            // We can only handle blocks of 80 samples
673            // Can be fixed, but I don't think it's needed
674            if ((lengthIn % 80) != 0)
675            {
676                return -1;
677            }
678            if (maxLen < ((lengthIn * 11) / 4))
679            {
680                return -1;
681            }
682            tmp_mem = (WebRtc_Word32*)malloc(98 * sizeof(WebRtc_Word32));
683
684            for (int i = 0; i < lengthIn; i += 80)
685            {
686                WebRtcSpl_Resample8khzTo22khz(samplesIn + i, samplesOut + (i * 11) / 4,
687                                              (WebRtcSpl_State8khzTo22khz *)state1_,
688                                              tmp_mem);
689            }
690            outLen = (lengthIn * 11) / 4;
691            free(tmp_mem);
692            return 0;
693        case kResamplerMode8To11:
694            // We can only handle blocks of 160 samples
695            // Can be fixed, but I don't think it's needed
696            if ((lengthIn % 160) != 0)
697            {
698                return -1;
699            }
700            if (maxLen < ((lengthIn * 11) / 8))
701            {
702                return -1;
703            }
704            tmp_mem = (WebRtc_Word32*)malloc(88 * sizeof(WebRtc_Word32));
705
706            for (int i = 0; i < lengthIn; i += 160)
707            {
708                WebRtcSpl_Resample16khzTo22khz(samplesIn + i, samplesOut + (i * 11) / 8,
709                                               (WebRtcSpl_State16khzTo22khz *)state1_,
710                                               tmp_mem);
711            }
712            outLen = (lengthIn * 11) / 8;
713            free(tmp_mem);
714            return 0;
715
716        case kResamplerMode11To16:
717            // We can only handle blocks of 110 samples
718            if ((lengthIn % 110) != 0)
719            {
720                return -1;
721            }
722            if (maxLen < ((lengthIn * 16) / 11))
723            {
724                return -1;
725            }
726
727            tmp_mem = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32));
728            tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn * 2));
729
730            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
731
732            for (int i = 0; i < (lengthIn * 2); i += 220)
733            {
734                WebRtcSpl_Resample22khzTo16khz(tmp + i, samplesOut + (i / 220) * 160,
735                                               (WebRtcSpl_State22khzTo16khz *)state2_,
736                                               tmp_mem);
737            }
738
739            outLen = (lengthIn * 16) / 11;
740
741            free(tmp_mem);
742            free(tmp);
743            return 0;
744
745        case kResamplerMode11To32:
746
747            // We can only handle blocks of 110 samples
748            if ((lengthIn % 110) != 0)
749            {
750                return -1;
751            }
752            if (maxLen < ((lengthIn * 32) / 11))
753            {
754                return -1;
755            }
756
757            tmp_mem = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32));
758            tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn * 2));
759
760            // 11 -> 22 kHz in samplesOut
761            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)state1_);
762
763            // 22 -> 16 in tmp
764            for (int i = 0; i < (lengthIn * 2); i += 220)
765            {
766                WebRtcSpl_Resample22khzTo16khz(samplesOut + i, tmp + (i / 220) * 160,
767                                               (WebRtcSpl_State22khzTo16khz *)state2_,
768                                               tmp_mem);
769            }
770
771            // 16 -> 32 in samplesOut
772            WebRtcSpl_UpsampleBy2(tmp, (lengthIn * 16) / 11, samplesOut,
773                                  (WebRtc_Word32*)state3_);
774
775            outLen = (lengthIn * 32) / 11;
776
777            free(tmp_mem);
778            free(tmp);
779            return 0;
780
781        case kResamplerMode2To1:
782            if (maxLen < (lengthIn / 2))
783            {
784                return -1;
785            }
786            WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, samplesOut, (WebRtc_Word32*)state1_);
787            outLen = lengthIn / 2;
788            return 0;
789        case kResamplerMode3To1:
790            // We can only handle blocks of 480 samples
791            // Can be fixed, but I don't think it's needed
792            if ((lengthIn % 480) != 0)
793            {
794                return -1;
795            }
796            if (maxLen < (lengthIn / 3))
797            {
798                return -1;
799            }
800            tmp_mem = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32));
801
802            for (int i = 0; i < lengthIn; i += 480)
803            {
804                WebRtcSpl_Resample48khzTo16khz(samplesIn + i, samplesOut + i / 3,
805                                               (WebRtcSpl_State48khzTo16khz *)state1_,
806                                               tmp_mem);
807            }
808            outLen = lengthIn / 3;
809            free(tmp_mem);
810            return 0;
811        case kResamplerMode4To1:
812            if (maxLen < (lengthIn / 4))
813            {
814                return -1;
815            }
816            tmp = (WebRtc_Word16*)malloc(sizeof(WebRtc_Word16) * lengthIn / 2);
817            // 4:2
818            WebRtcSpl_DownsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
819            // 2:1
820            WebRtcSpl_DownsampleBy2(tmp, lengthIn / 2, samplesOut, (WebRtc_Word32*)state2_);
821            outLen = lengthIn / 4;
822            free(tmp);
823            return 0;
824
825        case kResamplerMode6To1:
826            // We can only handle blocks of 480 samples
827            // Can be fixed, but I don't think it's needed
828            if ((lengthIn % 480) != 0)
829            {
830                return -1;
831            }
832            if (maxLen < (lengthIn / 6))
833            {
834                return -1;
835            }
836
837            tmp_mem = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32));
838            tmp = (WebRtc_Word16*)malloc((sizeof(WebRtc_Word16) * lengthIn) / 3);
839
840            for (int i = 0; i < lengthIn; i += 480)
841            {
842                WebRtcSpl_Resample48khzTo16khz(samplesIn + i, tmp + i / 3,
843                                               (WebRtcSpl_State48khzTo16khz *)state1_,
844                                               tmp_mem);
845            }
846            outLen = lengthIn / 3;
847            free(tmp_mem);
848            WebRtcSpl_DownsampleBy2(tmp, outLen, samplesOut, (WebRtc_Word32*)state2_);
849            free(tmp);
850            outLen = outLen / 2;
851            return 0;
852        case kResamplerMode12To1:
853            // We can only handle blocks of 480 samples
854            // Can be fixed, but I don't think it's needed
855            if ((lengthIn % 480) != 0) {
856              return -1;
857            }
858            if (maxLen < (lengthIn / 12)) {
859              return -1;
860            }
861
862            tmp_mem = (WebRtc_Word32*) malloc(496 * sizeof(WebRtc_Word32));
863            tmp = (WebRtc_Word16*) malloc((sizeof(WebRtc_Word16) * lengthIn) / 3);
864            tmp_2 = (WebRtc_Word16*) malloc((sizeof(WebRtc_Word16) * lengthIn) / 6);
865            // 12:4
866            for (int i = 0; i < lengthIn; i += 480) {
867              // WebRtcSpl_Resample48khzTo16khz() takes a block of 480 samples
868              // as input and outputs a resampled block of 160 samples. The
869              // data is now actually in 96 kHz sampling rate, despite the
870              // function name, and with a resampling factor of 1/3 becomes
871              // 32 kHz.
872              WebRtcSpl_Resample48khzTo16khz(samplesIn + i, tmp + i / 3,
873                                             (WebRtcSpl_State48khzTo16khz*) state1_,
874                                             tmp_mem);
875            }
876            outLen = lengthIn / 3;
877            free(tmp_mem);
878            // 4:2
879            WebRtcSpl_DownsampleBy2(tmp, outLen, tmp_2,
880                                    (WebRtc_Word32*) state2_);
881            outLen = outLen / 2;
882            free(tmp);
883            // 2:1
884            WebRtcSpl_DownsampleBy2(tmp_2, outLen, samplesOut,
885                                    (WebRtc_Word32*) state3_);
886            free(tmp_2);
887            outLen = outLen / 2;
888            return 0;
889        case kResamplerMode3To2:
890            if (maxLen < (lengthIn * 2 / 3))
891            {
892                return -1;
893            }
894            // 3:6
895            tmp = static_cast<WebRtc_Word16*> (malloc(sizeof(WebRtc_Word16) * lengthIn * 2));
896            WebRtcSpl_UpsampleBy2(samplesIn, lengthIn, tmp, (WebRtc_Word32*)state1_);
897            lengthIn *= 2;
898            // 6:2
899            // We can only handle blocks of 480 samples
900            // Can be fixed, but I don't think it's needed
901            if ((lengthIn % 480) != 0)
902            {
903                free(tmp);
904                return -1;
905            }
906            tmp_mem = (WebRtc_Word32*)malloc(496 * sizeof(WebRtc_Word32));
907            for (int i = 0; i < lengthIn; i += 480)
908            {
909                WebRtcSpl_Resample48khzTo16khz(tmp + i, samplesOut + i / 3,
910                                               (WebRtcSpl_State48khzTo16khz *)state2_,
911                                               tmp_mem);
912            }
913            outLen = lengthIn / 3;
914            free(tmp);
915            free(tmp_mem);
916            return 0;
917        case kResamplerMode11To2:
918            // We can only handle blocks of 220 samples
919            // Can be fixed, but I don't think it's needed
920            if ((lengthIn % 220) != 0)
921            {
922                return -1;
923            }
924            if (maxLen < ((lengthIn * 2) / 11))
925            {
926                return -1;
927            }
928            tmp_mem = (WebRtc_Word32*)malloc(126 * sizeof(WebRtc_Word32));
929            tmp = (WebRtc_Word16*)malloc((lengthIn * 4) / 11 * sizeof(WebRtc_Word16));
930
931            for (int i = 0; i < lengthIn; i += 220)
932            {
933                WebRtcSpl_Resample22khzTo8khz(samplesIn + i, tmp + (i * 4) / 11,
934                                              (WebRtcSpl_State22khzTo8khz *)state1_,
935                                              tmp_mem);
936            }
937            lengthIn = (lengthIn * 4) / 11;
938
939            WebRtcSpl_DownsampleBy2(tmp, lengthIn, samplesOut, (WebRtc_Word32*)state2_);
940            outLen = lengthIn / 2;
941
942            free(tmp_mem);
943            free(tmp);
944            return 0;
945        case kResamplerMode11To4:
946            // We can only handle blocks of 220 samples
947            // Can be fixed, but I don't think it's needed
948            if ((lengthIn % 220) != 0)
949            {
950                return -1;
951            }
952            if (maxLen < ((lengthIn * 4) / 11))
953            {
954                return -1;
955            }
956            tmp_mem = (WebRtc_Word32*)malloc(126 * sizeof(WebRtc_Word32));
957
958            for (int i = 0; i < lengthIn; i += 220)
959            {
960                WebRtcSpl_Resample22khzTo8khz(samplesIn + i, samplesOut + (i * 4) / 11,
961                                              (WebRtcSpl_State22khzTo8khz *)state1_,
962                                              tmp_mem);
963            }
964            outLen = (lengthIn * 4) / 11;
965            free(tmp_mem);
966            return 0;
967        case kResamplerMode11To8:
968            // We can only handle blocks of 160 samples
969            // Can be fixed, but I don't think it's needed
970            if ((lengthIn % 220) != 0)
971            {
972                return -1;
973            }
974            if (maxLen < ((lengthIn * 8) / 11))
975            {
976                return -1;
977            }
978            tmp_mem = (WebRtc_Word32*)malloc(104 * sizeof(WebRtc_Word32));
979
980            for (int i = 0; i < lengthIn; i += 220)
981            {
982                WebRtcSpl_Resample22khzTo16khz(samplesIn + i, samplesOut + (i * 8) / 11,
983                                               (WebRtcSpl_State22khzTo16khz *)state1_,
984                                               tmp_mem);
985            }
986            outLen = (lengthIn * 8) / 11;
987            free(tmp_mem);
988            return 0;
989            break;
990
991    }
992    return 0;
993}
994
995// Asynchronous resampling, input
996int Resampler::Insert(WebRtc_Word16 * samplesIn, int lengthIn)
997{
998    if (my_type_ != kResamplerAsynchronous)
999    {
1000        return -1;
1001    }
1002    int sizeNeeded, tenMsblock;
1003
1004    // Determine need for size of outBuffer
1005    sizeNeeded = out_buffer_size_ + ((lengthIn + in_buffer_size_) * my_out_frequency_khz_)
1006            / my_in_frequency_khz_;
1007    if (sizeNeeded > out_buffer_size_max_)
1008    {
1009        // Round the value upwards to complete 10 ms blocks
1010        tenMsblock = my_out_frequency_khz_ * 10;
1011        sizeNeeded = (sizeNeeded / tenMsblock + 1) * tenMsblock;
1012        out_buffer_ = (WebRtc_Word16*)realloc(out_buffer_, sizeNeeded * sizeof(WebRtc_Word16));
1013        out_buffer_size_max_ = sizeNeeded;
1014    }
1015
1016    // If we need to use inBuffer, make sure all input data fits there.
1017
1018    tenMsblock = my_in_frequency_khz_ * 10;
1019    if (in_buffer_size_ || (lengthIn % tenMsblock))
1020    {
1021        // Check if input buffer size is enough
1022        if ((in_buffer_size_ + lengthIn) > in_buffer_size_max_)
1023        {
1024            // Round the value upwards to complete 10 ms blocks
1025            sizeNeeded = ((in_buffer_size_ + lengthIn) / tenMsblock + 1) * tenMsblock;
1026            in_buffer_ = (WebRtc_Word16*)realloc(in_buffer_,
1027                                                 sizeNeeded * sizeof(WebRtc_Word16));
1028            in_buffer_size_max_ = sizeNeeded;
1029        }
1030        // Copy in data to input buffer
1031        memcpy(in_buffer_ + in_buffer_size_, samplesIn, lengthIn * sizeof(WebRtc_Word16));
1032
1033        // Resample all available 10 ms blocks
1034        int lenOut;
1035        int dataLenToResample = (in_buffer_size_ / tenMsblock) * tenMsblock;
1036        Push(in_buffer_, dataLenToResample, out_buffer_ + out_buffer_size_,
1037             out_buffer_size_max_ - out_buffer_size_, lenOut);
1038        out_buffer_size_ += lenOut;
1039
1040        // Save the rest
1041        memmove(in_buffer_, in_buffer_ + dataLenToResample,
1042                (in_buffer_size_ - dataLenToResample) * sizeof(WebRtc_Word16));
1043        in_buffer_size_ -= dataLenToResample;
1044    } else
1045    {
1046        // Just resample
1047        int lenOut;
1048        Push(in_buffer_, lengthIn, out_buffer_ + out_buffer_size_,
1049             out_buffer_size_max_ - out_buffer_size_, lenOut);
1050        out_buffer_size_ += lenOut;
1051    }
1052
1053    return 0;
1054}
1055
1056// Asynchronous resampling output, remaining samples are buffered
1057int Resampler::Pull(WebRtc_Word16* samplesOut, int desiredLen, int &outLen)
1058{
1059    if (my_type_ != kResamplerAsynchronous)
1060    {
1061        return -1;
1062    }
1063
1064    // Check that we have enough data
1065    if (desiredLen <= out_buffer_size_)
1066    {
1067        // Give out the date
1068        memcpy(samplesOut, out_buffer_, desiredLen * sizeof(WebRtc_Word32));
1069
1070        // Shuffle down remaining
1071        memmove(out_buffer_, out_buffer_ + desiredLen,
1072                (out_buffer_size_ - desiredLen) * sizeof(WebRtc_Word16));
1073
1074        // Update remaining size
1075        out_buffer_size_ -= desiredLen;
1076
1077        return 0;
1078    } else
1079    {
1080        return -1;
1081    }
1082}
1083
1084} // namespace webrtc
1085