diff options
Diffstat (limited to 'lib/rbcodec/dsp/dsp_sample_input.c')
-rw-r--r-- | lib/rbcodec/dsp/dsp_sample_input.c | 334 |
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 | |||
51 | extern void dsp_sample_output_init(struct sample_io_data *this); | ||
52 | extern void dsp_sample_output_flush(struct sample_io_data *this); | ||
53 | |||
54 | /* convert count 16-bit mono to 32-bit mono */ | ||
55 | static 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 */ | ||
90 | static 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 */ | ||
127 | static 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 */ | ||
165 | static 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 */ | ||
183 | static 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 */ | ||
219 | static 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 */ | ||
231 | static 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 | |||
272 | static 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 */ | ||
279 | static void dsp_sample_input_flush(struct sample_io_data *this) | ||
280 | { | ||
281 | this->sample_buf.remcount = 0; | ||
282 | } | ||
283 | |||
284 | void 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 | } | ||