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 #include <assert.h>
19
20 #include "webrtc/common_audio/resampler/include/resampler.h"
21 #include "webrtc/common_audio/signal_processing/include/signal_processing_library.h"
22
23 // TODO(jesup) better adjust per platform ability
24 // Note: if these are changed (higher), you may need to change the
25 // KernelDelay values in the unit tests here and in output_mixer.
26 #if defined(WEBRTC_ANDROID)
27 #define RESAMPLER_QUALITY 2
28 #else
29 #define RESAMPLER_QUALITY 3
30 #endif
31
32 namespace webrtc {
33
Resampler()34 Resampler::Resampler() : state_(NULL), channels_(0)
35 {
36 // Note: Push will fail until Reset() is called
37 }
38
Resampler(int inFreq,int outFreq,size_t num_channels)39 Resampler::Resampler(int inFreq, int outFreq, size_t num_channels)
40 : Resampler() {
41 Reset(inFreq, outFreq, num_channels);
42 }
43
~Resampler()44 Resampler::~Resampler()
45 {
46 if (state_)
47 {
48 speex_resampler_destroy(state_);
49 }
50 }
51
ResetIfNeeded(int inFreq,int outFreq,size_t num_channels)52 int Resampler::ResetIfNeeded(int inFreq, int outFreq, size_t num_channels)
53 {
54 if (!state_ || channels_ != num_channels ||
55 inFreq != in_freq_ || outFreq != out_freq_)
56 {
57 // Note that fixed-rate resamplers where input == output rate will
58 // have state_ == NULL, and will call Reset() here - but reset won't
59 // do anything beyond overwrite the member vars unless it needs a
60 // real resampler.
61 return Reset(inFreq, outFreq, num_channels);
62 } else {
63 return 0;
64 }
65 }
66
Reset(int inFreq,int outFreq,size_t num_channels)67 int Resampler::Reset(int inFreq, int outFreq, size_t num_channels)
68 {
69 if (num_channels != 1 && num_channels != 2) {
70 return -1;
71 }
72
73 if (state_)
74 {
75 speex_resampler_destroy(state_);
76 state_ = NULL;
77 }
78 channels_ = num_channels;
79 in_freq_ = inFreq;
80 out_freq_ = outFreq;
81
82 // For fixed-rate, same-rate resamples we just memcpy and so don't spin up a resampler
83 if (inFreq != outFreq)
84 {
85 state_ = speex_resampler_init(num_channels, inFreq, outFreq, RESAMPLER_QUALITY, NULL);
86 if (!state_)
87 {
88 return -1;
89 }
90 }
91 return 0;
92 }
93
94 // Synchronous resampling, all output samples are written to samplesOut
95 // TODO(jesup) Change to take samples-per-channel in and out
Push(const int16_t * samplesIn,size_t lengthIn,int16_t * samplesOut,size_t maxLen,size_t & outLen)96 int Resampler::Push(const int16_t* samplesIn, size_t lengthIn, int16_t* samplesOut,
97 size_t maxLen, size_t &outLen)
98 {
99 if (maxLen < lengthIn)
100 {
101 return -1;
102 }
103 if (!state_)
104 {
105 if (in_freq_ != out_freq_ || channels_ == 0)
106 {
107 // Push() will fail until Reset() is called
108 return -1;
109 }
110 // Same-freq "resample" - use memcpy, which avoids
111 // filtering and delay. For non-fixed rates, where we might tweak
112 // from 48000->48000 to 48000->48001 for drift, we need to resample
113 // (and filter) all the time to avoid glitches on rate changes.
114 memcpy(samplesOut, samplesIn, lengthIn*sizeof(*samplesIn));
115 outLen = lengthIn;
116 return 0;
117 }
118 assert(channels_ == 1 || channels_ == 2);
119 spx_uint32_t len = lengthIn = (lengthIn >> (channels_ - 1));
120 spx_uint32_t out = (spx_uint32_t) (maxLen >> (channels_ - 1));
121 if ((speex_resampler_process_interleaved_int(state_, samplesIn, &len,
122 samplesOut, &out) != RESAMPLER_ERR_SUCCESS) ||
123 len != (spx_uint32_t) lengthIn)
124 {
125 return -1;
126 }
127 outLen = (int) (channels_ * out);
128 return 0;
129 }
130 }// namespace webrtc
131