diff options
Diffstat (limited to 'apps/dsp.c')
-rw-r--r-- | apps/dsp.c | 354 |
1 files changed, 170 insertions, 184 deletions
diff --git a/apps/dsp.c b/apps/dsp.c index be851e2305..3b95145b39 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -38,9 +38,14 @@ | |||
38 | #define WORD_FRACBITS 27 | 38 | #define WORD_FRACBITS 27 |
39 | 39 | ||
40 | #define NATIVE_DEPTH 16 | 40 | #define NATIVE_DEPTH 16 |
41 | /* If the buffer sizes change, check the assembly code! */ | ||
41 | #define SAMPLE_BUF_COUNT 256 | 42 | #define SAMPLE_BUF_COUNT 256 |
42 | #define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ | 43 | #define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ |
43 | #define DEFAULT_GAIN 0x01000000 | 44 | #define DEFAULT_GAIN 0x01000000 |
45 | #define SAMPLE_BUF_LEFT_CHANNEL 0 | ||
46 | #define SAMPLE_BUF_RIGHT_CHANNEL (SAMPLE_BUF_COUNT/2) | ||
47 | #define RESAMPLE_BUF_LEFT_CHANNEL 0 | ||
48 | #define RESAMPLE_BUF_RIGHT_CHANNEL (RESAMPLE_BUF_COUNT/2) | ||
44 | 49 | ||
45 | /* enums to index conversion properly with stereo mode and other settings */ | 50 | /* enums to index conversion properly with stereo mode and other settings */ |
46 | enum | 51 | enum |
@@ -66,11 +71,10 @@ enum | |||
66 | * NOTE: Any assembly routines that use these structures must be updated | 71 | * NOTE: Any assembly routines that use these structures must be updated |
67 | * if current data members are moved or changed. | 72 | * if current data members are moved or changed. |
68 | */ | 73 | */ |
69 | /* 32-bit achitecture offset */ | ||
70 | struct resample_data | 74 | struct resample_data |
71 | { | 75 | { |
72 | long delta; /* 00h */ | 76 | uint32_t delta; /* 00h */ |
73 | long phase; /* 04h */ | 77 | uint32_t phase; /* 04h */ |
74 | int32_t last_sample[2]; /* 08h */ | 78 | int32_t last_sample[2]; /* 08h */ |
75 | /* 10h */ | 79 | /* 10h */ |
76 | }; | 80 | }; |
@@ -93,9 +97,10 @@ struct dsp_data | |||
93 | int output_scale; /* 00h */ | 97 | int output_scale; /* 00h */ |
94 | int num_channels; /* 04h */ | 98 | int num_channels; /* 04h */ |
95 | struct resample_data resample_data; /* 08h */ | 99 | struct resample_data resample_data; /* 08h */ |
96 | int clip_min; /* 18h */ | 100 | int32_t clip_min; /* 18h */ |
97 | int clip_max; /* 2ch */ | 101 | int32_t clip_max; /* 1ch */ |
98 | /* 30h */ | 102 | int32_t gain; /* 20h - Note that this is in S8.23 format. */ |
103 | /* 24h */ | ||
99 | }; | 104 | }; |
100 | 105 | ||
101 | /* No asm...yet */ | 106 | /* No asm...yet */ |
@@ -132,13 +137,18 @@ struct eq_state | |||
132 | #include <dsp_asm.h> | 137 | #include <dsp_asm.h> |
133 | 138 | ||
134 | /* Typedefs keep things much neater in this case */ | 139 | /* Typedefs keep things much neater in this case */ |
135 | typedef int (*sample_input_fn_type)(int count, const char *src[], | 140 | typedef void (*sample_input_fn_type)(int count, const char *src[], |
136 | int32_t *dst[]); | 141 | int32_t *dst[]); |
137 | typedef int (*resample_fn_type)(int count, struct dsp_data *data, | 142 | typedef int (*resample_fn_type)(int count, struct dsp_data *data, |
138 | int32_t *src[], int32_t *dst[]); | 143 | int32_t *src[], int32_t *dst[]); |
139 | typedef void (*sample_output_fn_type)(int count, struct dsp_data *data, | 144 | typedef void (*sample_output_fn_type)(int count, struct dsp_data *data, |
140 | int32_t *src[], int16_t *dst); | 145 | int32_t *src[], int16_t *dst); |
146 | /* Single-DSP channel processing in place */ | ||
141 | typedef void (*channels_process_fn_type)(int count, int32_t *buf[]); | 147 | typedef void (*channels_process_fn_type)(int count, int32_t *buf[]); |
148 | /* DSP local channel processing in place */ | ||
149 | typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data, | ||
150 | int32_t *buf[]); | ||
151 | |||
142 | 152 | ||
143 | /* | 153 | /* |
144 | ***************************************************************************/ | 154 | ***************************************************************************/ |
@@ -152,16 +162,16 @@ struct dsp_config | |||
152 | int sample_bytes; | 162 | int sample_bytes; |
153 | int stereo_mode; | 163 | int stereo_mode; |
154 | int frac_bits; | 164 | int frac_bits; |
155 | long gain; /* Note that this is in S8.23 format. */ | ||
156 | /* Functions that change depending upon settings - NULL if stage is | 165 | /* Functions that change depending upon settings - NULL if stage is |
157 | disabled */ | 166 | disabled */ |
158 | sample_input_fn_type input_samples; | 167 | sample_input_fn_type input_samples; |
159 | resample_fn_type resample; | 168 | resample_fn_type resample; |
160 | sample_output_fn_type output_samples; | 169 | sample_output_fn_type output_samples; |
161 | /* These will be NULL for the voice codec and is more economical that | 170 | /* These will be NULL for the voice codec and is more economical that |
162 | way */ | 171 | way */ |
163 | channels_process_fn_type apply_crossfeed; | 172 | channels_process_dsp_fn_type apply_gain; |
164 | channels_process_fn_type channels_process; | 173 | channels_process_fn_type apply_crossfeed; |
174 | channels_process_fn_type channels_process; | ||
165 | }; | 175 | }; |
166 | 176 | ||
167 | /* General DSP config */ | 177 | /* General DSP config */ |
@@ -211,7 +221,7 @@ static struct dsp_config *dsp IDATA_ATTR = audio_dsp; | |||
211 | * of copying needed is minimized for that case. | 221 | * of copying needed is minimized for that case. |
212 | */ | 222 | */ |
213 | 223 | ||
214 | static int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR; | 224 | int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR; |
215 | static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR; | 225 | static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR; |
216 | 226 | ||
217 | /* set a new dsp and return old one */ | 227 | /* set a new dsp and return old one */ |
@@ -258,23 +268,20 @@ void sound_set_pitch(int permille) | |||
258 | dsp_configure(DSP_SWITCH_FREQUENCY, dsp->codec_frequency); | 268 | dsp_configure(DSP_SWITCH_FREQUENCY, dsp->codec_frequency); |
259 | } | 269 | } |
260 | 270 | ||
261 | /* Convert at most count samples to the internal format, if needed. Returns | 271 | /* Convert count samples to the internal format, if needed. Updates src |
262 | * number of samples ready for further processing. Updates src to point | 272 | * to point past the samples "consumed" and dst is set to point to the |
263 | * past the samples "consumed" and dst is set to point to the samples to | 273 | * samples to consume. Note that for mono, dst[0] equals dst[1], as there |
264 | * consume. Note that for mono, dst[0] equals dst[1], as there is no point | 274 | * is no point in processing the same data twice. |
265 | * in processing the same data twice. | ||
266 | */ | 275 | */ |
267 | 276 | ||
268 | /* convert count 16-bit mono to 32-bit mono */ | 277 | /* convert count 16-bit mono to 32-bit mono */ |
269 | static int sample_input_lte_native_mono( | 278 | static void sample_input_lte_native_mono( |
270 | int count, const char *src[], int32_t *dst[]) | 279 | int count, const char *src[], int32_t *dst[]) |
271 | { | 280 | { |
272 | count = MIN(SAMPLE_BUF_COUNT/2, count); | ||
273 | |||
274 | const int16_t *s = (int16_t *) src[0]; | 281 | const int16_t *s = (int16_t *) src[0]; |
275 | const int16_t * const send = s + count; | 282 | const int16_t * const send = s + count; |
276 | int32_t *d = dst[0] = dst[1] = sample_buf; | 283 | int32_t *d = dst[0] = dst[1] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL]; |
277 | const int scale = WORD_SHIFT; | 284 | int scale = WORD_SHIFT; |
278 | 285 | ||
279 | do | 286 | do |
280 | { | 287 | { |
@@ -283,21 +290,17 @@ static int sample_input_lte_native_mono( | |||
283 | while (s < send); | 290 | while (s < send); |
284 | 291 | ||
285 | src[0] = (char *)s; | 292 | src[0] = (char *)s; |
286 | |||
287 | return count; | ||
288 | } | 293 | } |
289 | 294 | ||
290 | /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */ | 295 | /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */ |
291 | static int sample_input_lte_native_i_stereo( | 296 | static void sample_input_lte_native_i_stereo( |
292 | int count, const char *src[], int32_t *dst[]) | 297 | int count, const char *src[], int32_t *dst[]) |
293 | { | 298 | { |
294 | count = MIN(SAMPLE_BUF_COUNT/2, count); | ||
295 | |||
296 | const int32_t *s = (int32_t *) src[0]; | 299 | const int32_t *s = (int32_t *) src[0]; |
297 | const int32_t * const send = s + count; | 300 | const int32_t * const send = s + count; |
298 | int32_t *dl = dst[0] = sample_buf; | 301 | int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL]; |
299 | int32_t *dr = dst[1] = sample_buf + SAMPLE_BUF_COUNT/2; | 302 | int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL]; |
300 | const int scale = WORD_SHIFT; | 303 | int scale = WORD_SHIFT; |
301 | 304 | ||
302 | do | 305 | do |
303 | { | 306 | { |
@@ -313,22 +316,18 @@ static int sample_input_lte_native_i_stereo( | |||
313 | while (s < send); | 316 | while (s < send); |
314 | 317 | ||
315 | src[0] = (char *)s; | 318 | src[0] = (char *)s; |
316 | |||
317 | return count; | ||
318 | } | 319 | } |
319 | 320 | ||
320 | /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */ | 321 | /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */ |
321 | static int sample_input_lte_native_ni_stereo( | 322 | static void sample_input_lte_native_ni_stereo( |
322 | int count, const char *src[], int32_t *dst[]) | 323 | int count, const char *src[], int32_t *dst[]) |
323 | { | 324 | { |
324 | count = MIN(SAMPLE_BUF_COUNT/2, count); | ||
325 | |||
326 | const int16_t *sl = (int16_t *) src[0]; | 325 | const int16_t *sl = (int16_t *) src[0]; |
327 | const int16_t *sr = (int16_t *) src[1]; | 326 | const int16_t *sr = (int16_t *) src[1]; |
328 | const int16_t * const slend = sl + count; | 327 | const int16_t * const slend = sl + count; |
329 | int32_t *dl = dst[0] = sample_buf; | 328 | int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL]; |
330 | int32_t *dr = dst[1] = sample_buf + SAMPLE_BUF_COUNT/2; | 329 | int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL]; |
331 | const int scale = WORD_SHIFT; | 330 | int scale = WORD_SHIFT; |
332 | 331 | ||
333 | do | 332 | do |
334 | { | 333 | { |
@@ -339,35 +338,24 @@ static int sample_input_lte_native_ni_stereo( | |||
339 | 338 | ||
340 | src[0] = (char *)sl; | 339 | src[0] = (char *)sl; |
341 | src[1] = (char *)sr; | 340 | src[1] = (char *)sr; |
342 | |||
343 | return count; | ||
344 | } | 341 | } |
345 | 342 | ||
346 | /* convert count 32-bit mono to 32-bit mono */ | 343 | /* convert count 32-bit mono to 32-bit mono */ |
347 | static int sample_input_gt_native_mono( | 344 | static void sample_input_gt_native_mono( |
348 | int count, const char *src[], int32_t *dst[]) | 345 | int count, const char *src[], int32_t *dst[]) |
349 | { | 346 | { |
350 | count = MIN(SAMPLE_BUF_COUNT/2, count); | ||
351 | |||
352 | dst[0] = dst[1] = (int32_t *)src[0]; | 347 | dst[0] = dst[1] = (int32_t *)src[0]; |
353 | src[0] = (char *)(dst[0] + count); | 348 | src[0] = (char *)(dst[0] + count); |
354 | |||
355 | return count; | ||
356 | } | 349 | } |
357 | 350 | ||
358 | /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */ | 351 | /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */ |
359 | static int sample_input_gt_native_i_stereo( | 352 | static void sample_input_gt_native_i_stereo( |
360 | int count, const char *src[], int32_t *dst[]) | 353 | int count, const char *src[], int32_t *dst[]) |
361 | { | 354 | { |
362 | count = MIN(SAMPLE_BUF_COUNT/2, count); | ||
363 | |||
364 | const int32_t *s = (int32_t *)src[0]; | 355 | const int32_t *s = (int32_t *)src[0]; |
365 | const int32_t * const send = s + 2*count; | 356 | const int32_t * const send = s + 2*count; |
366 | int32_t *dl = sample_buf; | 357 | int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL]; |
367 | int32_t *dr = sample_buf + SAMPLE_BUF_COUNT/2; | 358 | int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL]; |
368 | |||
369 | dst[0] = dl; | ||
370 | dst[1] = dr; | ||
371 | 359 | ||
372 | do | 360 | do |
373 | { | 361 | { |
@@ -377,22 +365,16 @@ static int sample_input_gt_native_i_stereo( | |||
377 | while (s < send); | 365 | while (s < send); |
378 | 366 | ||
379 | src[0] = (char *)send; | 367 | src[0] = (char *)send; |
380 | |||
381 | return count; | ||
382 | } | 368 | } |
383 | 369 | ||
384 | /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */ | 370 | /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */ |
385 | static int sample_input_gt_native_ni_stereo( | 371 | static void sample_input_gt_native_ni_stereo( |
386 | int count, const char *src[], int32_t *dst[]) | 372 | int count, const char *src[], int32_t *dst[]) |
387 | { | 373 | { |
388 | count = MIN(SAMPLE_BUF_COUNT/2, count); | ||
389 | |||
390 | dst[0] = (int32_t *)src[0]; | 374 | dst[0] = (int32_t *)src[0]; |
391 | dst[1] = (int32_t *)src[1]; | 375 | dst[1] = (int32_t *)src[1]; |
392 | src[0] = (char *)(dst[0] + count); | 376 | src[0] = (char *)(dst[0] + count); |
393 | src[1] = (char *)(dst[1] + count); | 377 | src[1] = (char *)(dst[1] + count); |
394 | |||
395 | return count; | ||
396 | } | 378 | } |
397 | 379 | ||
398 | /** | 380 | /** |
@@ -573,12 +555,6 @@ static void sample_output_new_format(void) | |||
573 | dsp->output_samples = sample_output_functions[out]; | 555 | dsp->output_samples = sample_output_functions[out]; |
574 | } | 556 | } |
575 | 557 | ||
576 | static void resampler_set_delta(int frequency) | ||
577 | { | ||
578 | dsp->data.resample_data.delta = (unsigned long) | ||
579 | frequency * 65536LL / NATIVE_FREQUENCY; | ||
580 | } | ||
581 | |||
582 | /** | 558 | /** |
583 | * Linear interpolation resampling that introduces a one sample delay because | 559 | * Linear interpolation resampling that introduces a one sample delay because |
584 | * of our inability to look into the future at the end of a frame. | 560 | * of our inability to look into the future at the end of a frame. |
@@ -587,9 +563,9 @@ static void resampler_set_delta(int frequency) | |||
587 | static int dsp_downsample(int count, struct dsp_data *data, | 563 | static int dsp_downsample(int count, struct dsp_data *data, |
588 | int32_t *src[], int32_t *dst[]) | 564 | int32_t *src[], int32_t *dst[]) |
589 | { | 565 | { |
590 | int ch = data->num_channels - 1; | 566 | int ch = data->num_channels - 1; |
591 | long delta = data->resample_data.delta; | 567 | uint32_t delta = data->resample_data.delta; |
592 | long phase, pos; | 568 | uint32_t phase, pos; |
593 | int32_t *d; | 569 | int32_t *d; |
594 | 570 | ||
595 | /* Rolled channel loop actually showed slightly faster. */ | 571 | /* Rolled channel loop actually showed slightly faster. */ |
@@ -610,7 +586,7 @@ static int dsp_downsample(int count, struct dsp_data *data, | |||
610 | if (pos > 0) | 586 | if (pos > 0) |
611 | last = s[pos - 1]; | 587 | last = s[pos - 1]; |
612 | 588 | ||
613 | while (pos < count) | 589 | while (pos < (uint32_t)count) |
614 | { | 590 | { |
615 | *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last); | 591 | *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last); |
616 | phase += delta; | 592 | phase += delta; |
@@ -625,12 +601,12 @@ static int dsp_downsample(int count, struct dsp_data *data, | |||
625 | return d - dst[0]; | 601 | return d - dst[0]; |
626 | } | 602 | } |
627 | 603 | ||
628 | static int dsp_upsample(int count, struct dsp_data *data, | 604 | static int dsp_upsample(int count, struct dsp_data *data, |
629 | int32_t *src[], int32_t *dst[]) | 605 | int32_t *src[], int32_t *dst[]) |
630 | { | 606 | { |
631 | int ch = data->num_channels - 1; | 607 | int ch = data->num_channels - 1; |
632 | long delta = data->resample_data.delta; | 608 | uint32_t delta = data->resample_data.delta; |
633 | long phase, pos; | 609 | uint32_t phase, pos; |
634 | int32_t *d; | 610 | int32_t *d; |
635 | 611 | ||
636 | /* Rolled channel loop actually showed slightly faster. */ | 612 | /* Rolled channel loop actually showed slightly faster. */ |
@@ -653,7 +629,7 @@ static int dsp_upsample(int count, struct dsp_data *data, | |||
653 | pos = phase >> 16; | 629 | pos = phase >> 16; |
654 | } | 630 | } |
655 | 631 | ||
656 | while (pos < count) | 632 | while (pos < (uint32_t)count) |
657 | { | 633 | { |
658 | last = s[pos - 1]; | 634 | last = s[pos - 1]; |
659 | *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last); | 635 | *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last); |
@@ -669,24 +645,43 @@ static int dsp_upsample(int count, struct dsp_data *data, | |||
669 | } | 645 | } |
670 | #endif /* DSP_HAVE_ASM_RESAMPLING */ | 646 | #endif /* DSP_HAVE_ASM_RESAMPLING */ |
671 | 647 | ||
648 | static void resampler_new_delta(void) | ||
649 | { | ||
650 | dsp->data.resample_data.delta = (unsigned long) | ||
651 | dsp->frequency * 65536LL / NATIVE_FREQUENCY; | ||
652 | |||
653 | if (dsp->frequency == NATIVE_FREQUENCY) | ||
654 | { | ||
655 | /* NOTE: If fully glitch-free transistions from no resampling to | ||
656 | resampling are desired, last_sample history should be maintained | ||
657 | even when not resampling. */ | ||
658 | dsp->resample = NULL; | ||
659 | dsp->data.resample_data.phase = 0; | ||
660 | dsp->data.resample_data.last_sample[0] = 0; | ||
661 | dsp->data.resample_data.last_sample[1] = 0; | ||
662 | } | ||
663 | else if (dsp->frequency < NATIVE_FREQUENCY) | ||
664 | dsp->resample = dsp_upsample; | ||
665 | else | ||
666 | dsp->resample = dsp_downsample; | ||
667 | } | ||
668 | |||
672 | /* Resample count stereo samples. Updates the src array, if resampling is | 669 | /* Resample count stereo samples. Updates the src array, if resampling is |
673 | * done, to refer to the resampled data. Returns number of stereo samples | 670 | * done, to refer to the resampled data. Returns number of stereo samples |
674 | * for further processing. | 671 | * for further processing. |
675 | */ | 672 | */ |
676 | static inline int resample(int count, int32_t *src[]) | 673 | static inline int resample(int count, int32_t *src[]) |
677 | { | 674 | { |
678 | if (dsp->resample) | 675 | int32_t *dst[2] = |
679 | { | 676 | { |
680 | int32_t *dst[2] = | 677 | &resample_buf[RESAMPLE_BUF_LEFT_CHANNEL], |
681 | { | 678 | &resample_buf[RESAMPLE_BUF_RIGHT_CHANNEL], |
682 | resample_buf, | 679 | }; |
683 | resample_buf + RESAMPLE_BUF_COUNT/2, | ||
684 | }; | ||
685 | 680 | ||
686 | count = dsp->resample(count, &dsp->data, src, dst); | 681 | count = dsp->resample(count, &dsp->data, src, dst); |
687 | src[0] = dst[0]; | 682 | |
688 | src[1] = dst[dsp->data.num_channels - 1]; | 683 | src[0] = dst[0]; |
689 | } | 684 | src[1] = dst[dsp->data.num_channels - 1]; |
690 | 685 | ||
691 | return count; | 686 | return count; |
692 | } | 687 | } |
@@ -810,30 +805,59 @@ void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff) | |||
810 | c[2] <<= 4; | 805 | c[2] <<= 4; |
811 | } | 806 | } |
812 | 807 | ||
808 | /* Apply a constant gain to the samples (e.g., for ReplayGain). | ||
809 | * Note that this must be called before the resampler. | ||
810 | */ | ||
811 | #ifndef DSP_HAVE_ASM_APPLY_GAIN | ||
812 | static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[]) | ||
813 | { | ||
814 | const int32_t gain = data->gain; | ||
815 | int ch = data->num_channels - 1; | ||
816 | |||
817 | do | ||
818 | { | ||
819 | int32_t *s = buf[ch]; | ||
820 | int32_t *d = buf[ch]; | ||
821 | int32_t samp = *s++; | ||
822 | int i = 0; | ||
823 | |||
824 | do | ||
825 | { | ||
826 | FRACMUL_8_LOOP(samp, gain, s, d); | ||
827 | } | ||
828 | while (++i < count); | ||
829 | } | ||
830 | while (--ch >= 0); | ||
831 | } | ||
832 | #endif /* DSP_HAVE_ASM_APPLY_GAIN */ | ||
833 | |||
813 | /* Combine all gains to a global gain. */ | 834 | /* Combine all gains to a global gain. */ |
814 | static void set_gain(struct dsp_config *dsp) | 835 | static void set_gain(struct dsp_config *dsp) |
815 | { | 836 | { |
816 | dsp->gain = DEFAULT_GAIN; | 837 | dsp->data.gain = DEFAULT_GAIN; |
817 | 838 | ||
818 | /* Replay gain not relevant to voice */ | 839 | /* Replay gain not relevant to voice */ |
819 | if (dsp == audio_dsp && replaygain) | 840 | if (dsp == audio_dsp && replaygain) |
820 | { | 841 | { |
821 | dsp->gain = replaygain; | 842 | dsp->data.gain = replaygain; |
822 | } | 843 | } |
823 | 844 | ||
824 | if (eq_enabled && eq_precut) | 845 | if (eq_enabled && eq_precut) |
825 | { | 846 | { |
826 | dsp->gain = (long) (((int64_t) dsp->gain * eq_precut) >> 24); | 847 | dsp->data.gain = |
848 | (long) (((int64_t) dsp->data.gain * eq_precut) >> 24); | ||
827 | } | 849 | } |
828 | 850 | ||
829 | if (dsp->gain == DEFAULT_GAIN) | 851 | if (dsp->data.gain == DEFAULT_GAIN) |
830 | { | 852 | { |
831 | dsp->gain = 0; | 853 | dsp->data.gain = 0; |
832 | } | 854 | } |
833 | else | 855 | else |
834 | { | 856 | { |
835 | dsp->gain >>= 1; | 857 | dsp->data.gain >>= 1; |
836 | } | 858 | } |
859 | |||
860 | dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL; | ||
837 | } | 861 | } |
838 | 862 | ||
839 | /** | 863 | /** |
@@ -927,50 +951,6 @@ static void eq_process(int count, int32_t *buf[]) | |||
927 | } | 951 | } |
928 | } | 952 | } |
929 | 953 | ||
930 | /* Apply a constant gain to the samples (e.g., for ReplayGain). May update | ||
931 | * the src array if gain was applied. | ||
932 | * Note that this must be called before the resampler. | ||
933 | */ | ||
934 | static void apply_gain(int count, int32_t *buf[]) | ||
935 | { | ||
936 | int32_t *sl, *sr; | ||
937 | int32_t s, *d; | ||
938 | long gain; | ||
939 | int i; | ||
940 | |||
941 | if (new_gain) | ||
942 | { | ||
943 | /* Gain has changed */ | ||
944 | dsp_set_replaygain(); | ||
945 | if (dsp->gain == 0) | ||
946 | return; /* No gain to apply now */ | ||
947 | } | ||
948 | |||
949 | sl = buf[0], sr = buf[1]; | ||
950 | gain = dsp->gain; | ||
951 | |||
952 | if (sl != sr) | ||
953 | { | ||
954 | d = &sample_buf[SAMPLE_BUF_COUNT / 2]; | ||
955 | buf[1] = d; | ||
956 | s = *sr++; | ||
957 | |||
958 | for (i = 0; i < count; i++) | ||
959 | FRACMUL_8_LOOP(s, gain, sr, d); | ||
960 | } | ||
961 | else | ||
962 | { | ||
963 | buf[1] = &sample_buf[0]; | ||
964 | } | ||
965 | |||
966 | d = &sample_buf[0]; | ||
967 | buf[0] = d; | ||
968 | s = *sl++; | ||
969 | |||
970 | for (i = 0; i < count; i++) | ||
971 | FRACMUL_8_LOOP(s, gain, sl, d); | ||
972 | } | ||
973 | |||
974 | void dsp_set_stereo_width(int value) | 954 | void dsp_set_stereo_width(int value) |
975 | { | 955 | { |
976 | long width, straight, cross; | 956 | long width, straight, cross; |
@@ -993,35 +973,6 @@ void dsp_set_stereo_width(int value) | |||
993 | dsp_sw_cross = cross << 8; | 973 | dsp_sw_cross = cross << 8; |
994 | } | 974 | } |
995 | 975 | ||
996 | /** | ||
997 | * Implements the different channel configurations and stereo width. | ||
998 | */ | ||
999 | |||
1000 | /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for | ||
1001 | * completeness. */ | ||
1002 | #if 0 | ||
1003 | static void channels_process_sound_chan_stereo(int count, int32_t *buf[]) | ||
1004 | { | ||
1005 | /* The channels are each just themselves */ | ||
1006 | (void)count; (void)buf; | ||
1007 | } | ||
1008 | #endif | ||
1009 | |||
1010 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO | ||
1011 | static void channels_process_sound_chan_mono(int count, int32_t *buf[]) | ||
1012 | { | ||
1013 | int32_t *sl = buf[0], *sr = buf[1]; | ||
1014 | |||
1015 | do | ||
1016 | { | ||
1017 | int32_t lr = *sl/2 + *sr/2; | ||
1018 | *sl++ = lr; | ||
1019 | *sr++ = lr; | ||
1020 | } | ||
1021 | while (--count > 0); | ||
1022 | } | ||
1023 | #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */ | ||
1024 | |||
1025 | #if CONFIG_CODEC == SWCODEC | 976 | #if CONFIG_CODEC == SWCODEC |
1026 | 977 | ||
1027 | #ifdef HAVE_SW_TONE_CONTROLS | 978 | #ifdef HAVE_SW_TONE_CONTROLS |
@@ -1063,6 +1014,35 @@ int dsp_callback(int msg, intptr_t param) | |||
1063 | } | 1014 | } |
1064 | #endif | 1015 | #endif |
1065 | 1016 | ||
1017 | /** | ||
1018 | * Implements the different channel configurations and stereo width. | ||
1019 | */ | ||
1020 | |||
1021 | /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for | ||
1022 | * completeness. */ | ||
1023 | #if 0 | ||
1024 | static void channels_process_sound_chan_stereo(int count, int32_t *buf[]) | ||
1025 | { | ||
1026 | /* The channels are each just themselves */ | ||
1027 | (void)count; (void)buf; | ||
1028 | } | ||
1029 | #endif | ||
1030 | |||
1031 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO | ||
1032 | static void channels_process_sound_chan_mono(int count, int32_t *buf[]) | ||
1033 | { | ||
1034 | int32_t *sl = buf[0], *sr = buf[1]; | ||
1035 | |||
1036 | do | ||
1037 | { | ||
1038 | int32_t lr = *sl/2 + *sr/2; | ||
1039 | *sl++ = lr; | ||
1040 | *sr++ = lr; | ||
1041 | } | ||
1042 | while (--count > 0); | ||
1043 | } | ||
1044 | #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */ | ||
1045 | |||
1066 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM | 1046 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM |
1067 | static void channels_process_sound_chan_custom(int count, int32_t *buf[]) | 1047 | static void channels_process_sound_chan_custom(int count, int32_t *buf[]) |
1068 | { | 1048 | { |
@@ -1151,30 +1131,47 @@ int dsp_process(char *dst, const char *src[], int count) | |||
1151 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); | 1131 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); |
1152 | #endif | 1132 | #endif |
1153 | 1133 | ||
1134 | if (new_gain) | ||
1135 | dsp_set_replaygain(); /* Gain has changed */ | ||
1136 | |||
1137 | /* Testing function pointers for NULL is preferred since the pointer | ||
1138 | will be preloaded to be used for the call if not. */ | ||
1154 | while (count > 0) | 1139 | while (count > 0) |
1155 | { | 1140 | { |
1156 | samples = dsp->input_samples(count, src, tmp); | 1141 | samples = MIN(SAMPLE_BUF_COUNT/2, count); |
1157 | count -= samples; | 1142 | count -= samples; |
1158 | if (dsp->gain != 0) | 1143 | |
1159 | apply_gain(samples, tmp); | 1144 | dsp->input_samples(samples, src, tmp); |
1160 | if ((samples = resample(samples, tmp)) <= 0) | 1145 | |
1146 | if (dsp->apply_gain) | ||
1147 | dsp->apply_gain(samples, &dsp->data, tmp); | ||
1148 | |||
1149 | if (dsp->resample && (samples = resample(samples, tmp)) <= 0) | ||
1161 | break; /* I'm pretty sure we're downsampling here */ | 1150 | break; /* I'm pretty sure we're downsampling here */ |
1151 | |||
1162 | if (dsp->apply_crossfeed) | 1152 | if (dsp->apply_crossfeed) |
1163 | dsp->apply_crossfeed(samples, tmp); | 1153 | dsp->apply_crossfeed(samples, tmp); |
1154 | |||
1164 | /* TODO: EQ and tone controls need separate structs for audio and voice | 1155 | /* TODO: EQ and tone controls need separate structs for audio and voice |
1165 | * DSP processing thanks to filter history. isn't really audible now, but | 1156 | * DSP processing thanks to filter history. isn't really audible now, but |
1166 | * might be the day we start handling voice more delicately. | 1157 | * might be the day we start handling voice more delicately. Planned |
1158 | * changes may well run all relevent channels through the same EQ so | ||
1159 | * perhaps not. | ||
1167 | */ | 1160 | */ |
1168 | if (eq_enabled) | 1161 | if (eq_enabled) |
1169 | eq_process(samples, tmp); | 1162 | eq_process(samples, tmp); |
1163 | |||
1170 | #ifdef HAVE_SW_TONE_CONTROLS | 1164 | #ifdef HAVE_SW_TONE_CONTROLS |
1171 | if ((bass | treble) != 0) | 1165 | if ((bass | treble) != 0) |
1172 | eq_filter(tmp, &tone_filter, samples, dsp->data.num_channels, | 1166 | eq_filter(tmp, &tone_filter, samples, dsp->data.num_channels, |
1173 | FILTER_BISHELF_SHIFT); | 1167 | FILTER_BISHELF_SHIFT); |
1174 | #endif | 1168 | #endif |
1169 | |||
1175 | if (dsp->channels_process) | 1170 | if (dsp->channels_process) |
1176 | dsp->channels_process(samples, tmp); | 1171 | dsp->channels_process(samples, tmp); |
1172 | |||
1177 | dsp->output_samples(samples, &dsp->data, tmp, (int16_t *)dst); | 1173 | dsp->output_samples(samples, &dsp->data, tmp, (int16_t *)dst); |
1174 | |||
1178 | written += samples; | 1175 | written += samples; |
1179 | dst += samples * sizeof (int16_t) * 2; | 1176 | dst += samples * sizeof (int16_t) * 2; |
1180 | yield(); | 1177 | yield(); |
@@ -1245,9 +1242,6 @@ bool dsp_configure(int setting, intptr_t value) | |||
1245 | if (dsp == audio_dsp) | 1242 | if (dsp == audio_dsp) |
1246 | { | 1243 | { |
1247 | *var = value; | 1244 | *var = value; |
1248 | /* In case current gain is zero, force at least one call | ||
1249 | to apply_gain or apply_gain won't pick up on new_gain */ | ||
1250 | audio_dsp->gain = -1; | ||
1251 | new_gain = true; | 1245 | new_gain = true; |
1252 | } | 1246 | } |
1253 | } | 1247 | } |
@@ -1282,15 +1276,7 @@ bool dsp_configure(int setting, intptr_t value) | |||
1282 | else | 1276 | else |
1283 | dsp->frequency = dsp->codec_frequency; | 1277 | dsp->frequency = dsp->codec_frequency; |
1284 | 1278 | ||
1285 | resampler_set_delta(dsp->frequency); | 1279 | resampler_new_delta(); |
1286 | |||
1287 | if (dsp->frequency == NATIVE_FREQUENCY) | ||
1288 | dsp->resample = NULL; | ||
1289 | else if (dsp->frequency < NATIVE_FREQUENCY) | ||
1290 | dsp->resample = dsp_upsample; | ||
1291 | else | ||
1292 | dsp->resample = dsp_downsample; | ||
1293 | |||
1294 | break; | 1280 | break; |
1295 | 1281 | ||
1296 | case DSP_SET_SAMPLE_DEPTH: | 1282 | case DSP_SET_SAMPLE_DEPTH: |
@@ -1348,7 +1334,7 @@ bool dsp_configure(int setting, intptr_t value) | |||
1348 | case DSP_FLUSH: | 1334 | case DSP_FLUSH: |
1349 | memset(&dsp->data.resample_data, 0, | 1335 | memset(&dsp->data.resample_data, 0, |
1350 | sizeof (dsp->data.resample_data)); | 1336 | sizeof (dsp->data.resample_data)); |
1351 | resampler_set_delta(dsp->frequency); | 1337 | resampler_new_delta(); |
1352 | dither_init(); | 1338 | dither_init(); |
1353 | break; | 1339 | break; |
1354 | 1340 | ||