Properly quote variable used as arg to test -n to fix errors like: /bin/bash: line...
[gnash.git] / libmedia / AudioResampler.cpp
blobaddb4984a5a86b0813f2361472d37cb99082c45f
1 // AudioResampler.cpp -- custom audio resampler
2 //
3 // Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 Free Software
4 // Foundation, Inc
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 #include "AudioResampler.h"
22 #include <cstring>
23 #include <cassert>
25 namespace gnash {
26 namespace media {
28 void
29 AudioResampler::convert_raw_data(
30 boost::int16_t** adjusted_data,
31 int* adjusted_size,
32 void* data,
33 int sample_count, // A stereo pair counts as one
34 int sample_size, // Should now always == 2
35 // sample_rate and stereo are those of the incoming sample
36 int sample_rate,
37 bool stereo,
38 // m_sample_rate, m_stereo are the format we must convert to.
39 int m_sample_rate,
40 bool m_stereo)
43 assert(sample_size == 2); // at least it seems the code relies on this...
45 // simple hack to handle dup'ing mono to stereo
46 if ( !stereo && m_stereo)
48 sample_rate >>= 1;
51 // simple hack to lose half the samples to get mono from stereo
52 if ( stereo && !m_stereo)
54 sample_rate <<= 1;
57 // Brain-dead sample-rate conversion: duplicate or
58 // skip input samples an integral number of times.
59 int inc = 1; // increment
60 int dup = 1; // duplicate
61 if (sample_rate > m_sample_rate)
63 inc = sample_rate / m_sample_rate;
65 else if (sample_rate < m_sample_rate)
67 dup = m_sample_rate / sample_rate;
70 int output_sample_count = (sample_count * dup * (stereo ? 2 : 1)) / inc;
71 boost::int16_t* out_data = new boost::int16_t[output_sample_count];
72 *adjusted_data = out_data;
73 *adjusted_size = output_sample_count * sizeof(boost::int16_t); // in bytes
75 // Either inc > 1 (decimate the audio)
76 // or dup > 1 (repeat samples)
77 // or both == 1 (no transformation required)
78 if (inc == 1 && dup == 1)
80 // No tranformation required
81 std::memcpy(out_data, data, output_sample_count * sizeof(boost::int16_t));
83 else if (inc > 1)
85 // Downsample by skipping samples from the input
86 boost::int16_t* in = (boost::int16_t*) data;
87 for (int i = output_sample_count; i > 0; i--)
89 *out_data++ = *in;
90 in += inc;
93 else if (dup > 1)
95 // Upsample by duplicating input samples in the output.
97 // The straight sample-replication code handles mono-to-stereo (sort of)
98 // and upsampling of mono but would make a botch of stereo-to-stereo
99 // upsampling, giving the left sample in both channels
100 // then the right sample in both channels alternately.
101 // So for stereo-stereo transforms we have a stereo routine.
103 boost::int16_t* in = (boost::int16_t*) data;
105 if (stereo && m_stereo) {
106 // Stereo-to-stereo upsampling: Replicate pairs of samples
107 for (int i = output_sample_count / dup / 2; i > 0; i--)
109 for (int j = dup; j > 0; j--)
111 out_data[0] = in[0];
112 out_data[1] = in[1];
113 out_data += 2;
115 in += 2;
117 } else {
119 // Linear upsampling, either to increase a sample rate
120 // or to convert a mono file to stereo or both:
121 // replicate each sample several times.
122 switch (dup)
124 case 2:
125 for (int i = output_sample_count / dup; i > 0; i--)
127 *out_data++ = *in;
128 *out_data++ = *in;
129 in++;
131 break;
132 case 4:
133 for (int i = output_sample_count / dup; i > 0; i--)
135 *out_data++ = *in;
136 *out_data++ = *in;
137 *out_data++ = *in;
138 *out_data++ = *in;
139 in++;
141 break;
142 default:
143 for (int i = output_sample_count / dup; i > 0; i--)
145 for (int j = dup; j > 0; j--)
147 *out_data++ = *in;
149 in++;
151 break;
157 } // namespace media
158 } // namespace gnash
160 // Local Variables:
161 // mode: C++
162 // indent-tabs-mode: t
163 // End: