summaryrefslogtreecommitdiff
path: root/lib/rbcodec/dsp/dsp_sample_input.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/dsp/dsp_sample_input.c')
-rw-r--r--lib/rbcodec/dsp/dsp_sample_input.c334
1 files changed, 334 insertions, 0 deletions
diff --git a/lib/rbcodec/dsp/dsp_sample_input.c b/lib/rbcodec/dsp/dsp_sample_input.c
new file mode 100644
index 0000000000..84127e1f96
--- /dev/null
+++ b/lib/rbcodec/dsp/dsp_sample_input.c
@@ -0,0 +1,334 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2005 Miika Pekkarinen
11 * Copyright (C) 2012 Michael Sevakis
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
20 *
21 ****************************************************************************/
22#include "config.h"
23#include "system.h"
24#include "dsp.h"
25#include "dsp_sample_io.h"
26
27#if 1
28#include <debug.h>
29#else
30#undef DEBUGF
31#define DEBUGF(...)
32#endif
33
34/* The internal format is 32-bit samples, non-interleaved, stereo. This
35 * format is similar to the raw output from several codecs, so no copying is
36 * needed for that case.
37 *
38 * Note that for mono, dst[0] equals dst[1], as there is no point in
39 * processing the same data twice nor should it be done when modifying
40 * samples in-place.
41 *
42 * When conversion is required:
43 * Updates source buffer to point past the samples "consumed" also consuming
44 * that portion of the input buffer and the destination is set to the buffer
45 * of samples for later stages to consume.
46 *
47 * Input operates similarly to how an out-of-place processing stage should
48 * behave.
49 */
50
51extern void dsp_sample_output_init(struct sample_io_data *this);
52extern void dsp_sample_output_flush(struct sample_io_data *this);
53
54/* convert count 16-bit mono to 32-bit mono */
55static void sample_input_mono16(struct sample_io_data *this,
56 struct dsp_buffer **buf_p)
57{
58 struct dsp_buffer *src = *buf_p;
59 struct dsp_buffer *dst = &this->sample_buf;
60
61 *buf_p = dst;
62
63 if (dst->remcount > 0)
64 return; /* data still remains */
65
66 int count = MIN(src->remcount, SAMPLE_BUF_COUNT);
67
68 dst->remcount = count;
69 dst->p32[0] = this->sample_buf_arr[0];
70 dst->p32[1] = this->sample_buf_arr[0];
71 dst->proc_mask = src->proc_mask;
72
73 if (count <= 0)
74 return; /* purged sample_buf */
75
76 const int16_t *s = src->pin[0];
77 int32_t *d = dst->p32[0];
78 const int scale = WORD_SHIFT;
79
80 dsp_advance_buffer_input(src, count, sizeof (int16_t));
81
82 do
83 {
84 *d++ = *s++ << scale;
85 }
86 while (--count > 0);
87}
88
89/* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
90static void sample_input_i_stereo16(struct sample_io_data *this,
91 struct dsp_buffer **buf_p)
92{
93 struct dsp_buffer *src = *buf_p;
94 struct dsp_buffer *dst = &this->sample_buf;
95
96 *buf_p = dst;
97
98 if (dst->remcount > 0)
99 return; /* data still remains */
100
101 int count = MIN(src->remcount, SAMPLE_BUF_COUNT);
102
103 dst->remcount = count;
104 dst->p32[0] = this->sample_buf_arr[0];
105 dst->p32[1] = this->sample_buf_arr[1];
106 dst->proc_mask = src->proc_mask;
107
108 if (count <= 0)
109 return; /* purged sample_buf */
110
111 const int16_t *s = src->pin[0];
112 int32_t *dl = dst->p32[0];
113 int32_t *dr = dst->p32[1];
114 const int scale = WORD_SHIFT;
115
116 dsp_advance_buffer_input(src, count, 2*sizeof (int16_t));
117
118 do
119 {
120 *dl++ = *s++ << scale;
121 *dr++ = *s++ << scale;
122 }
123 while (--count > 0);
124}
125
126/* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
127static void sample_input_ni_stereo16(struct sample_io_data *this,
128 struct dsp_buffer **buf_p)
129{
130 struct dsp_buffer *src = *buf_p;
131 struct dsp_buffer *dst = &this->sample_buf;
132
133 *buf_p = dst;
134
135 if (dst->remcount > 0)
136 return; /* data still remains */
137
138 int count = MIN(src->remcount, SAMPLE_BUF_COUNT);
139
140 dst->remcount = count;
141 dst->p32[0] = this->sample_buf_arr[0];
142 dst->p32[1] = this->sample_buf_arr[1];
143 dst->proc_mask = src->proc_mask;
144
145 if (count <= 0)
146 return; /* purged sample_buf */
147
148 const int16_t *sl = src->pin[0];
149 const int16_t *sr = src->pin[1];
150 int32_t *dl = dst->p32[0];
151 int32_t *dr = dst->p32[1];
152 const int scale = WORD_SHIFT;
153
154 dsp_advance_buffer_input(src, count, sizeof (int16_t));
155
156 do
157 {
158 *dl++ = *sl++ << scale;
159 *dr++ = *sr++ << scale;
160 }
161 while (--count > 0);
162}
163
164/* convert count 32-bit mono to 32-bit mono */
165static void sample_input_mono32(struct sample_io_data *this,
166 struct dsp_buffer **buf_p)
167{
168 struct dsp_buffer *dst = &this->sample_buf;
169
170 if (dst->remcount > 0)
171 {
172 *buf_p = dst;
173 return; /* data still remains */
174 }
175 /* else no buffer switch */
176
177 struct dsp_buffer *src = *buf_p;
178 src->p32[1] = src->p32[0];
179}
180
181
182/* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
183static void sample_input_i_stereo32(struct sample_io_data *this,
184 struct dsp_buffer **buf_p)
185{
186 struct dsp_buffer *src = *buf_p;
187 struct dsp_buffer *dst = &this->sample_buf;
188
189 *buf_p = dst;
190
191 if (dst->remcount > 0)
192 return; /* data still remains */
193
194 int count = MIN(src->remcount, SAMPLE_BUF_COUNT);
195
196 dst->remcount = count;
197 dst->p32[0] = this->sample_buf_arr[0];
198 dst->p32[1] = this->sample_buf_arr[1];
199 dst->proc_mask = src->proc_mask;
200
201 if (count <= 0)
202 return; /* purged sample_buf */
203
204 const int32_t *s = src->pin[0];
205 int32_t *dl = dst->p32[0];
206 int32_t *dr = dst->p32[1];
207
208 dsp_advance_buffer_input(src, count, 2*sizeof (int32_t));
209
210 do
211 {
212 *dl++ = *s++;
213 *dr++ = *s++;
214 }
215 while (--count > 0);
216}
217
218/* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
219static void sample_input_ni_stereo32(struct sample_io_data *this,
220 struct dsp_buffer **buf_p)
221{
222 struct dsp_buffer *dst = &this->sample_buf;
223
224 if (dst->remcount > 0)
225 *buf_p = dst; /* data still remains */
226 /* else no buffer switch */
227}
228
229/* set the to-native sample conversion function based on dsp sample
230 * parameters */
231static void dsp_sample_input_format_change(struct sample_io_data *this,
232 struct dsp_buffer **buf_p)
233{
234 static const sample_input_fn_type fns[STEREO_NUM_MODES][2] =
235 {
236 [STEREO_INTERLEAVED] =
237 { sample_input_i_stereo16,
238 sample_input_i_stereo32 },
239 [STEREO_NONINTERLEAVED] =
240 { sample_input_ni_stereo16,
241 sample_input_ni_stereo32 },
242 [STEREO_MONO] =
243 { sample_input_mono16,
244 sample_input_mono32 },
245 };
246
247 struct dsp_buffer *src = *buf_p;
248 struct dsp_buffer *dst = &this->sample_buf;
249
250 /* Ack configured format change */
251 format_change_ack(&this->format);
252
253 if (dst->remcount > 0)
254 {
255 *buf_p = dst;
256 return; /* data still remains */
257 }
258
259 DSP_PRINT_FORMAT(DSP Input, -1, src->format);
260
261 /* new format - remember it and pass it along */
262 dst->format = src->format;
263 this->input_samples[0] = fns[this->stereo_mode]
264 [this->sample_depth > NATIVE_DEPTH ? 1 : 0];
265
266 this->input_samples[0](this, buf_p);
267
268 if (*buf_p == dst) /* buffer switch? */
269 format_change_ack(&src->format);
270}
271
272static void dsp_sample_input_init(struct sample_io_data *this)
273{
274 this->input_samples[0] = sample_input_ni_stereo32;
275 this->input_samples[1] = dsp_sample_input_format_change;
276}
277
278/* discard the sample buffer */
279static void dsp_sample_input_flush(struct sample_io_data *this)
280{
281 this->sample_buf.remcount = 0;
282}
283
284void dsp_sample_io_configure(struct sample_io_data *this,
285 unsigned int setting,
286 intptr_t value)
287{
288 switch (setting)
289 {
290 case DSP_INIT:
291 dsp_sample_input_init(this);
292 dsp_sample_output_init(this);
293 break;
294
295 case DSP_RESET:
296 /* Reset all sample descriptions to default */
297 format_change_set(&this->format);
298 this->format.num_channels = 2;
299 this->format.frac_bits = WORD_FRACBITS;
300 this->format.output_scale = WORD_FRACBITS + 1 - NATIVE_DEPTH;
301 this->format.frequency = NATIVE_FREQUENCY;
302 this->format.codec_frequency = NATIVE_FREQUENCY;
303 this->sample_depth = NATIVE_DEPTH;
304 this->stereo_mode = STEREO_NONINTERLEAVED;
305 break;
306
307 case DSP_SET_FREQUENCY:
308 value = value > 0 ? value : NATIVE_FREQUENCY;
309 format_change_set(&this->format);
310 this->format.frequency = value;
311 this->format.codec_frequency = value;
312 break;
313
314 case DSP_SET_SAMPLE_DEPTH:
315 format_change_set(&this->format);
316 this->format.frac_bits =
317 value <= NATIVE_DEPTH ? WORD_FRACBITS : value;
318 this->format.output_scale =
319 this->format.frac_bits + 1 - NATIVE_DEPTH;
320 this->sample_depth = value;
321 break;
322
323 case DSP_SET_STEREO_MODE:
324 format_change_set(&this->format);
325 this->format.num_channels = value == STEREO_MONO ? 1 : 2;
326 this->stereo_mode = value;
327 break;
328
329 case DSP_FLUSH:
330 dsp_sample_input_flush(this);
331 dsp_sample_output_flush(this);
332 break;
333 }
334}