Fix reds. No need for #ifdef to save buttons anymore.
[maemo-rb.git] / apps / dsp.c
blob00de511dd047b04a38c2caec66446db902069d19
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 "system.h"
23 #include <sound.h>
24 #include "dsp.h"
25 #include "dsp-util.h"
26 #include "eq.h"
27 #include "kernel.h"
28 #include "settings.h"
29 #include "replaygain.h"
30 #include "tdspeed.h"
31 #include "core_alloc.h"
32 #include "fixedpoint.h"
33 #include "fracmul.h"
35 /* Define LOGF_ENABLE to enable logf output in this file */
36 /*#define LOGF_ENABLE*/
37 #include "logf.h"
39 /* 16-bit samples are scaled based on these constants. The shift should be
40 * no more than 15.
42 #define WORD_SHIFT 12
43 #define WORD_FRACBITS 27
45 #define NATIVE_DEPTH 16
46 #define SMALL_SAMPLE_BUF_COUNT 128 /* Per channel */
47 #define DEFAULT_GAIN 0x01000000
49 /* enums to index conversion properly with stereo mode and other settings */
50 enum
52 SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED,
53 SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED,
54 SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO,
55 SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES,
56 SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES,
57 SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES,
58 SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES
61 enum
63 SAMPLE_OUTPUT_MONO = 0,
64 SAMPLE_OUTPUT_STEREO,
65 SAMPLE_OUTPUT_DITHERED_MONO,
66 SAMPLE_OUTPUT_DITHERED_STEREO
69 /****************************************************************************
70 * NOTE: Any assembly routines that use these structures must be updated
71 * if current data members are moved or changed.
73 struct resample_data
75 uint32_t delta; /* 00h */
76 uint32_t phase; /* 04h */
77 int32_t last_sample[2]; /* 08h */
78 /* 10h */
81 /* This is for passing needed data to assembly dsp routines. If another
82 * dsp parameter needs to be passed, add to the end of the structure
83 * and remove from dsp_config.
84 * If another function type becomes assembly optimized and requires dsp
85 * config info, add a pointer paramter of type "struct dsp_data *".
86 * If removing something from other than the end, reserve the spot or
87 * else update every implementation for every target.
88 * Be sure to add the offset of the new member for easy viewing as well. :)
89 * It is the first member of dsp_config and all members can be accessesed
90 * through the main aggregate but this is intended to make a safe haven
91 * for these items whereas the c part can be rearranged at will. dsp_data
92 * could even moved within dsp_config without disurbing the order.
94 struct dsp_data
96 int output_scale; /* 00h */
97 int num_channels; /* 04h */
98 struct resample_data resample_data; /* 08h */
99 int32_t clip_min; /* 18h */
100 int32_t clip_max; /* 1ch */
101 int32_t gain; /* 20h - Note that this is in S8.23 format. */
102 /* 24h */
105 /* No asm...yet */
106 struct dither_data
108 long error[3]; /* 00h */
109 long random; /* 0ch */
110 /* 10h */
113 struct crossfeed_data
115 int32_t gain; /* 00h - Direct path gain */
116 int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */
117 int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */
118 int32_t delay[13][2]; /* 20h */
119 int32_t *index; /* 88h - Current pointer into the delay line */
120 /* 8ch */
123 /* Current setup is one lowshelf filters three peaking filters and one
124 * highshelf filter. Varying the number of shelving filters make no sense,
125 * but adding peaking filters is possible.
127 struct eq_state
129 char enabled[5]; /* 00h - Flags for active filters */
130 struct eqfilter filters[5]; /* 08h - packing is 4? */
131 /* 10ch */
134 /* Include header with defines which functions are implemented in assembly
135 code for the target */
136 #include <dsp_asm.h>
138 /* Typedefs keep things much neater in this case */
139 typedef void (*sample_input_fn_type)(int count, const char *src[],
140 int32_t *dst[]);
141 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
142 const int32_t *src[], int32_t *dst[]);
143 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
144 const int32_t *src[], int16_t *dst);
146 /* Single-DSP channel processing in place */
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[]);
153 ***************************************************************************/
155 struct dsp_config
157 struct dsp_data data; /* Config members for use in asm routines */
158 long codec_frequency; /* Sample rate of data coming from the codec */
159 long frequency; /* Effective sample rate after pitch shift (if any) */
160 int sample_depth;
161 int sample_bytes;
162 int stereo_mode;
163 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
164 #ifdef HAVE_PITCHSCREEN
165 bool tdspeed_active; /* Timestretch is in use */
166 #endif
167 int frac_bits;
168 #ifdef HAVE_SW_TONE_CONTROLS
169 /* Filter struct for software bass/treble controls */
170 struct eqfilter tone_filter;
171 #endif
172 /* Functions that change depending upon settings - NULL if stage is
173 disabled */
174 sample_input_fn_type input_samples;
175 resample_fn_type resample;
176 sample_output_fn_type output_samples;
177 /* These will be NULL for the voice codec and is more economical that
178 way */
179 channels_process_dsp_fn_type apply_gain;
180 channels_process_fn_type apply_crossfeed;
181 channels_process_fn_type eq_process;
182 channels_process_fn_type channels_process;
183 channels_process_fn_type compressor_process;
186 /* General DSP config */
187 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
188 /* Dithering */
189 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
190 static long dither_mask IBSS_ATTR;
191 static long dither_bias IBSS_ATTR;
192 /* Crossfeed */
193 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
195 .index = (int32_t *)crossfeed_data.delay
198 /* Equalizer */
199 static struct eq_state eq_data; /* A */
201 /* Software tone controls */
202 #ifdef HAVE_SW_TONE_CONTROLS
203 static int prescale; /* A/V */
204 static int bass; /* A/V */
205 static int treble; /* A/V */
206 #endif
208 /* Settings applicable to audio codec only */
209 #ifdef HAVE_PITCHSCREEN
210 static int32_t pitch_ratio = PITCH_SPEED_100;
211 static int big_sample_locks;
212 #endif
213 static int channels_mode;
214 long dsp_sw_gain;
215 long dsp_sw_cross;
216 static bool dither_enabled;
217 static long eq_precut;
218 static long track_gain;
219 static bool new_gain;
220 static long album_gain;
221 static long track_peak;
222 static long album_peak;
223 static long replaygain;
224 static bool crossfeed_enabled;
226 #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
227 #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
229 /* The internal format is 32-bit samples, non-interleaved, stereo. This
230 * format is similar to the raw output from several codecs, so the amount
231 * of copying needed is minimized for that case.
234 #define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
235 #define SMALL_RESAMPLE_BUF_COUNT (SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO)
236 #define BIG_SAMPLE_BUF_COUNT SMALL_RESAMPLE_BUF_COUNT
237 #define BIG_RESAMPLE_BUF_COUNT (BIG_SAMPLE_BUF_COUNT * RESAMPLE_RATIO)
239 static int32_t small_sample_buf[2][SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
240 static int32_t small_resample_buf[2][SMALL_RESAMPLE_BUF_COUNT] IBSS_ATTR;
242 #ifdef HAVE_PITCHSCREEN
243 static int32_t (* big_sample_buf)[BIG_SAMPLE_BUF_COUNT] = NULL;
244 static int32_t (* big_resample_buf)[BIG_RESAMPLE_BUF_COUNT] = NULL;
245 #endif
247 static int sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
248 static int32_t *sample_buf[2] = { small_sample_buf[0], small_sample_buf[1] };
249 static int resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
250 static int32_t *resample_buf[2] = { small_resample_buf[0], small_resample_buf[1] };
252 /* compressor */
253 static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
254 static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
255 static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
256 static int32_t release_gain IBSS_ATTR; /* S7.24 format */
257 #define UNITY (1L << 24) /* unity gain in S7.24 format */
258 static void compressor_process(int count, int32_t *buf[]);
261 #ifdef HAVE_PITCHSCREEN
262 int32_t sound_get_pitch(void)
264 return pitch_ratio;
267 void sound_set_pitch(int32_t percent)
269 pitch_ratio = percent;
270 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
271 AUDIO_DSP.codec_frequency);
274 static void tdspeed_set_pointers( bool time_stretch_active )
276 if( time_stretch_active )
278 sample_buf_count = BIG_SAMPLE_BUF_COUNT;
279 resample_buf_count = BIG_RESAMPLE_BUF_COUNT;
280 sample_buf[0] = big_sample_buf[0];
281 sample_buf[1] = big_sample_buf[1];
282 resample_buf[0] = big_resample_buf[0];
283 resample_buf[1] = big_resample_buf[1];
285 else
287 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
288 resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
289 sample_buf[0] = small_sample_buf[0];
290 sample_buf[1] = small_sample_buf[1];
291 resample_buf[0] = small_resample_buf[0];
292 resample_buf[1] = small_resample_buf[1];
296 static void tdspeed_setup(struct dsp_config *dspc)
298 /* Assume timestretch will not be used */
299 dspc->tdspeed_active = false;
301 tdspeed_set_pointers( false );
303 if (!dsp_timestretch_available())
304 return; /* Timestretch not enabled or buffer not allocated */
306 if (dspc->tdspeed_percent == 0)
307 dspc->tdspeed_percent = PITCH_SPEED_100;
309 if (!tdspeed_config(
310 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
311 dspc->stereo_mode != STEREO_MONO,
312 dspc->tdspeed_percent))
313 return; /* Timestretch not possible or needed with these parameters */
315 /* Timestretch is to be used */
316 dspc->tdspeed_active = true;
318 tdspeed_set_pointers( true );
322 static int move_callback(int handle, void* current, void* new)
324 (void)handle;(void)current;
326 if ( big_sample_locks > 0 )
327 return BUFLIB_CB_CANNOT_MOVE;
329 big_sample_buf = new;
331 /* no allocation without timestretch enabled */
332 tdspeed_set_pointers( true );
333 return BUFLIB_CB_OK;
336 static void lock_sample_buf( bool lock )
338 if ( lock )
339 big_sample_locks++;
340 else
341 big_sample_locks--;
344 static struct buflib_callbacks ops = {
345 .move_callback = move_callback,
346 .shrink_callback = NULL,
350 void dsp_timestretch_enable(bool enabled)
352 /* Hook to set up timestretch buffer on first call to settings_apply() */
353 static int handle = -1;
354 if (enabled)
356 if (big_sample_buf)
357 return; /* already allocated and enabled */
359 /* Set up timestretch buffers */
360 big_sample_buf = &small_resample_buf[0];
361 handle = core_alloc_ex("resample buf",
362 2 * BIG_RESAMPLE_BUF_COUNT * sizeof(int32_t),
363 &ops);
364 big_sample_locks = 0;
365 enabled = handle >= 0;
367 if (enabled)
369 /* success, now setup tdspeed */
370 big_resample_buf = core_get_data(handle);
372 tdspeed_init();
373 tdspeed_setup(&AUDIO_DSP);
377 if (!enabled)
379 dsp_set_timestretch(PITCH_SPEED_100);
380 tdspeed_finish();
382 if (handle >= 0)
383 core_free(handle);
385 handle = -1;
386 big_sample_buf = NULL;
390 void dsp_set_timestretch(int32_t percent)
392 AUDIO_DSP.tdspeed_percent = percent;
393 tdspeed_setup(&AUDIO_DSP);
396 int32_t dsp_get_timestretch()
398 return AUDIO_DSP.tdspeed_percent;
401 bool dsp_timestretch_available()
403 return (global_settings.timestretch_enabled && big_sample_buf);
405 #endif /* HAVE_PITCHSCREEN */
407 /* Convert count samples to the internal format, if needed. Updates src
408 * to point past the samples "consumed" and dst is set to point to the
409 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
410 * is no point in processing the same data twice.
413 /* convert count 16-bit mono to 32-bit mono */
414 static void sample_input_lte_native_mono(
415 int count, const char *src[], int32_t *dst[])
417 const int16_t *s = (int16_t *) src[0];
418 const int16_t * const send = s + count;
419 int32_t *d = dst[0] = dst[1] = sample_buf[0];
420 int scale = WORD_SHIFT;
422 while (s < send)
424 *d++ = *s++ << scale;
427 src[0] = (char *)s;
430 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
431 static void sample_input_lte_native_i_stereo(
432 int count, const char *src[], int32_t *dst[])
434 const int32_t *s = (int32_t *) src[0];
435 const int32_t * const send = s + count;
436 int32_t *dl = dst[0] = sample_buf[0];
437 int32_t *dr = dst[1] = sample_buf[1];
438 int scale = WORD_SHIFT;
440 while (s < send)
442 int32_t slr = *s++;
443 #ifdef ROCKBOX_LITTLE_ENDIAN
444 *dl++ = (slr >> 16) << scale;
445 *dr++ = (int32_t)(int16_t)slr << scale;
446 #else /* ROCKBOX_BIG_ENDIAN */
447 *dl++ = (int32_t)(int16_t)slr << scale;
448 *dr++ = (slr >> 16) << scale;
449 #endif
452 src[0] = (char *)s;
455 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
456 static void sample_input_lte_native_ni_stereo(
457 int count, const char *src[], int32_t *dst[])
459 const int16_t *sl = (int16_t *) src[0];
460 const int16_t *sr = (int16_t *) src[1];
461 const int16_t * const slend = sl + count;
462 int32_t *dl = dst[0] = sample_buf[0];
463 int32_t *dr = dst[1] = sample_buf[1];
464 int scale = WORD_SHIFT;
466 while (sl < slend)
468 *dl++ = *sl++ << scale;
469 *dr++ = *sr++ << scale;
472 src[0] = (char *)sl;
473 src[1] = (char *)sr;
476 /* convert count 32-bit mono to 32-bit mono */
477 static void sample_input_gt_native_mono(
478 int count, const char *src[], int32_t *dst[])
480 dst[0] = dst[1] = (int32_t *)src[0];
481 src[0] = (char *)(dst[0] + count);
484 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
485 static void sample_input_gt_native_i_stereo(
486 int count, const char *src[], int32_t *dst[])
488 const int32_t *s = (int32_t *)src[0];
489 const int32_t * const send = s + 2*count;
490 int32_t *dl = dst[0] = sample_buf[0];
491 int32_t *dr = dst[1] = sample_buf[1];
493 while (s < send)
495 *dl++ = *s++;
496 *dr++ = *s++;
499 src[0] = (char *)send;
502 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
503 static void sample_input_gt_native_ni_stereo(
504 int count, const char *src[], int32_t *dst[])
506 dst[0] = (int32_t *)src[0];
507 dst[1] = (int32_t *)src[1];
508 src[0] = (char *)(dst[0] + count);
509 src[1] = (char *)(dst[1] + count);
513 * sample_input_new_format()
515 * set the to-native sample conversion function based on dsp sample parameters
517 * !DSPPARAMSYNC
518 * needs syncing with changes to the following dsp parameters:
519 * * dsp->stereo_mode (A/V)
520 * * dsp->sample_depth (A/V)
522 static void sample_input_new_format(struct dsp_config *dsp)
524 static const sample_input_fn_type sample_input_functions[] =
526 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
527 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
528 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
529 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
530 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
531 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
534 int convert = dsp->stereo_mode;
536 if (dsp->sample_depth > NATIVE_DEPTH)
537 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
539 dsp->input_samples = sample_input_functions[convert];
543 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
544 /* write mono internal format to output format */
545 static void sample_output_mono(int count, struct dsp_data *data,
546 const int32_t *src[], int16_t *dst)
548 const int32_t *s0 = src[0];
549 const int scale = data->output_scale;
550 const int dc_bias = 1 << (scale - 1);
552 while (count-- > 0)
554 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
555 *dst++ = lr;
556 *dst++ = lr;
559 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
561 /* write stereo internal format to output format */
562 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
563 static void sample_output_stereo(int count, struct dsp_data *data,
564 const int32_t *src[], int16_t *dst)
566 const int32_t *s0 = src[0];
567 const int32_t *s1 = src[1];
568 const int scale = data->output_scale;
569 const int dc_bias = 1 << (scale - 1);
571 while (count-- > 0)
573 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
574 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
577 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
580 * The "dither" code to convert the 24-bit samples produced by libmad was
581 * taken from the coolplayer project - coolplayer.sourceforge.net
583 * This function handles mono and stereo outputs.
585 static void sample_output_dithered(int count, struct dsp_data *data,
586 const int32_t *src[], int16_t *dst)
588 const int32_t mask = dither_mask;
589 const int32_t bias = dither_bias;
590 const int scale = data->output_scale;
591 const int32_t min = data->clip_min;
592 const int32_t max = data->clip_max;
593 const int32_t range = max - min;
594 int ch;
595 int16_t *d;
597 for (ch = 0; ch < data->num_channels; ch++)
599 struct dither_data * const dither = &dither_data[ch];
600 const int32_t *s = src[ch];
601 int i;
603 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
605 int32_t output, sample;
606 int32_t random;
608 /* Noise shape and bias (for correct rounding later) */
609 sample = *s;
610 sample += dither->error[0] - dither->error[1] + dither->error[2];
611 dither->error[2] = dither->error[1];
612 dither->error[1] = dither->error[0]/2;
614 output = sample + bias;
616 /* Dither, highpass triangle PDF */
617 random = dither->random*0x0019660dL + 0x3c6ef35fL;
618 output += (random & mask) - (dither->random & mask);
619 dither->random = random;
621 /* Round sample to output range */
622 output &= ~mask;
624 /* Error feedback */
625 dither->error[0] = sample - output;
627 /* Clip */
628 if ((uint32_t)(output - min) > (uint32_t)range)
630 int32_t c = min;
631 if (output > min)
632 c += range;
633 output = c;
636 /* Quantize and store */
637 *d = output >> scale;
641 if (data->num_channels == 2)
642 return;
644 /* Have to duplicate left samples into the right channel since
645 pcm buffer and hardware is interleaved stereo */
646 d = &dst[0];
648 while (count-- > 0)
650 int16_t s = *d++;
651 *d++ = s;
656 * sample_output_new_format()
658 * set the from-native to ouput sample conversion routine
660 * !DSPPARAMSYNC
661 * needs syncing with changes to the following dsp parameters:
662 * * dsp->stereo_mode (A/V)
663 * * dither_enabled (A)
665 static void sample_output_new_format(struct dsp_config *dsp)
667 static const sample_output_fn_type sample_output_functions[] =
669 sample_output_mono,
670 sample_output_stereo,
671 sample_output_dithered,
672 sample_output_dithered
675 int out = dsp->data.num_channels - 1;
677 if (dsp == &AUDIO_DSP && dither_enabled)
678 out += 2;
680 dsp->output_samples = sample_output_functions[out];
684 * Linear interpolation resampling that introduces a one sample delay because
685 * of our inability to look into the future at the end of a frame.
687 #ifndef DSP_HAVE_ASM_RESAMPLING
688 static int dsp_downsample(int count, struct dsp_data *data,
689 const int32_t *src[], int32_t *dst[])
691 int ch = data->num_channels - 1;
692 uint32_t delta = data->resample_data.delta;
693 uint32_t phase, pos;
694 int32_t *d;
696 /* Rolled channel loop actually showed slightly faster. */
699 /* Just initialize things and not worry too much about the relatively
700 * uncommon case of not being able to spit out a sample for the frame.
702 const int32_t *s = src[ch];
703 int32_t last = data->resample_data.last_sample[ch];
705 data->resample_data.last_sample[ch] = s[count - 1];
706 d = dst[ch];
707 phase = data->resample_data.phase;
708 pos = phase >> 16;
710 /* Do we need last sample of previous frame for interpolation? */
711 if (pos > 0)
712 last = s[pos - 1];
714 while (pos < (uint32_t)count)
716 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
717 phase += delta;
718 pos = phase >> 16;
719 last = s[pos - 1];
722 while (--ch >= 0);
724 /* Wrap phase accumulator back to start of next frame. */
725 data->resample_data.phase = phase - (count << 16);
726 return d - dst[0];
729 static int dsp_upsample(int count, struct dsp_data *data,
730 const int32_t *src[], int32_t *dst[])
732 int ch = data->num_channels - 1;
733 uint32_t delta = data->resample_data.delta;
734 uint32_t phase, pos;
735 int32_t *d;
737 /* Rolled channel loop actually showed slightly faster. */
740 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
741 const int32_t *s = src[ch];
742 int32_t last = data->resample_data.last_sample[ch];
744 data->resample_data.last_sample[ch] = s[count - 1];
745 d = dst[ch];
746 phase = data->resample_data.phase;
747 pos = phase >> 16;
749 while (pos == 0)
751 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
752 phase += delta;
753 pos = phase >> 16;
756 while (pos < (uint32_t)count)
758 last = s[pos - 1];
759 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
760 phase += delta;
761 pos = phase >> 16;
764 while (--ch >= 0);
766 /* Wrap phase accumulator back to start of next frame. */
767 data->resample_data.phase = phase & 0xffff;
768 return d - dst[0];
770 #endif /* DSP_HAVE_ASM_RESAMPLING */
772 static void resampler_new_delta(struct dsp_config *dsp)
774 dsp->data.resample_data.delta = (unsigned long)
775 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
777 if (dsp->frequency == NATIVE_FREQUENCY)
779 /* NOTE: If fully glitch-free transistions from no resampling to
780 resampling are desired, last_sample history should be maintained
781 even when not resampling. */
782 dsp->resample = NULL;
783 dsp->data.resample_data.phase = 0;
784 dsp->data.resample_data.last_sample[0] = 0;
785 dsp->data.resample_data.last_sample[1] = 0;
787 else if (dsp->frequency < NATIVE_FREQUENCY)
788 dsp->resample = dsp_upsample;
789 else
790 dsp->resample = dsp_downsample;
793 /* Resample count stereo samples. Updates the src array, if resampling is
794 * done, to refer to the resampled data. Returns number of stereo samples
795 * for further processing.
797 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
799 int32_t *dst[2] =
801 resample_buf[0],
802 resample_buf[1]
804 lock_sample_buf( true );
805 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
807 src[0] = dst[0];
808 src[1] = dst[dsp->data.num_channels - 1];
809 lock_sample_buf( false );
810 return count;
813 static void dither_init(struct dsp_config *dsp)
815 memset(dither_data, 0, sizeof (dither_data));
816 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
817 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
820 void dsp_dither_enable(bool enable)
822 struct dsp_config *dsp = &AUDIO_DSP;
823 dither_enabled = enable;
824 sample_output_new_format(dsp);
827 /* Applies crossfeed to the stereo signal in src.
828 * Crossfeed is a process where listening over speakers is simulated. This
829 * is good for old hard panned stereo records, which might be quite fatiguing
830 * to listen to on headphones with no crossfeed.
832 #ifndef DSP_HAVE_ASM_CROSSFEED
833 static void apply_crossfeed(int count, int32_t *buf[])
835 int32_t *hist_l = &crossfeed_data.history[0];
836 int32_t *hist_r = &crossfeed_data.history[2];
837 int32_t *delay = &crossfeed_data.delay[0][0];
838 int32_t *coefs = &crossfeed_data.coefs[0];
839 int32_t gain = crossfeed_data.gain;
840 int32_t *di = crossfeed_data.index;
842 int32_t acc;
843 int32_t left, right;
844 int i;
846 for (i = 0; i < count; i++)
848 left = buf[0][i];
849 right = buf[1][i];
851 /* Filter delayed sample from left speaker */
852 acc = FRACMUL(*di, coefs[0]);
853 acc += FRACMUL(hist_l[0], coefs[1]);
854 acc += FRACMUL(hist_l[1], coefs[2]);
855 /* Save filter history for left speaker */
856 hist_l[1] = acc;
857 hist_l[0] = *di;
858 *di++ = left;
859 /* Filter delayed sample from right speaker */
860 acc = FRACMUL(*di, coefs[0]);
861 acc += FRACMUL(hist_r[0], coefs[1]);
862 acc += FRACMUL(hist_r[1], coefs[2]);
863 /* Save filter history for right speaker */
864 hist_r[1] = acc;
865 hist_r[0] = *di;
866 *di++ = right;
867 /* Now add the attenuated direct sound and write to outputs */
868 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
869 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
871 /* Wrap delay line index if bigger than delay line size */
872 if (di >= delay + 13*2)
873 di = delay;
875 /* Write back local copies of data we've modified */
876 crossfeed_data.index = di;
878 #endif /* DSP_HAVE_ASM_CROSSFEED */
881 * dsp_set_crossfeed(bool enable)
883 * !DSPPARAMSYNC
884 * needs syncing with changes to the following dsp parameters:
885 * * dsp->stereo_mode (A)
887 void dsp_set_crossfeed(bool enable)
889 crossfeed_enabled = enable;
890 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
891 ? apply_crossfeed : NULL;
894 void dsp_set_crossfeed_direct_gain(int gain)
896 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
897 /* If gain is negative, the calculation overflowed and we need to clamp */
898 if (crossfeed_data.gain < 0)
899 crossfeed_data.gain = 0x7fffffff;
902 /* Both gains should be below 0 dB */
903 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
905 int32_t *c = crossfeed_data.coefs;
906 long scaler = get_replaygain_int(lf_gain * 10) << 7;
908 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
909 hf_gain -= lf_gain;
910 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
911 * point instead of shelf midpoint. This is for compatibility with the old
912 * crossfeed shelf filter and should be removed if crossfeed settings are
913 * ever made incompatible for any other good reason.
915 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
916 filter_shelf_coefs(cutoff, hf_gain, false, c);
917 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
918 * over 1 and can do this safely
920 c[0] = FRACMUL_SHL(c[0], scaler, 4);
921 c[1] = FRACMUL_SHL(c[1], scaler, 4);
922 c[2] <<= 4;
925 /* Apply a constant gain to the samples (e.g., for ReplayGain).
926 * Note that this must be called before the resampler.
928 #ifndef DSP_HAVE_ASM_APPLY_GAIN
929 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
931 const int32_t gain = data->gain;
932 int ch;
934 for (ch = 0; ch < data->num_channels; ch++)
936 int32_t *d = buf[ch];
937 int i;
939 for (i = 0; i < count; i++)
940 d[i] = FRACMUL_SHL(d[i], gain, 8);
943 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
945 /* Combine all gains to a global gain. */
946 static void set_gain(struct dsp_config *dsp)
948 /* gains are in S7.24 format */
949 dsp->data.gain = DEFAULT_GAIN;
951 /* Replay gain not relevant to voice */
952 if (dsp == &AUDIO_DSP && replaygain)
954 dsp->data.gain = replaygain;
957 if (dsp->eq_process && eq_precut)
959 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
962 #ifdef HAVE_SW_VOLUME_CONTROL
963 if (global_settings.volume < SW_VOLUME_MAX ||
964 global_settings.volume > SW_VOLUME_MIN)
966 int vol_gain = get_replaygain_int(global_settings.volume * 100);
967 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
969 #endif
971 if (dsp->data.gain == DEFAULT_GAIN)
973 dsp->data.gain = 0;
975 else
977 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
980 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
984 * Update the amount to cut the audio before applying the equalizer.
986 * @param precut to apply in decibels (multiplied by 10)
988 void dsp_set_eq_precut(int precut)
990 eq_precut = get_replaygain_int(precut * -10);
991 set_gain(&AUDIO_DSP);
995 * Synchronize the equalizer filter coefficients with the global settings.
997 * @param band the equalizer band to synchronize
999 void dsp_set_eq_coefs(int band)
1001 const int *setting;
1002 long gain;
1003 unsigned long cutoff, q;
1005 /* Adjust setting pointer to the band we actually want to change */
1006 setting = &global_settings.eq_band0_cutoff + (band * 3);
1008 /* Convert user settings to format required by coef generator functions */
1009 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
1010 q = *setting++;
1011 gain = *setting++;
1013 if (q == 0)
1014 q = 1;
1016 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
1017 which it should be, since we're executed from the main thread. */
1019 /* Assume a band is disabled if the gain is zero */
1020 if (gain == 0)
1022 eq_data.enabled[band] = 0;
1024 else
1026 if (band == 0)
1027 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1028 else if (band == 4)
1029 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1030 else
1031 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1033 eq_data.enabled[band] = 1;
1037 /* Apply EQ filters to those bands that have got it switched on. */
1038 static void eq_process(int count, int32_t *buf[])
1040 static const int shifts[] =
1042 EQ_SHELF_SHIFT, /* low shelf */
1043 EQ_PEAK_SHIFT, /* peaking */
1044 EQ_PEAK_SHIFT, /* peaking */
1045 EQ_PEAK_SHIFT, /* peaking */
1046 EQ_SHELF_SHIFT, /* high shelf */
1048 unsigned int channels = AUDIO_DSP.data.num_channels;
1049 int i;
1051 /* filter configuration currently is 1 low shelf filter, 3 band peaking
1052 filters and 1 high shelf filter, in that order. we need to know this
1053 so we can choose the correct shift factor.
1055 for (i = 0; i < 5; i++)
1057 if (!eq_data.enabled[i])
1058 continue;
1059 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1064 * Use to enable the equalizer.
1066 * @param enable true to enable the equalizer
1068 void dsp_set_eq(bool enable)
1070 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1071 set_gain(&AUDIO_DSP);
1074 static void dsp_set_stereo_width(int value)
1076 long width, straight, cross;
1078 width = value * 0x7fffff / 100;
1080 if (value <= 100)
1082 straight = (0x7fffff + width) / 2;
1083 cross = straight - width;
1085 else
1087 /* straight = (1 + width) / (2 * width) */
1088 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1089 cross = straight - 0x7fffff;
1092 dsp_sw_gain = straight << 8;
1093 dsp_sw_cross = cross << 8;
1097 * Implements the different channel configurations and stereo width.
1100 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1101 * completeness. */
1102 #if 0
1103 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1105 /* The channels are each just themselves */
1106 (void)count; (void)buf;
1108 #endif
1110 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1111 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1113 int32_t *sl = buf[0], *sr = buf[1];
1115 while (count-- > 0)
1117 int32_t lr = *sl/2 + *sr/2;
1118 *sl++ = lr;
1119 *sr++ = lr;
1122 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1124 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1125 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1127 const int32_t gain = dsp_sw_gain;
1128 const int32_t cross = dsp_sw_cross;
1129 int32_t *sl = buf[0], *sr = buf[1];
1131 while (count-- > 0)
1133 int32_t l = *sl;
1134 int32_t r = *sr;
1135 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1136 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1139 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1141 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1143 /* Just copy over the other channel */
1144 memcpy(buf[1], buf[0], count * sizeof (*buf));
1147 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1149 /* Just copy over the other channel */
1150 memcpy(buf[0], buf[1], count * sizeof (*buf));
1153 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1154 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1156 int32_t *sl = buf[0], *sr = buf[1];
1158 while (count-- > 0)
1160 int32_t ch = *sl/2 - *sr/2;
1161 *sl++ = ch;
1162 *sr++ = -ch;
1165 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1167 static void dsp_set_channel_config(int value)
1169 static const channels_process_fn_type channels_process_functions[] =
1171 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1172 [SOUND_CHAN_STEREO] = NULL,
1173 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1174 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1175 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1176 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1177 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1180 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1181 AUDIO_DSP.stereo_mode == STEREO_MONO)
1183 value = SOUND_CHAN_STEREO;
1186 /* This doesn't apply to voice */
1187 channels_mode = value;
1188 AUDIO_DSP.channels_process = channels_process_functions[value];
1191 #if CONFIG_CODEC == SWCODEC
1193 #ifdef HAVE_SW_TONE_CONTROLS
1194 static void set_tone_controls(void)
1196 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1197 0xffffffff/NATIVE_FREQUENCY*3500,
1198 bass, treble, -prescale,
1199 AUDIO_DSP.tone_filter.coefs);
1200 /* Sync the voice dsp coefficients */
1201 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1202 sizeof (VOICE_DSP.tone_filter.coefs));
1204 #endif
1206 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1207 * code directly.
1209 int dsp_callback(int msg, intptr_t param)
1211 switch (msg)
1213 #ifdef HAVE_SW_TONE_CONTROLS
1214 case DSP_CALLBACK_SET_PRESCALE:
1215 prescale = param;
1216 set_tone_controls();
1217 break;
1218 /* prescaler is always set after calling any of these, so we wait with
1219 * calculating coefs until the above case is hit.
1221 case DSP_CALLBACK_SET_BASS:
1222 bass = param;
1223 break;
1224 case DSP_CALLBACK_SET_TREBLE:
1225 treble = param;
1226 break;
1227 #ifdef HAVE_SW_VOLUME_CONTROL
1228 case DSP_CALLBACK_SET_SW_VOLUME:
1229 set_gain(&AUDIO_DSP);
1230 break;
1231 #endif
1232 #endif
1233 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1234 dsp_set_channel_config(param);
1235 break;
1236 case DSP_CALLBACK_SET_STEREO_WIDTH:
1237 dsp_set_stereo_width(param);
1238 break;
1239 default:
1240 break;
1242 return 0;
1244 #endif
1246 /* Process and convert src audio to dst based on the DSP configuration,
1247 * reading count number of audio samples. dst is assumed to be large
1248 * enough; use dsp_output_count() to get the required number. src is an
1249 * array of pointers; for mono and interleaved stereo, it contains one
1250 * pointer to the start of the audio data and the other is ignored; for
1251 * non-interleaved stereo, it contains two pointers, one for each audio
1252 * channel. Returns number of bytes written to dst.
1254 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1256 static int32_t *tmp[2]; /* tdspeed_doit() needs it static */
1257 static long last_yield;
1258 long tick;
1259 int written = 0;
1261 #if defined(CPU_COLDFIRE)
1262 /* set emac unit for dsp processing, and save old macsr, we're running in
1263 codec thread context at this point, so can't clobber it */
1264 unsigned long old_macsr = coldfire_get_macsr();
1265 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1266 #endif
1268 if (new_gain)
1269 dsp_set_replaygain(); /* Gain has changed */
1271 /* Perform at least one yield before starting */
1272 last_yield = current_tick;
1273 yield();
1275 /* Testing function pointers for NULL is preferred since the pointer
1276 will be preloaded to be used for the call if not. */
1277 while (count > 0)
1279 int samples = MIN(sample_buf_count, count);
1280 count -= samples;
1282 dsp->input_samples(samples, src, tmp);
1284 #ifdef HAVE_PITCHSCREEN
1285 if (dsp->tdspeed_active)
1286 samples = tdspeed_doit(tmp, samples);
1287 #endif
1289 int chunk_offset = 0;
1290 while (samples > 0)
1292 int32_t *t2[2];
1293 t2[0] = tmp[0]+chunk_offset;
1294 t2[1] = tmp[1]+chunk_offset;
1296 int chunk = MIN(sample_buf_count, samples);
1297 chunk_offset += chunk;
1298 samples -= chunk;
1300 if (dsp->apply_gain)
1301 dsp->apply_gain(chunk, &dsp->data, t2);
1303 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1304 break; /* I'm pretty sure we're downsampling here */
1306 if (dsp->apply_crossfeed)
1307 dsp->apply_crossfeed(chunk, t2);
1309 if (dsp->eq_process)
1310 dsp->eq_process(chunk, t2);
1312 #ifdef HAVE_SW_TONE_CONTROLS
1313 if ((bass | treble) != 0)
1314 eq_filter(t2, &dsp->tone_filter, chunk,
1315 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1316 #endif
1318 if (dsp->channels_process)
1319 dsp->channels_process(chunk, t2);
1321 if (dsp->compressor_process)
1322 dsp->compressor_process(chunk, t2);
1324 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1326 written += chunk;
1327 dst += chunk * sizeof (int16_t) * 2;
1329 /* yield at least once each tick */
1330 tick = current_tick;
1331 if (TIME_AFTER(tick, last_yield))
1333 last_yield = tick;
1334 yield();
1339 #if defined(CPU_COLDFIRE)
1340 /* set old macsr again */
1341 coldfire_set_macsr(old_macsr);
1342 #endif
1343 return written;
1346 /* Given count number of input samples, calculate the maximum number of
1347 * samples of output data that would be generated (the calculation is not
1348 * entirely exact and rounds upwards to be on the safe side; during
1349 * resampling, the number of samples generated depends on the current state
1350 * of the resampler).
1352 /* dsp_input_size MUST be called afterwards */
1353 int dsp_output_count(struct dsp_config *dsp, int count)
1355 #ifdef HAVE_PITCHSCREEN
1356 if (dsp->tdspeed_active)
1357 count = tdspeed_est_output_size();
1358 #endif
1359 if (dsp->resample)
1361 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1362 + (dsp->frequency - 1)) / dsp->frequency);
1365 /* Now we have the resampled sample count which must not exceed
1366 * resample_buf_count to avoid resample buffer overflow. One
1367 * must call dsp_input_count() to get the correct input sample
1368 * count.
1370 if (count > resample_buf_count)
1371 count = resample_buf_count;
1373 return count;
1376 /* Given count output samples, calculate number of input samples
1377 * that would be consumed in order to fill the output buffer.
1379 int dsp_input_count(struct dsp_config *dsp, int count)
1381 /* count is now the number of resampled input samples. Convert to
1382 original input samples. */
1383 if (dsp->resample)
1385 /* Use the real resampling delta =
1386 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1387 * round towards zero to avoid buffer overflows. */
1388 count = (int)(((unsigned long)count *
1389 dsp->data.resample_data.delta) >> 16);
1392 #ifdef HAVE_PITCHSCREEN
1393 if (dsp->tdspeed_active)
1394 count = tdspeed_est_input_size(count);
1395 #endif
1397 return count;
1400 static void dsp_set_gain_var(long *var, long value)
1402 *var = value;
1403 new_gain = true;
1406 static void dsp_update_functions(struct dsp_config *dsp)
1408 sample_input_new_format(dsp);
1409 sample_output_new_format(dsp);
1410 if (dsp == &AUDIO_DSP)
1411 dsp_set_crossfeed(crossfeed_enabled);
1414 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1416 switch (setting)
1418 case DSP_MYDSP:
1419 switch (value)
1421 case CODEC_IDX_AUDIO:
1422 return (intptr_t)&AUDIO_DSP;
1423 case CODEC_IDX_VOICE:
1424 return (intptr_t)&VOICE_DSP;
1425 default:
1426 return (intptr_t)NULL;
1429 case DSP_SET_FREQUENCY:
1430 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1431 /* Fall through!!! */
1432 case DSP_SWITCH_FREQUENCY:
1433 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1434 /* Account for playback speed adjustment when setting dsp->frequency
1435 if we're called from the main audio thread. Voice UI thread should
1436 not need this feature.
1438 #ifdef HAVE_PITCHSCREEN
1439 if (dsp == &AUDIO_DSP)
1440 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1441 else
1442 #endif
1443 dsp->frequency = dsp->codec_frequency;
1445 resampler_new_delta(dsp);
1446 #ifdef HAVE_PITCHSCREEN
1447 tdspeed_setup(dsp);
1448 #endif
1449 break;
1451 case DSP_SET_SAMPLE_DEPTH:
1452 dsp->sample_depth = value;
1454 if (dsp->sample_depth <= NATIVE_DEPTH)
1456 dsp->frac_bits = WORD_FRACBITS;
1457 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1458 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1459 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1461 else
1463 dsp->frac_bits = value;
1464 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1465 dsp->data.clip_max = (1 << value) - 1;
1466 dsp->data.clip_min = -(1 << value);
1469 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1470 sample_input_new_format(dsp);
1471 dither_init(dsp);
1472 break;
1474 case DSP_SET_STEREO_MODE:
1475 dsp->stereo_mode = value;
1476 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1477 dsp_update_functions(dsp);
1478 #ifdef HAVE_PITCHSCREEN
1479 tdspeed_setup(dsp);
1480 #endif
1481 break;
1483 case DSP_RESET:
1484 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1485 dsp->data.num_channels = 2;
1486 dsp->sample_depth = NATIVE_DEPTH;
1487 dsp->frac_bits = WORD_FRACBITS;
1488 dsp->sample_bytes = sizeof (int16_t);
1489 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1490 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1491 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1492 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1494 if (dsp == &AUDIO_DSP)
1496 track_gain = 0;
1497 album_gain = 0;
1498 track_peak = 0;
1499 album_peak = 0;
1500 new_gain = true;
1503 dsp_update_functions(dsp);
1504 resampler_new_delta(dsp);
1505 #ifdef HAVE_PITCHSCREEN
1506 tdspeed_setup(dsp);
1507 #endif
1508 if (dsp == &AUDIO_DSP)
1509 release_gain = UNITY;
1510 break;
1512 case DSP_FLUSH:
1513 memset(&dsp->data.resample_data, 0,
1514 sizeof (dsp->data.resample_data));
1515 resampler_new_delta(dsp);
1516 dither_init(dsp);
1517 #ifdef HAVE_PITCHSCREEN
1518 tdspeed_setup(dsp);
1519 #endif
1520 if (dsp == &AUDIO_DSP)
1521 release_gain = UNITY;
1522 break;
1524 case DSP_SET_TRACK_GAIN:
1525 if (dsp == &AUDIO_DSP)
1526 dsp_set_gain_var(&track_gain, value);
1527 break;
1529 case DSP_SET_ALBUM_GAIN:
1530 if (dsp == &AUDIO_DSP)
1531 dsp_set_gain_var(&album_gain, value);
1532 break;
1534 case DSP_SET_TRACK_PEAK:
1535 if (dsp == &AUDIO_DSP)
1536 dsp_set_gain_var(&track_peak, value);
1537 break;
1539 case DSP_SET_ALBUM_PEAK:
1540 if (dsp == &AUDIO_DSP)
1541 dsp_set_gain_var(&album_peak, value);
1542 break;
1544 default:
1545 return 0;
1548 return 1;
1551 int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
1553 int type;
1555 bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
1556 || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1557 && global_settings.playlist_shuffle));
1559 type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
1560 : have_track_gain ? REPLAYGAIN_TRACK : -1;
1562 return type;
1565 void dsp_set_replaygain(void)
1567 long gain = 0;
1569 new_gain = false;
1571 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1572 global_settings.replaygain_noclip)
1574 bool track_mode = get_replaygain_mode(track_gain != 0,
1575 album_gain != 0) == REPLAYGAIN_TRACK;
1576 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1578 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1580 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1582 if (global_settings.replaygain_preamp)
1584 long preamp = get_replaygain_int(
1585 global_settings.replaygain_preamp * 10);
1587 gain = (long) (((int64_t) gain * preamp) >> 24);
1591 if (gain == 0)
1593 /* So that noclip can work even with no gain information. */
1594 gain = DEFAULT_GAIN;
1597 if (global_settings.replaygain_noclip && (peak != 0)
1598 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1600 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1603 if (gain == DEFAULT_GAIN)
1605 /* Nothing to do, disable processing. */
1606 gain = 0;
1610 /* Store in S7.24 format to simplify calculations. */
1611 replaygain = gain;
1612 set_gain(&AUDIO_DSP);
1615 /** SET COMPRESSOR
1616 * Called by the menu system to configure the compressor process */
1617 void dsp_set_compressor(void)
1619 static int curr_set[5];
1620 int new_set[5] = {
1621 global_settings.compressor_threshold,
1622 global_settings.compressor_makeup_gain,
1623 global_settings.compressor_ratio,
1624 global_settings.compressor_knee,
1625 global_settings.compressor_release_time};
1627 /* make menu values useful */
1628 int threshold = new_set[0];
1629 bool auto_gain = (new_set[1] == 1);
1630 const int comp_ratios[] = {2, 4, 6, 10, 0};
1631 int ratio = comp_ratios[new_set[2]];
1632 bool soft_knee = (new_set[3] == 1);
1633 int release = new_set[4] * NATIVE_FREQUENCY / 1000;
1635 bool changed = false;
1636 bool active = (threshold < 0);
1638 for (int i = 0; i < 5; i++)
1640 if (curr_set[i] != new_set[i])
1642 changed = true;
1643 curr_set[i] = new_set[i];
1645 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1646 switch (i)
1648 case 0:
1649 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1650 threshold, active ? "Yes" : "No");
1651 break;
1652 case 1:
1653 logf(" Compressor Makeup Gain: %s",
1654 auto_gain ? "Auto" : "Off");
1655 break;
1656 case 2:
1657 if (ratio)
1658 { logf(" Compressor Ratio: %d:1", ratio); }
1659 else
1660 { logf(" Compressor Ratio: Limit"); }
1661 break;
1662 case 3:
1663 logf(" Compressor Knee: %s", soft_knee?"Soft":"Hard");
1664 break;
1665 case 4:
1666 logf(" Compressor Release: %d", release);
1667 break;
1669 #endif
1673 if (changed && active)
1675 /* configure variables for compressor operation */
1676 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1677 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1678 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1679 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1680 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1681 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1682 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1683 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1684 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1686 struct curve_point
1688 int32_t db; /* S15.16 format */
1689 int32_t offset; /* S15.16 format */
1690 } db_curve[5];
1692 /** Set up the shape of the compression curve first as decibel values*/
1693 /* db_curve[0] = bottom of knee
1694 [1] = threshold
1695 [2] = top of knee
1696 [3] = 0 db input
1697 [4] = ~+12db input (2 bits clipping overhead) */
1699 db_curve[1].db = threshold << 16;
1700 if (soft_knee)
1702 /* bottom of knee is 3dB below the threshold for soft knee*/
1703 db_curve[0].db = db_curve[1].db - (3 << 16);
1704 /* top of knee is 3dB above the threshold for soft knee */
1705 db_curve[2].db = db_curve[1].db + (3 << 16);
1706 if (ratio)
1707 /* offset = -3db * (ratio - 1) / ratio */
1708 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1709 * (ratio - 1) / ratio);
1710 else
1711 /* offset = -3db for hard limit */
1712 db_curve[2].offset = (-3 << 16);
1714 else
1716 /* bottom of knee is at the threshold for hard knee */
1717 db_curve[0].db = threshold << 16;
1718 /* top of knee is at the threshold for hard knee */
1719 db_curve[2].db = threshold << 16;
1720 db_curve[2].offset = 0;
1723 /* Calculate 0db and ~+12db offsets */
1724 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1725 if (ratio)
1727 /* offset = threshold * (ratio - 1) / ratio */
1728 db_curve[3].offset = (int32_t)((long long)(threshold << 16)
1729 * (ratio - 1) / ratio);
1730 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1731 * (ratio - 1) / ratio) + db_curve[3].offset;
1733 else
1735 /* offset = threshold for hard limit */
1736 db_curve[3].offset = (threshold << 16);
1737 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1740 /** Now set up the comp_curve table with compression offsets in the form
1741 of gain factors in S7.24 format */
1742 /* comp_curve[0] is 0 (-infinity db) input */
1743 comp_curve[0] = UNITY;
1744 /* comp_curve[1 to 63] are intermediate compression values corresponding
1745 to the 6 MSB of the input values of a non-clipped signal */
1746 for (int i = 1; i < 64; i++)
1748 /* db constants are stored as positive numbers;
1749 make them negative here */
1750 int32_t this_db = -db[i];
1752 /* no compression below the knee */
1753 if (this_db <= db_curve[0].db)
1754 comp_curve[i] = UNITY;
1756 /* if soft knee and below top of knee,
1757 interpolate along soft knee slope */
1758 else if (soft_knee && (this_db <= db_curve[2].db))
1759 comp_curve[i] = fp_factor(fp_mul(
1760 ((this_db - db_curve[0].db) / 6),
1761 db_curve[2].offset, 16), 16) << 8;
1763 /* interpolate along ratio slope above the knee */
1764 else
1765 comp_curve[i] = fp_factor(fp_mul(
1766 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1767 db_curve[3].offset, 16), 16) << 8;
1769 /* comp_curve[64] is the compression level of a maximum level,
1770 non-clipped signal */
1771 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1773 /* comp_curve[65] is the compression level of a maximum level,
1774 clipped signal */
1775 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1777 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1778 logf("\n *** Compression Offsets ***");
1779 /* some settings for display only, not used in calculations */
1780 db_curve[0].offset = 0;
1781 db_curve[1].offset = 0;
1782 db_curve[3].db = 0;
1784 for (int i = 0; i <= 4; i++)
1786 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1787 (float)db_curve[i].db / (1 << 16),
1788 (float)db_curve[i].offset / (1 << 16));
1791 logf("\nGain factors:");
1792 for (int i = 1; i <= 65; i++)
1794 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1795 if (i % 4 == 0) debugf("\n");
1797 debugf("\n");
1798 #endif
1800 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1801 comp_makeup_gain = auto_gain ?
1802 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1803 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1805 /* calculate per-sample gain change a rate of 10db over release time */
1806 comp_rel_slope = 0xAF0BB2 / release;
1807 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1809 release_gain = UNITY;
1812 /* enable/disable the compressor */
1813 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1816 /** GET COMPRESSION GAIN
1817 * Returns the required gain factor in S7.24 format in order to compress the
1818 * sample in accordance with the compression curve. Always 1 or less.
1820 static inline int32_t get_compression_gain(int32_t sample)
1822 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1824 /* sample must be positive */
1825 if (sample < 0)
1826 sample = -(sample + 1);
1828 /* shift sample into 15 frac bit range */
1829 if (frac_bits_offset > 0)
1830 sample >>= frac_bits_offset;
1831 if (frac_bits_offset < 0)
1832 sample <<= -frac_bits_offset;
1834 /* normal case: sample isn't clipped */
1835 if (sample < (1 << 15))
1837 /* index is 6 MSB, rem is 9 LSB */
1838 int index = sample >> 9;
1839 int32_t rem = (sample & 0x1FF) << 22;
1841 /* interpolate from the compression curve:
1842 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1843 return comp_curve[index] - (FRACMUL(rem,
1844 (comp_curve[index] - comp_curve[index + 1])));
1846 /* sample is somewhat clipped, up to 2 bits of overhead */
1847 if (sample < (1 << 17))
1849 /* straight interpolation:
1850 higher gain - ((clipped portion of sample * 4/3
1851 / (1 << 31)) * (higher gain - lower gain)) */
1852 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1853 (comp_curve[64] - comp_curve[65])));
1856 /* sample is too clipped, return invalid value */
1857 return -1;
1860 /** COMPRESSOR PROCESS
1861 * Changes the gain of the samples according to the compressor curve
1863 static void compressor_process(int count, int32_t *buf[])
1865 const int num_chan = AUDIO_DSP.data.num_channels;
1866 int32_t *in_buf[2] = {buf[0], buf[1]};
1868 while (count-- > 0)
1870 int ch;
1871 /* use lowest (most compressed) gain factor of the output buffer
1872 sample pair for both samples (mono is also handled correctly here) */
1873 int32_t sample_gain = UNITY;
1874 for (ch = 0; ch < num_chan; ch++)
1876 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1877 if (this_gain < sample_gain)
1878 sample_gain = this_gain;
1881 /* perform release slope; skip if no compression and no release slope */
1882 if ((sample_gain != UNITY) || (release_gain != UNITY))
1884 /* if larger offset than previous slope, start new release slope */
1885 if ((sample_gain <= release_gain) && (sample_gain > 0))
1887 release_gain = sample_gain;
1889 else
1890 /* keep sloping towards unity gain (and ignore invalid value) */
1892 release_gain += comp_rel_slope;
1893 if (release_gain > UNITY)
1895 release_gain = UNITY;
1900 /* total gain factor is the product of release gain and makeup gain,
1901 but avoid computation if possible */
1902 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1903 (comp_makeup_gain == UNITY) ? release_gain :
1904 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1906 /* Implement the compressor: apply total gain factor (if any) to the
1907 output buffer sample pair/mono sample */
1908 if (total_gain != UNITY)
1910 for (ch = 0; ch < num_chan; ch++)
1912 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1915 in_buf[0]++;
1916 in_buf[1]++;