Make disabling HAVE_PITCHSCREEN actually work without breaking the build
[kugel-rb.git] / apps / dsp.c
blob33a54008e202659fab524689ce48f8c41071f240
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
22 #include <stdbool.h>
23 #include <inttypes.h>
24 #include <string.h>
25 #include <sound.h>
26 #include "dsp.h"
27 #include "eq.h"
28 #include "kernel.h"
29 #include "system.h"
30 #include "settings.h"
31 #include "replaygain.h"
32 #include "tdspeed.h"
33 #include "buffer.h"
34 #include "fixedpoint.h"
35 #include "fracmul.h"
37 /* Define LOGF_ENABLE to enable logf output in this file */
38 /*#define LOGF_ENABLE*/
39 #include "logf.h"
41 /* 16-bit samples are scaled based on these constants. The shift should be
42 * no more than 15.
44 #define WORD_SHIFT 12
45 #define WORD_FRACBITS 27
47 #define NATIVE_DEPTH 16
48 /* If the small buffer size changes, check the assembly code! */
49 #define SMALL_SAMPLE_BUF_COUNT 256
50 #define DEFAULT_GAIN 0x01000000
52 /* enums to index conversion properly with stereo mode and other settings */
53 enum
55 SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED,
56 SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED,
57 SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO,
58 SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES,
59 SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES,
60 SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES,
61 SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES
64 enum
66 SAMPLE_OUTPUT_MONO = 0,
67 SAMPLE_OUTPUT_STEREO,
68 SAMPLE_OUTPUT_DITHERED_MONO,
69 SAMPLE_OUTPUT_DITHERED_STEREO
72 /****************************************************************************
73 * NOTE: Any assembly routines that use these structures must be updated
74 * if current data members are moved or changed.
76 struct resample_data
78 uint32_t delta; /* 00h */
79 uint32_t phase; /* 04h */
80 int32_t last_sample[2]; /* 08h */
81 /* 10h */
84 /* This is for passing needed data to assembly dsp routines. If another
85 * dsp parameter needs to be passed, add to the end of the structure
86 * and remove from dsp_config.
87 * If another function type becomes assembly optimized and requires dsp
88 * config info, add a pointer paramter of type "struct dsp_data *".
89 * If removing something from other than the end, reserve the spot or
90 * else update every implementation for every target.
91 * Be sure to add the offset of the new member for easy viewing as well. :)
92 * It is the first member of dsp_config and all members can be accessesed
93 * through the main aggregate but this is intended to make a safe haven
94 * for these items whereas the c part can be rearranged at will. dsp_data
95 * could even moved within dsp_config without disurbing the order.
97 struct dsp_data
99 int output_scale; /* 00h */
100 int num_channels; /* 04h */
101 struct resample_data resample_data; /* 08h */
102 int32_t clip_min; /* 18h */
103 int32_t clip_max; /* 1ch */
104 int32_t gain; /* 20h - Note that this is in S8.23 format. */
105 /* 24h */
108 /* No asm...yet */
109 struct dither_data
111 long error[3]; /* 00h */
112 long random; /* 0ch */
113 /* 10h */
116 struct crossfeed_data
118 int32_t gain; /* 00h - Direct path gain */
119 int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */
120 int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */
121 int32_t delay[13][2]; /* 20h */
122 int32_t *index; /* 88h - Current pointer into the delay line */
123 /* 8ch */
126 /* Current setup is one lowshelf filters three peaking filters and one
127 * highshelf filter. Varying the number of shelving filters make no sense,
128 * but adding peaking filters is possible.
130 struct eq_state
132 char enabled[5]; /* 00h - Flags for active filters */
133 struct eqfilter filters[5]; /* 08h - packing is 4? */
134 /* 10ch */
137 struct compressor_menu
139 int threshold; /* dB - from menu */
140 bool auto_gain; /* 0 = off, 1 = auto */
141 int ratio; /* from menu */
142 bool soft_knee; /* 0 = hard knee, 1 = soft knee */
143 int release; /* samples - from menu */
146 /* Include header with defines which functions are implemented in assembly
147 code for the target */
148 #include <dsp_asm.h>
150 /* Typedefs keep things much neater in this case */
151 typedef void (*sample_input_fn_type)(int count, const char *src[],
152 int32_t *dst[]);
153 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
154 const int32_t *src[], int32_t *dst[]);
155 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
156 const int32_t *src[], int16_t *dst);
158 /* Single-DSP channel processing in place */
159 typedef void (*channels_process_fn_type)(int count, int32_t *buf[]);
160 /* DSP local channel processing in place */
161 typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data,
162 int32_t *buf[]);
165 ***************************************************************************/
167 struct dsp_config
169 struct dsp_data data; /* Config members for use in asm routines */
170 long codec_frequency; /* Sample rate of data coming from the codec */
171 long frequency; /* Effective sample rate after pitch shift (if any) */
172 int sample_depth;
173 int sample_bytes;
174 int stereo_mode;
175 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
176 bool tdspeed_active; /* Timestretch is in use */
177 int frac_bits;
178 #ifdef HAVE_SW_TONE_CONTROLS
179 /* Filter struct for software bass/treble controls */
180 struct eqfilter tone_filter;
181 #endif
182 /* Functions that change depending upon settings - NULL if stage is
183 disabled */
184 sample_input_fn_type input_samples;
185 resample_fn_type resample;
186 sample_output_fn_type output_samples;
187 /* These will be NULL for the voice codec and is more economical that
188 way */
189 channels_process_dsp_fn_type apply_gain;
190 channels_process_fn_type apply_crossfeed;
191 channels_process_fn_type eq_process;
192 channels_process_fn_type channels_process;
193 channels_process_fn_type compressor_process;
196 /* General DSP config */
197 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
198 /* Dithering */
199 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
200 static long dither_mask IBSS_ATTR;
201 static long dither_bias IBSS_ATTR;
202 /* Crossfeed */
203 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
205 .index = (int32_t *)crossfeed_data.delay
208 /* Equalizer */
209 static struct eq_state eq_data; /* A */
211 /* Software tone controls */
212 #ifdef HAVE_SW_TONE_CONTROLS
213 static int prescale; /* A/V */
214 static int bass; /* A/V */
215 static int treble; /* A/V */
216 #endif
218 /* Settings applicable to audio codec only */
219 #ifdef HAVE_PITCHSCREEN
220 static int32_t pitch_ratio = PITCH_SPEED_100;
221 #endif
222 static int channels_mode;
223 long dsp_sw_gain;
224 long dsp_sw_cross;
225 static bool dither_enabled;
226 static long eq_precut;
227 static long track_gain;
228 static bool new_gain;
229 static long album_gain;
230 static long track_peak;
231 static long album_peak;
232 static long replaygain;
233 static bool crossfeed_enabled;
235 #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
236 #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
238 /* The internal format is 32-bit samples, non-interleaved, stereo. This
239 * format is similar to the raw output from several codecs, so the amount
240 * of copying needed is minimized for that case.
243 #define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
245 #ifdef HAVE_PITCHSCREEN
246 static int32_t small_sample_buf[SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
247 static int32_t small_resample_buf[SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO] IBSS_ATTR;
249 static int32_t *big_sample_buf = NULL;
250 static int32_t *big_resample_buf = NULL;
251 static int big_sample_buf_count = -1; /* -1=unknown, 0=not available */
252 #endif
254 static int sample_buf_count;
255 static int32_t *sample_buf;
256 static int32_t *resample_buf;
258 #define SAMPLE_BUF_LEFT_CHANNEL 0
259 #define SAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2)
260 #define RESAMPLE_BUF_LEFT_CHANNEL 0
261 #define RESAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2 * RESAMPLE_RATIO)
263 /* compressor */
264 static struct compressor_menu c_menu;
265 static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
266 static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
267 static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
268 static int32_t release_gain IBSS_ATTR; /* S7.24 format */
269 #define UNITY (1L << 24) /* unity gain in S7.24 format */
270 static void compressor_process(int count, int32_t *buf[]);
273 /* Clip sample to signed 16 bit range */
274 static inline int32_t clip_sample_16(int32_t sample)
276 if ((int16_t)sample != sample)
277 sample = 0x7fff ^ (sample >> 31);
278 return sample;
281 #ifdef HAVE_PITCHSCREEN
282 int32_t sound_get_pitch(void)
284 return pitch_ratio;
287 void sound_set_pitch(int32_t percent)
289 pitch_ratio = percent;
290 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
291 AUDIO_DSP.codec_frequency);
294 static void tdspeed_setup(struct dsp_config *dspc)
296 /* Assume timestretch will not be used */
297 dspc->tdspeed_active = false;
298 sample_buf = small_sample_buf;
299 resample_buf = small_resample_buf;
300 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
302 if(!dsp_timestretch_available())
303 return; /* Timestretch not enabled or buffer not allocated */
304 if (dspc->tdspeed_percent == 0)
305 dspc->tdspeed_percent = PITCH_SPEED_100;
306 if (!tdspeed_config(
307 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
308 dspc->stereo_mode != STEREO_MONO,
309 dspc->tdspeed_percent))
310 return; /* Timestretch not possible or needed with these parameters */
312 /* Timestretch is to be used */
313 dspc->tdspeed_active = true;
314 sample_buf = big_sample_buf;
315 sample_buf_count = big_sample_buf_count;
316 resample_buf = big_resample_buf;
319 void dsp_timestretch_enable(bool enabled)
321 /* Hook to set up timestretch buffer on first call to settings_apply() */
322 if (big_sample_buf_count < 0) /* Only do something on first call */
324 if (enabled)
326 /* Set up timestretch buffers */
327 big_sample_buf_count = SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO;
328 big_sample_buf = small_resample_buf;
329 big_resample_buf = (int32_t *) buffer_alloc(big_sample_buf_count * RESAMPLE_RATIO * sizeof(int32_t));
331 else
333 /* Not enabled at startup, "big" buffers will never be available */
334 big_sample_buf_count = 0;
336 tdspeed_setup(&AUDIO_DSP);
340 void dsp_set_timestretch(int32_t percent)
342 AUDIO_DSP.tdspeed_percent = percent;
343 tdspeed_setup(&AUDIO_DSP);
346 int32_t dsp_get_timestretch()
348 return AUDIO_DSP.tdspeed_percent;
351 bool dsp_timestretch_available()
353 return (global_settings.timestretch_enabled && big_sample_buf_count > 0);
355 #endif
357 /* Convert count samples to the internal format, if needed. Updates src
358 * to point past the samples "consumed" and dst is set to point to the
359 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
360 * is no point in processing the same data twice.
363 /* convert count 16-bit mono to 32-bit mono */
364 static void sample_input_lte_native_mono(
365 int count, const char *src[], int32_t *dst[])
367 const int16_t *s = (int16_t *) src[0];
368 const int16_t * const send = s + count;
369 int32_t *d = dst[0] = dst[1] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
370 int scale = WORD_SHIFT;
372 while (s < send)
374 *d++ = *s++ << scale;
377 src[0] = (char *)s;
380 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
381 static void sample_input_lte_native_i_stereo(
382 int count, const char *src[], int32_t *dst[])
384 const int32_t *s = (int32_t *) src[0];
385 const int32_t * const send = s + count;
386 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
387 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
388 int scale = WORD_SHIFT;
390 while (s < send)
392 int32_t slr = *s++;
393 #ifdef ROCKBOX_LITTLE_ENDIAN
394 *dl++ = (slr >> 16) << scale;
395 *dr++ = (int32_t)(int16_t)slr << scale;
396 #else /* ROCKBOX_BIG_ENDIAN */
397 *dl++ = (int32_t)(int16_t)slr << scale;
398 *dr++ = (slr >> 16) << scale;
399 #endif
402 src[0] = (char *)s;
405 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
406 static void sample_input_lte_native_ni_stereo(
407 int count, const char *src[], int32_t *dst[])
409 const int16_t *sl = (int16_t *) src[0];
410 const int16_t *sr = (int16_t *) src[1];
411 const int16_t * const slend = sl + count;
412 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
413 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
414 int scale = WORD_SHIFT;
416 while (sl < slend)
418 *dl++ = *sl++ << scale;
419 *dr++ = *sr++ << scale;
422 src[0] = (char *)sl;
423 src[1] = (char *)sr;
426 /* convert count 32-bit mono to 32-bit mono */
427 static void sample_input_gt_native_mono(
428 int count, const char *src[], int32_t *dst[])
430 dst[0] = dst[1] = (int32_t *)src[0];
431 src[0] = (char *)(dst[0] + count);
434 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
435 static void sample_input_gt_native_i_stereo(
436 int count, const char *src[], int32_t *dst[])
438 const int32_t *s = (int32_t *)src[0];
439 const int32_t * const send = s + 2*count;
440 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
441 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
443 while (s < send)
445 *dl++ = *s++;
446 *dr++ = *s++;
449 src[0] = (char *)send;
452 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
453 static void sample_input_gt_native_ni_stereo(
454 int count, const char *src[], int32_t *dst[])
456 dst[0] = (int32_t *)src[0];
457 dst[1] = (int32_t *)src[1];
458 src[0] = (char *)(dst[0] + count);
459 src[1] = (char *)(dst[1] + count);
463 * sample_input_new_format()
465 * set the to-native sample conversion function based on dsp sample parameters
467 * !DSPPARAMSYNC
468 * needs syncing with changes to the following dsp parameters:
469 * * dsp->stereo_mode (A/V)
470 * * dsp->sample_depth (A/V)
472 static void sample_input_new_format(struct dsp_config *dsp)
474 static const sample_input_fn_type sample_input_functions[] =
476 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
477 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
478 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
479 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
480 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
481 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
484 int convert = dsp->stereo_mode;
486 if (dsp->sample_depth > NATIVE_DEPTH)
487 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
489 dsp->input_samples = sample_input_functions[convert];
493 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
494 /* write mono internal format to output format */
495 static void sample_output_mono(int count, struct dsp_data *data,
496 const int32_t *src[], int16_t *dst)
498 const int32_t *s0 = src[0];
499 const int scale = data->output_scale;
500 const int dc_bias = 1 << (scale - 1);
502 while (count-- > 0)
504 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
505 *dst++ = lr;
506 *dst++ = lr;
509 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
511 /* write stereo internal format to output format */
512 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
513 static void sample_output_stereo(int count, struct dsp_data *data,
514 const int32_t *src[], int16_t *dst)
516 const int32_t *s0 = src[0];
517 const int32_t *s1 = src[1];
518 const int scale = data->output_scale;
519 const int dc_bias = 1 << (scale - 1);
521 while (count-- > 0)
523 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
524 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
527 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
530 * The "dither" code to convert the 24-bit samples produced by libmad was
531 * taken from the coolplayer project - coolplayer.sourceforge.net
533 * This function handles mono and stereo outputs.
535 static void sample_output_dithered(int count, struct dsp_data *data,
536 const int32_t *src[], int16_t *dst)
538 const int32_t mask = dither_mask;
539 const int32_t bias = dither_bias;
540 const int scale = data->output_scale;
541 const int32_t min = data->clip_min;
542 const int32_t max = data->clip_max;
543 const int32_t range = max - min;
544 int ch;
545 int16_t *d;
547 for (ch = 0; ch < data->num_channels; ch++)
549 struct dither_data * const dither = &dither_data[ch];
550 const int32_t *s = src[ch];
551 int i;
553 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
555 int32_t output, sample;
556 int32_t random;
558 /* Noise shape and bias (for correct rounding later) */
559 sample = *s;
560 sample += dither->error[0] - dither->error[1] + dither->error[2];
561 dither->error[2] = dither->error[1];
562 dither->error[1] = dither->error[0]/2;
564 output = sample + bias;
566 /* Dither, highpass triangle PDF */
567 random = dither->random*0x0019660dL + 0x3c6ef35fL;
568 output += (random & mask) - (dither->random & mask);
569 dither->random = random;
571 /* Round sample to output range */
572 output &= ~mask;
574 /* Error feedback */
575 dither->error[0] = sample - output;
577 /* Clip */
578 if ((uint32_t)(output - min) > (uint32_t)range)
580 int32_t c = min;
581 if (output > min)
582 c += range;
583 output = c;
586 /* Quantize and store */
587 *d = output >> scale;
591 if (data->num_channels == 2)
592 return;
594 /* Have to duplicate left samples into the right channel since
595 pcm buffer and hardware is interleaved stereo */
596 d = &dst[0];
598 while (count-- > 0)
600 int16_t s = *d++;
601 *d++ = s;
606 * sample_output_new_format()
608 * set the from-native to ouput sample conversion routine
610 * !DSPPARAMSYNC
611 * needs syncing with changes to the following dsp parameters:
612 * * dsp->stereo_mode (A/V)
613 * * dither_enabled (A)
615 static void sample_output_new_format(struct dsp_config *dsp)
617 static const sample_output_fn_type sample_output_functions[] =
619 sample_output_mono,
620 sample_output_stereo,
621 sample_output_dithered,
622 sample_output_dithered
625 int out = dsp->data.num_channels - 1;
627 if (dsp == &AUDIO_DSP && dither_enabled)
628 out += 2;
630 dsp->output_samples = sample_output_functions[out];
634 * Linear interpolation resampling that introduces a one sample delay because
635 * of our inability to look into the future at the end of a frame.
637 #ifndef DSP_HAVE_ASM_RESAMPLING
638 static int dsp_downsample(int count, struct dsp_data *data,
639 const int32_t *src[], int32_t *dst[])
641 int ch = data->num_channels - 1;
642 uint32_t delta = data->resample_data.delta;
643 uint32_t phase, pos;
644 int32_t *d;
646 /* Rolled channel loop actually showed slightly faster. */
649 /* Just initialize things and not worry too much about the relatively
650 * uncommon case of not being able to spit out a sample for the frame.
652 const int32_t *s = src[ch];
653 int32_t last = data->resample_data.last_sample[ch];
655 data->resample_data.last_sample[ch] = s[count - 1];
656 d = dst[ch];
657 phase = data->resample_data.phase;
658 pos = phase >> 16;
660 /* Do we need last sample of previous frame for interpolation? */
661 if (pos > 0)
662 last = s[pos - 1];
664 while (pos < (uint32_t)count)
666 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
667 phase += delta;
668 pos = phase >> 16;
669 last = s[pos - 1];
672 while (--ch >= 0);
674 /* Wrap phase accumulator back to start of next frame. */
675 data->resample_data.phase = phase - (count << 16);
676 return d - dst[0];
679 static int dsp_upsample(int count, struct dsp_data *data,
680 const int32_t *src[], int32_t *dst[])
682 int ch = data->num_channels - 1;
683 uint32_t delta = data->resample_data.delta;
684 uint32_t phase, pos;
685 int32_t *d;
687 /* Rolled channel loop actually showed slightly faster. */
690 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
691 const int32_t *s = src[ch];
692 int32_t last = data->resample_data.last_sample[ch];
694 data->resample_data.last_sample[ch] = s[count - 1];
695 d = dst[ch];
696 phase = data->resample_data.phase;
697 pos = phase >> 16;
699 while (pos == 0)
701 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
702 phase += delta;
703 pos = phase >> 16;
706 while (pos < (uint32_t)count)
708 last = s[pos - 1];
709 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
710 phase += delta;
711 pos = phase >> 16;
714 while (--ch >= 0);
716 /* Wrap phase accumulator back to start of next frame. */
717 data->resample_data.phase = phase & 0xffff;
718 return d - dst[0];
720 #endif /* DSP_HAVE_ASM_RESAMPLING */
722 static void resampler_new_delta(struct dsp_config *dsp)
724 dsp->data.resample_data.delta = (unsigned long)
725 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
727 if (dsp->frequency == NATIVE_FREQUENCY)
729 /* NOTE: If fully glitch-free transistions from no resampling to
730 resampling are desired, last_sample history should be maintained
731 even when not resampling. */
732 dsp->resample = NULL;
733 dsp->data.resample_data.phase = 0;
734 dsp->data.resample_data.last_sample[0] = 0;
735 dsp->data.resample_data.last_sample[1] = 0;
737 else if (dsp->frequency < NATIVE_FREQUENCY)
738 dsp->resample = dsp_upsample;
739 else
740 dsp->resample = dsp_downsample;
743 /* Resample count stereo samples. Updates the src array, if resampling is
744 * done, to refer to the resampled data. Returns number of stereo samples
745 * for further processing.
747 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
749 int32_t *dst[2] =
751 &resample_buf[RESAMPLE_BUF_LEFT_CHANNEL],
752 &resample_buf[RESAMPLE_BUF_RIGHT_CHANNEL],
755 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
757 src[0] = dst[0];
758 src[1] = dst[dsp->data.num_channels - 1];
760 return count;
763 static void dither_init(struct dsp_config *dsp)
765 memset(dither_data, 0, sizeof (dither_data));
766 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
767 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
770 void dsp_dither_enable(bool enable)
772 struct dsp_config *dsp = &AUDIO_DSP;
773 dither_enabled = enable;
774 sample_output_new_format(dsp);
777 /* Applies crossfeed to the stereo signal in src.
778 * Crossfeed is a process where listening over speakers is simulated. This
779 * is good for old hard panned stereo records, which might be quite fatiguing
780 * to listen to on headphones with no crossfeed.
782 #ifndef DSP_HAVE_ASM_CROSSFEED
783 static void apply_crossfeed(int count, int32_t *buf[])
785 int32_t *hist_l = &crossfeed_data.history[0];
786 int32_t *hist_r = &crossfeed_data.history[2];
787 int32_t *delay = &crossfeed_data.delay[0][0];
788 int32_t *coefs = &crossfeed_data.coefs[0];
789 int32_t gain = crossfeed_data.gain;
790 int32_t *di = crossfeed_data.index;
792 int32_t acc;
793 int32_t left, right;
794 int i;
796 for (i = 0; i < count; i++)
798 left = buf[0][i];
799 right = buf[1][i];
801 /* Filter delayed sample from left speaker */
802 acc = FRACMUL(*di, coefs[0]);
803 acc += FRACMUL(hist_l[0], coefs[1]);
804 acc += FRACMUL(hist_l[1], coefs[2]);
805 /* Save filter history for left speaker */
806 hist_l[1] = acc;
807 hist_l[0] = *di;
808 *di++ = left;
809 /* Filter delayed sample from right speaker */
810 acc = FRACMUL(*di, coefs[0]);
811 acc += FRACMUL(hist_r[0], coefs[1]);
812 acc += FRACMUL(hist_r[1], coefs[2]);
813 /* Save filter history for right speaker */
814 hist_r[1] = acc;
815 hist_r[0] = *di;
816 *di++ = right;
817 /* Now add the attenuated direct sound and write to outputs */
818 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
819 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
821 /* Wrap delay line index if bigger than delay line size */
822 if (di >= delay + 13*2)
823 di = delay;
825 /* Write back local copies of data we've modified */
826 crossfeed_data.index = di;
828 #endif /* DSP_HAVE_ASM_CROSSFEED */
831 * dsp_set_crossfeed(bool enable)
833 * !DSPPARAMSYNC
834 * needs syncing with changes to the following dsp parameters:
835 * * dsp->stereo_mode (A)
837 void dsp_set_crossfeed(bool enable)
839 crossfeed_enabled = enable;
840 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
841 ? apply_crossfeed : NULL;
844 void dsp_set_crossfeed_direct_gain(int gain)
846 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
847 /* If gain is negative, the calculation overflowed and we need to clamp */
848 if (crossfeed_data.gain < 0)
849 crossfeed_data.gain = 0x7fffffff;
852 /* Both gains should be below 0 dB */
853 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
855 int32_t *c = crossfeed_data.coefs;
856 long scaler = get_replaygain_int(lf_gain * 10) << 7;
858 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
859 hf_gain -= lf_gain;
860 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
861 * point instead of shelf midpoint. This is for compatibility with the old
862 * crossfeed shelf filter and should be removed if crossfeed settings are
863 * ever made incompatible for any other good reason.
865 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
866 filter_shelf_coefs(cutoff, hf_gain, false, c);
867 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
868 * over 1 and can do this safely
870 c[0] = FRACMUL_SHL(c[0], scaler, 4);
871 c[1] = FRACMUL_SHL(c[1], scaler, 4);
872 c[2] <<= 4;
875 /* Apply a constant gain to the samples (e.g., for ReplayGain).
876 * Note that this must be called before the resampler.
878 #ifndef DSP_HAVE_ASM_APPLY_GAIN
879 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
881 const int32_t gain = data->gain;
882 int ch;
884 for (ch = 0; ch < data->num_channels; ch++)
886 int32_t *d = buf[ch];
887 int i;
889 for (i = 0; i < count; i++)
890 d[i] = FRACMUL_SHL(d[i], gain, 8);
893 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
895 /* Combine all gains to a global gain. */
896 static void set_gain(struct dsp_config *dsp)
898 /* gains are in S7.24 format */
899 dsp->data.gain = DEFAULT_GAIN;
901 /* Replay gain not relevant to voice */
902 if (dsp == &AUDIO_DSP && replaygain)
904 dsp->data.gain = replaygain;
907 if (dsp->eq_process && eq_precut)
909 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
912 #ifdef HAVE_SW_VOLUME_CONTROL
913 if (global_settings.volume < SW_VOLUME_MAX ||
914 global_settings.volume > SW_VOLUME_MIN)
916 int vol_gain = get_replaygain_int(global_settings.volume * 100);
917 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
919 #endif
921 if (dsp->data.gain == DEFAULT_GAIN)
923 dsp->data.gain = 0;
925 else
927 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
930 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
934 * Update the amount to cut the audio before applying the equalizer.
936 * @param precut to apply in decibels (multiplied by 10)
938 void dsp_set_eq_precut(int precut)
940 eq_precut = get_replaygain_int(precut * -10);
941 set_gain(&AUDIO_DSP);
945 * Synchronize the equalizer filter coefficients with the global settings.
947 * @param band the equalizer band to synchronize
949 void dsp_set_eq_coefs(int band)
951 const int *setting;
952 long gain;
953 unsigned long cutoff, q;
955 /* Adjust setting pointer to the band we actually want to change */
956 setting = &global_settings.eq_band0_cutoff + (band * 3);
958 /* Convert user settings to format required by coef generator functions */
959 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
960 q = *setting++;
961 gain = *setting++;
963 if (q == 0)
964 q = 1;
966 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
967 which it should be, since we're executed from the main thread. */
969 /* Assume a band is disabled if the gain is zero */
970 if (gain == 0)
972 eq_data.enabled[band] = 0;
974 else
976 if (band == 0)
977 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
978 else if (band == 4)
979 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
980 else
981 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
983 eq_data.enabled[band] = 1;
987 /* Apply EQ filters to those bands that have got it switched on. */
988 static void eq_process(int count, int32_t *buf[])
990 static const int shifts[] =
992 EQ_SHELF_SHIFT, /* low shelf */
993 EQ_PEAK_SHIFT, /* peaking */
994 EQ_PEAK_SHIFT, /* peaking */
995 EQ_PEAK_SHIFT, /* peaking */
996 EQ_SHELF_SHIFT, /* high shelf */
998 unsigned int channels = AUDIO_DSP.data.num_channels;
999 int i;
1001 /* filter configuration currently is 1 low shelf filter, 3 band peaking
1002 filters and 1 high shelf filter, in that order. we need to know this
1003 so we can choose the correct shift factor.
1005 for (i = 0; i < 5; i++)
1007 if (!eq_data.enabled[i])
1008 continue;
1009 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1014 * Use to enable the equalizer.
1016 * @param enable true to enable the equalizer
1018 void dsp_set_eq(bool enable)
1020 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1021 set_gain(&AUDIO_DSP);
1024 static void dsp_set_stereo_width(int value)
1026 long width, straight, cross;
1028 width = value * 0x7fffff / 100;
1030 if (value <= 100)
1032 straight = (0x7fffff + width) / 2;
1033 cross = straight - width;
1035 else
1037 /* straight = (1 + width) / (2 * width) */
1038 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1039 cross = straight - 0x7fffff;
1042 dsp_sw_gain = straight << 8;
1043 dsp_sw_cross = cross << 8;
1047 * Implements the different channel configurations and stereo width.
1050 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1051 * completeness. */
1052 #if 0
1053 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1055 /* The channels are each just themselves */
1056 (void)count; (void)buf;
1058 #endif
1060 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1061 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1063 int32_t *sl = buf[0], *sr = buf[1];
1065 while (count-- > 0)
1067 int32_t lr = *sl/2 + *sr/2;
1068 *sl++ = lr;
1069 *sr++ = lr;
1072 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1074 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1075 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1077 const int32_t gain = dsp_sw_gain;
1078 const int32_t cross = dsp_sw_cross;
1079 int32_t *sl = buf[0], *sr = buf[1];
1081 while (count-- > 0)
1083 int32_t l = *sl;
1084 int32_t r = *sr;
1085 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1086 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1089 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1091 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1093 /* Just copy over the other channel */
1094 memcpy(buf[1], buf[0], count * sizeof (*buf));
1097 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1099 /* Just copy over the other channel */
1100 memcpy(buf[0], buf[1], count * sizeof (*buf));
1103 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1104 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1106 int32_t *sl = buf[0], *sr = buf[1];
1108 while (count-- > 0)
1110 int32_t ch = *sl/2 - *sr/2;
1111 *sl++ = ch;
1112 *sr++ = -ch;
1115 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1117 static void dsp_set_channel_config(int value)
1119 static const channels_process_fn_type channels_process_functions[] =
1121 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1122 [SOUND_CHAN_STEREO] = NULL,
1123 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1124 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1125 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1126 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1127 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1130 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1131 AUDIO_DSP.stereo_mode == STEREO_MONO)
1133 value = SOUND_CHAN_STEREO;
1136 /* This doesn't apply to voice */
1137 channels_mode = value;
1138 AUDIO_DSP.channels_process = channels_process_functions[value];
1141 #if CONFIG_CODEC == SWCODEC
1143 #ifdef HAVE_SW_TONE_CONTROLS
1144 static void set_tone_controls(void)
1146 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1147 0xffffffff/NATIVE_FREQUENCY*3500,
1148 bass, treble, -prescale,
1149 AUDIO_DSP.tone_filter.coefs);
1150 /* Sync the voice dsp coefficients */
1151 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1152 sizeof (VOICE_DSP.tone_filter.coefs));
1154 #endif
1156 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1157 * code directly.
1159 int dsp_callback(int msg, intptr_t param)
1161 switch (msg)
1163 #ifdef HAVE_SW_TONE_CONTROLS
1164 case DSP_CALLBACK_SET_PRESCALE:
1165 prescale = param;
1166 set_tone_controls();
1167 break;
1168 /* prescaler is always set after calling any of these, so we wait with
1169 * calculating coefs until the above case is hit.
1171 case DSP_CALLBACK_SET_BASS:
1172 bass = param;
1173 break;
1174 case DSP_CALLBACK_SET_TREBLE:
1175 treble = param;
1176 break;
1177 #ifdef HAVE_SW_VOLUME_CONTROL
1178 case DSP_CALLBACK_SET_SW_VOLUME:
1179 set_gain(&AUDIO_DSP);
1180 break;
1181 #endif
1182 #endif
1183 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1184 dsp_set_channel_config(param);
1185 break;
1186 case DSP_CALLBACK_SET_STEREO_WIDTH:
1187 dsp_set_stereo_width(param);
1188 break;
1189 default:
1190 break;
1192 return 0;
1194 #endif
1196 /* Process and convert src audio to dst based on the DSP configuration,
1197 * reading count number of audio samples. dst is assumed to be large
1198 * enough; use dsp_output_count() to get the required number. src is an
1199 * array of pointers; for mono and interleaved stereo, it contains one
1200 * pointer to the start of the audio data and the other is ignored; for
1201 * non-interleaved stereo, it contains two pointers, one for each audio
1202 * channel. Returns number of bytes written to dst.
1204 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1206 int32_t *tmp[2];
1207 static long last_yield;
1208 long tick;
1209 int written = 0;
1211 #if defined(CPU_COLDFIRE)
1212 /* set emac unit for dsp processing, and save old macsr, we're running in
1213 codec thread context at this point, so can't clobber it */
1214 unsigned long old_macsr = coldfire_get_macsr();
1215 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1216 #endif
1218 if (new_gain)
1219 dsp_set_replaygain(); /* Gain has changed */
1221 /* Perform at least one yield before starting */
1222 last_yield = current_tick;
1223 yield();
1225 /* Testing function pointers for NULL is preferred since the pointer
1226 will be preloaded to be used for the call if not. */
1227 while (count > 0)
1229 int samples = MIN(sample_buf_count/2, count);
1230 count -= samples;
1232 dsp->input_samples(samples, src, tmp);
1234 #ifdef HAVE_PITCHSCREEN
1235 if (dsp->tdspeed_active)
1236 samples = tdspeed_doit(tmp, samples);
1237 #endif
1239 int chunk_offset = 0;
1240 while (samples > 0)
1242 int32_t *t2[2];
1243 t2[0] = tmp[0]+chunk_offset;
1244 t2[1] = tmp[1]+chunk_offset;
1246 int chunk = MIN(sample_buf_count/2, samples);
1247 chunk_offset += chunk;
1248 samples -= chunk;
1250 if (dsp->apply_gain)
1251 dsp->apply_gain(chunk, &dsp->data, t2);
1253 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1254 break; /* I'm pretty sure we're downsampling here */
1256 if (dsp->apply_crossfeed)
1257 dsp->apply_crossfeed(chunk, t2);
1259 if (dsp->eq_process)
1260 dsp->eq_process(chunk, t2);
1262 #ifdef HAVE_SW_TONE_CONTROLS
1263 if ((bass | treble) != 0)
1264 eq_filter(t2, &dsp->tone_filter, chunk,
1265 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1266 #endif
1268 if (dsp->channels_process)
1269 dsp->channels_process(chunk, t2);
1271 if (dsp->compressor_process)
1272 dsp->compressor_process(chunk, t2);
1274 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1276 written += chunk;
1277 dst += chunk * sizeof (int16_t) * 2;
1279 /* yield at least once each tick */
1280 tick = current_tick;
1281 if (TIME_AFTER(tick, last_yield))
1283 last_yield = tick;
1284 yield();
1289 #if defined(CPU_COLDFIRE)
1290 /* set old macsr again */
1291 coldfire_set_macsr(old_macsr);
1292 #endif
1293 return written;
1296 /* Given count number of input samples, calculate the maximum number of
1297 * samples of output data that would be generated (the calculation is not
1298 * entirely exact and rounds upwards to be on the safe side; during
1299 * resampling, the number of samples generated depends on the current state
1300 * of the resampler).
1302 /* dsp_input_size MUST be called afterwards */
1303 int dsp_output_count(struct dsp_config *dsp, int count)
1305 #ifdef HAVE_PITCHSCREEN
1306 if (dsp->tdspeed_active)
1307 count = tdspeed_est_output_size();
1308 #endif
1309 if (dsp->resample)
1311 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1312 + (dsp->frequency - 1)) / dsp->frequency);
1315 /* Now we have the resampled sample count which must not exceed
1316 * RESAMPLE_BUF_RIGHT_CHANNEL to avoid resample buffer overflow. One
1317 * must call dsp_input_count() to get the correct input sample
1318 * count.
1320 if (count > RESAMPLE_BUF_RIGHT_CHANNEL)
1321 count = RESAMPLE_BUF_RIGHT_CHANNEL;
1323 return count;
1326 /* Given count output samples, calculate number of input samples
1327 * that would be consumed in order to fill the output buffer.
1329 int dsp_input_count(struct dsp_config *dsp, int count)
1331 /* count is now the number of resampled input samples. Convert to
1332 original input samples. */
1333 if (dsp->resample)
1335 /* Use the real resampling delta =
1336 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1337 * round towards zero to avoid buffer overflows. */
1338 count = (int)(((unsigned long)count *
1339 dsp->data.resample_data.delta) >> 16);
1342 #ifdef HAVE_PITCHSCREEN
1343 if (dsp->tdspeed_active)
1344 count = tdspeed_est_input_size(count);
1345 #endif
1347 return count;
1350 static void dsp_set_gain_var(long *var, long value)
1352 *var = value;
1353 new_gain = true;
1356 static void dsp_update_functions(struct dsp_config *dsp)
1358 sample_input_new_format(dsp);
1359 sample_output_new_format(dsp);
1360 if (dsp == &AUDIO_DSP)
1361 dsp_set_crossfeed(crossfeed_enabled);
1364 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1366 switch (setting)
1368 case DSP_MYDSP:
1369 switch (value)
1371 case CODEC_IDX_AUDIO:
1372 return (intptr_t)&AUDIO_DSP;
1373 case CODEC_IDX_VOICE:
1374 return (intptr_t)&VOICE_DSP;
1375 default:
1376 return (intptr_t)NULL;
1379 case DSP_SET_FREQUENCY:
1380 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1381 /* Fall through!!! */
1382 case DSP_SWITCH_FREQUENCY:
1383 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1384 /* Account for playback speed adjustment when setting dsp->frequency
1385 if we're called from the main audio thread. Voice UI thread should
1386 not need this feature.
1388 #ifdef HAVE_PITCHSCREEN
1389 if (dsp == &AUDIO_DSP)
1390 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1391 else
1392 #endif
1393 dsp->frequency = dsp->codec_frequency;
1395 resampler_new_delta(dsp);
1396 #ifdef HAVE_PITCHSCREEN
1397 tdspeed_setup(dsp);
1398 #endif
1399 break;
1401 case DSP_SET_SAMPLE_DEPTH:
1402 dsp->sample_depth = value;
1404 if (dsp->sample_depth <= NATIVE_DEPTH)
1406 dsp->frac_bits = WORD_FRACBITS;
1407 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1408 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1409 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1411 else
1413 dsp->frac_bits = value;
1414 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1415 dsp->data.clip_max = (1 << value) - 1;
1416 dsp->data.clip_min = -(1 << value);
1419 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1420 sample_input_new_format(dsp);
1421 dither_init(dsp);
1422 break;
1424 case DSP_SET_STEREO_MODE:
1425 dsp->stereo_mode = value;
1426 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1427 dsp_update_functions(dsp);
1428 #ifdef HAVE_PITCHSCREEN
1429 tdspeed_setup(dsp);
1430 #endif
1431 break;
1433 case DSP_RESET:
1434 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1435 dsp->data.num_channels = 2;
1436 dsp->sample_depth = NATIVE_DEPTH;
1437 dsp->frac_bits = WORD_FRACBITS;
1438 dsp->sample_bytes = sizeof (int16_t);
1439 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1440 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1441 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1442 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1444 if (dsp == &AUDIO_DSP)
1446 track_gain = 0;
1447 album_gain = 0;
1448 track_peak = 0;
1449 album_peak = 0;
1450 new_gain = true;
1453 dsp_update_functions(dsp);
1454 resampler_new_delta(dsp);
1455 #ifdef HAVE_PITCHSCREEN
1456 tdspeed_setup(dsp);
1457 #endif
1458 if (dsp == &AUDIO_DSP)
1459 release_gain = UNITY;
1460 break;
1462 case DSP_FLUSH:
1463 memset(&dsp->data.resample_data, 0,
1464 sizeof (dsp->data.resample_data));
1465 resampler_new_delta(dsp);
1466 dither_init(dsp);
1467 #ifdef HAVE_PITCHSCREEN
1468 tdspeed_setup(dsp);
1469 #endif
1470 if (dsp == &AUDIO_DSP)
1471 release_gain = UNITY;
1472 break;
1474 case DSP_SET_TRACK_GAIN:
1475 if (dsp == &AUDIO_DSP)
1476 dsp_set_gain_var(&track_gain, value);
1477 break;
1479 case DSP_SET_ALBUM_GAIN:
1480 if (dsp == &AUDIO_DSP)
1481 dsp_set_gain_var(&album_gain, value);
1482 break;
1484 case DSP_SET_TRACK_PEAK:
1485 if (dsp == &AUDIO_DSP)
1486 dsp_set_gain_var(&track_peak, value);
1487 break;
1489 case DSP_SET_ALBUM_PEAK:
1490 if (dsp == &AUDIO_DSP)
1491 dsp_set_gain_var(&album_peak, value);
1492 break;
1494 default:
1495 return 0;
1498 return 1;
1501 int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
1503 int type;
1505 bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
1506 || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1507 && global_settings.playlist_shuffle));
1509 type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
1510 : have_track_gain ? REPLAYGAIN_TRACK : -1;
1512 return type;
1515 void dsp_set_replaygain(void)
1517 long gain = 0;
1519 new_gain = false;
1521 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1522 global_settings.replaygain_noclip)
1524 bool track_mode = get_replaygain_mode(track_gain != 0,
1525 album_gain != 0) == REPLAYGAIN_TRACK;
1526 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1528 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1530 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1532 if (global_settings.replaygain_preamp)
1534 long preamp = get_replaygain_int(
1535 global_settings.replaygain_preamp * 10);
1537 gain = (long) (((int64_t) gain * preamp) >> 24);
1541 if (gain == 0)
1543 /* So that noclip can work even with no gain information. */
1544 gain = DEFAULT_GAIN;
1547 if (global_settings.replaygain_noclip && (peak != 0)
1548 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1550 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1553 if (gain == DEFAULT_GAIN)
1555 /* Nothing to do, disable processing. */
1556 gain = 0;
1560 /* Store in S7.24 format to simplify calculations. */
1561 replaygain = gain;
1562 set_gain(&AUDIO_DSP);
1565 /** SET COMPRESSOR
1566 * Called by the menu system to configure the compressor process */
1567 void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
1568 int c_knee, int c_release)
1570 bool changed = false;
1571 bool active = (c_threshold < 0);
1572 bool new_auto_gain = (c_gain == 1);
1573 const int comp_ratio[] = {2, 4, 6, 10, 0};
1574 int new_ratio = comp_ratio[c_ratio];
1575 bool new_knee = (c_knee == 1);
1576 int new_release = c_release * NATIVE_FREQUENCY / 1000;
1578 if (c_menu.threshold != c_threshold)
1580 changed = true;
1581 c_menu.threshold = c_threshold;
1582 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1583 c_menu.threshold, active ? "Yes" : "No");
1586 if (c_menu.auto_gain != new_auto_gain)
1588 changed = true;
1589 c_menu.auto_gain = new_auto_gain;
1590 logf(" Compressor Makeup Gain: %s",
1591 c_menu.auto_gain ? "Auto" : "Off");
1594 if (c_menu.ratio != new_ratio)
1596 changed = true;
1597 c_menu.ratio = new_ratio;
1598 if (c_menu.ratio)
1599 { logf(" Compressor Ratio: %d:1", c_menu.ratio); }
1600 else
1601 { logf(" Compressor Ratio: Limit"); }
1604 if (c_menu.soft_knee != new_knee)
1606 changed = true;
1607 c_menu.soft_knee = new_knee;
1608 logf(" Compressor Knee: %s", c_menu.soft_knee==1?"Soft":"Hard");
1611 if (c_menu.release != new_release)
1613 changed = true;
1614 c_menu.release = new_release;
1615 logf(" Compressor Release: %d", c_menu.release);
1618 if (changed && active)
1620 /* configure variables for compressor operation */
1621 int i;
1622 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1623 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1624 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1625 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1626 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1627 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1628 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1629 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1630 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1632 struct curve_point
1634 int32_t db; /* S15.16 format */
1635 int32_t offset; /* S15.16 format */
1636 } db_curve[5];
1638 /** Set up the shape of the compression curve first as decibel values*/
1639 /* db_curve[0] = bottom of knee
1640 [1] = threshold
1641 [2] = top of knee
1642 [3] = 0 db input
1643 [4] = ~+12db input (2 bits clipping overhead) */
1645 db_curve[1].db = c_menu.threshold << 16;
1646 if (c_menu.soft_knee)
1648 /* bottom of knee is 3dB below the threshold for soft knee*/
1649 db_curve[0].db = db_curve[1].db - (3 << 16);
1650 /* top of knee is 3dB above the threshold for soft knee */
1651 db_curve[2].db = db_curve[1].db + (3 << 16);
1652 if (c_menu.ratio)
1653 /* offset = -3db * (ratio - 1) / ratio */
1654 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1655 * (c_menu.ratio - 1) / c_menu.ratio);
1656 else
1657 /* offset = -3db for hard limit */
1658 db_curve[2].offset = (-3 << 16);
1660 else
1662 /* bottom of knee is at the threshold for hard knee */
1663 db_curve[0].db = c_menu.threshold << 16;
1664 /* top of knee is at the threshold for hard knee */
1665 db_curve[2].db = c_menu.threshold << 16;
1666 db_curve[2].offset = 0;
1669 /* Calculate 0db and ~+12db offsets */
1670 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1671 if (c_menu.ratio)
1673 /* offset = threshold * (ratio - 1) / ratio */
1674 db_curve[3].offset = (int32_t)((long long)(c_menu.threshold << 16)
1675 * (c_menu.ratio - 1) / c_menu.ratio);
1676 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1677 * (c_menu.ratio - 1) / c_menu.ratio) + db_curve[3].offset;
1679 else
1681 /* offset = threshold for hard limit */
1682 db_curve[3].offset = (c_menu.threshold << 16);
1683 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1686 /** Now set up the comp_curve table with compression offsets in the form
1687 of gain factors in S7.24 format */
1688 /* comp_curve[0] is 0 (-infinity db) input */
1689 comp_curve[0] = UNITY;
1690 /* comp_curve[1 to 63] are intermediate compression values corresponding
1691 to the 6 MSB of the input values of a non-clipped signal */
1692 for (i = 1; i < 64; i++)
1694 /* db constants are stored as positive numbers;
1695 make them negative here */
1696 int32_t this_db = -db[i];
1698 /* no compression below the knee */
1699 if (this_db <= db_curve[0].db)
1700 comp_curve[i] = UNITY;
1702 /* if soft knee and below top of knee,
1703 interpolate along soft knee slope */
1704 else if (c_menu.soft_knee && (this_db <= db_curve[2].db))
1705 comp_curve[i] = fp_factor(fp_mul(
1706 ((this_db - db_curve[0].db) / 6),
1707 db_curve[2].offset, 16), 16) << 8;
1709 /* interpolate along ratio slope above the knee */
1710 else
1711 comp_curve[i] = fp_factor(fp_mul(
1712 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1713 db_curve[3].offset, 16), 16) << 8;
1715 /* comp_curve[64] is the compression level of a maximum level,
1716 non-clipped signal */
1717 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1719 /* comp_curve[65] is the compression level of a maximum level,
1720 clipped signal */
1721 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1723 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1724 logf("\n *** Compression Offsets ***");
1725 /* some settings for display only, not used in calculations */
1726 db_curve[0].offset = 0;
1727 db_curve[1].offset = 0;
1728 db_curve[3].db = 0;
1730 for (i = 0; i <= 4; i++)
1732 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1733 (float)db_curve[i].db / (1 << 16),
1734 (float)db_curve[i].offset / (1 << 16));
1737 logf("\nGain factors:");
1738 for (i = 1; i <= 65; i++)
1740 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1741 if (i % 4 == 0) debugf("\n");
1743 debugf("\n");
1744 #endif
1746 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1747 comp_makeup_gain = c_menu.auto_gain ?
1748 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1749 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1751 /* calculate per-sample gain change a rate of 10db over release time */
1752 comp_rel_slope = 0xAF0BB2 / c_menu.release;
1753 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1755 release_gain = UNITY;
1758 /* enable/disable the compressor */
1759 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1762 /** GET COMPRESSION GAIN
1763 * Returns the required gain factor in S7.24 format in order to compress the
1764 * sample in accordance with the compression curve. Always 1 or less.
1766 static inline int32_t get_compression_gain(int32_t sample)
1768 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1770 /* sample must be positive */
1771 if (sample < 0)
1772 sample = -(sample + 1);
1774 /* shift sample into 15 frac bit range */
1775 if (frac_bits_offset > 0)
1776 sample >>= frac_bits_offset;
1777 if (frac_bits_offset < 0)
1778 sample <<= -frac_bits_offset;
1780 /* normal case: sample isn't clipped */
1781 if (sample < (1 << 15))
1783 /* index is 6 MSB, rem is 9 LSB */
1784 int index = sample >> 9;
1785 int32_t rem = (sample & 0x1FF) << 22;
1787 /* interpolate from the compression curve:
1788 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1789 return comp_curve[index] - (FRACMUL(rem,
1790 (comp_curve[index] - comp_curve[index + 1])));
1792 /* sample is somewhat clipped, up to 2 bits of overhead */
1793 if (sample < (1 << 17))
1795 /* straight interpolation:
1796 higher gain - ((clipped portion of sample * 4/3
1797 / (1 << 31)) * (higher gain - lower gain)) */
1798 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1799 (comp_curve[64] - comp_curve[65])));
1802 /* sample is too clipped, return invalid value */
1803 return -1;
1806 /** COMPRESSOR PROCESS
1807 * Changes the gain of the samples according to the compressor curve
1809 static void compressor_process(int count, int32_t *buf[])
1811 const int num_chan = AUDIO_DSP.data.num_channels;
1812 int32_t *in_buf[2] = {buf[0], buf[1]};
1814 while (count-- > 0)
1816 int ch;
1817 /* use lowest (most compressed) gain factor of the output buffer
1818 sample pair for both samples (mono is also handled correctly here) */
1819 int32_t sample_gain = UNITY;
1820 for (ch = 0; ch < num_chan; ch++)
1822 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1823 if (this_gain < sample_gain)
1824 sample_gain = this_gain;
1827 /* perform release slope; skip if no compression and no release slope */
1828 if ((sample_gain != UNITY) || (release_gain != UNITY))
1830 /* if larger offset than previous slope, start new release slope */
1831 if ((sample_gain <= release_gain) && (sample_gain > 0))
1833 release_gain = sample_gain;
1835 else
1836 /* keep sloping towards unity gain (and ignore invalid value) */
1838 release_gain += comp_rel_slope;
1839 if (release_gain > UNITY)
1841 release_gain = UNITY;
1846 /* total gain factor is the product of release gain and makeup gain,
1847 but avoid computation if possible */
1848 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1849 (comp_makeup_gain == UNITY) ? release_gain :
1850 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1852 /* Implement the compressor: apply total gain factor (if any) to the
1853 output buffer sample pair/mono sample */
1854 if (total_gain != UNITY)
1856 for (ch = 0; ch < num_chan; ch++)
1858 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1861 in_buf[0]++;
1862 in_buf[1]++;