Make local functions and variables static where possible
[maemo-rb.git] / apps / dsp.c
blobd9c097af66046b053e11cadc5257d6c5b22b4ef4
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"
23 #include <stdbool.h>
24 #include <inttypes.h>
25 #include <string.h>
26 #include <sound.h>
27 #include "dsp.h"
28 #include "eq.h"
29 #include "kernel.h"
30 #include "system.h"
31 #include "settings.h"
32 #include "replaygain.h"
33 #include "tdspeed.h"
34 #include "core_alloc.h"
35 #include "fixedpoint.h"
36 #include "fracmul.h"
38 /* Define LOGF_ENABLE to enable logf output in this file */
39 /*#define LOGF_ENABLE*/
40 #include "logf.h"
42 /* 16-bit samples are scaled based on these constants. The shift should be
43 * no more than 15.
45 #define WORD_SHIFT 12
46 #define WORD_FRACBITS 27
48 #define NATIVE_DEPTH 16
49 #define SMALL_SAMPLE_BUF_COUNT 128 /* Per channel */
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 /* Include header with defines which functions are implemented in assembly
138 code for the target */
139 #include <dsp_asm.h>
141 /* Typedefs keep things much neater in this case */
142 typedef void (*sample_input_fn_type)(int count, const char *src[],
143 int32_t *dst[]);
144 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
145 const int32_t *src[], int32_t *dst[]);
146 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
147 const int32_t *src[], int16_t *dst);
149 /* Single-DSP channel processing in place */
150 typedef void (*channels_process_fn_type)(int count, int32_t *buf[]);
151 /* DSP local channel processing in place */
152 typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data,
153 int32_t *buf[]);
156 ***************************************************************************/
158 struct dsp_config
160 struct dsp_data data; /* Config members for use in asm routines */
161 long codec_frequency; /* Sample rate of data coming from the codec */
162 long frequency; /* Effective sample rate after pitch shift (if any) */
163 int sample_depth;
164 int sample_bytes;
165 int stereo_mode;
166 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
167 #ifdef HAVE_PITCHSCREEN
168 bool tdspeed_active; /* Timestretch is in use */
169 #endif
170 int frac_bits;
171 #ifdef HAVE_SW_TONE_CONTROLS
172 /* Filter struct for software bass/treble controls */
173 struct eqfilter tone_filter;
174 #endif
175 /* Functions that change depending upon settings - NULL if stage is
176 disabled */
177 sample_input_fn_type input_samples;
178 resample_fn_type resample;
179 sample_output_fn_type output_samples;
180 /* These will be NULL for the voice codec and is more economical that
181 way */
182 channels_process_dsp_fn_type apply_gain;
183 channels_process_fn_type apply_crossfeed;
184 channels_process_fn_type eq_process;
185 channels_process_fn_type channels_process;
186 channels_process_fn_type compressor_process;
189 /* General DSP config */
190 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
191 /* Dithering */
192 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
193 static long dither_mask IBSS_ATTR;
194 static long dither_bias IBSS_ATTR;
195 /* Crossfeed */
196 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
198 .index = (int32_t *)crossfeed_data.delay
201 /* Equalizer */
202 static struct eq_state eq_data; /* A */
204 /* Software tone controls */
205 #ifdef HAVE_SW_TONE_CONTROLS
206 static int prescale; /* A/V */
207 static int bass; /* A/V */
208 static int treble; /* A/V */
209 #endif
211 /* Settings applicable to audio codec only */
212 #ifdef HAVE_PITCHSCREEN
213 static int32_t pitch_ratio = PITCH_SPEED_100;
214 static int big_sample_locks;
215 #endif
216 static int channels_mode;
217 long dsp_sw_gain;
218 long dsp_sw_cross;
219 static bool dither_enabled;
220 static long eq_precut;
221 static long track_gain;
222 static bool new_gain;
223 static long album_gain;
224 static long track_peak;
225 static long album_peak;
226 static long replaygain;
227 static bool crossfeed_enabled;
229 #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
230 #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
232 /* The internal format is 32-bit samples, non-interleaved, stereo. This
233 * format is similar to the raw output from several codecs, so the amount
234 * of copying needed is minimized for that case.
237 #define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
238 #define SMALL_RESAMPLE_BUF_COUNT (SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO)
239 #define BIG_SAMPLE_BUF_COUNT SMALL_RESAMPLE_BUF_COUNT
240 #define BIG_RESAMPLE_BUF_COUNT (BIG_SAMPLE_BUF_COUNT * RESAMPLE_RATIO)
242 static int32_t small_sample_buf[2][SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
243 static int32_t small_resample_buf[2][SMALL_RESAMPLE_BUF_COUNT] IBSS_ATTR;
245 #ifdef HAVE_PITCHSCREEN
246 static int32_t (* big_sample_buf)[BIG_SAMPLE_BUF_COUNT] = NULL;
247 static int32_t (* big_resample_buf)[BIG_RESAMPLE_BUF_COUNT] = NULL;
248 #endif
250 static int sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
251 static int32_t *sample_buf[2] = { small_sample_buf[0], small_sample_buf[1] };
252 static int resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
253 static int32_t *resample_buf[2] = { small_resample_buf[0], small_resample_buf[1] };
255 /* compressor */
256 static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
257 static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
258 static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
259 static int32_t release_gain IBSS_ATTR; /* S7.24 format */
260 #define UNITY (1L << 24) /* unity gain in S7.24 format */
261 static void compressor_process(int count, int32_t *buf[]);
264 /* Clip sample to signed 16 bit range */
265 static inline int32_t clip_sample_16(int32_t sample)
267 if ((int16_t)sample != sample)
268 sample = 0x7fff ^ (sample >> 31);
269 return sample;
272 #ifdef HAVE_PITCHSCREEN
273 int32_t sound_get_pitch(void)
275 return pitch_ratio;
278 void sound_set_pitch(int32_t percent)
280 pitch_ratio = percent;
281 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
282 AUDIO_DSP.codec_frequency);
285 static void tdspeed_set_pointers( bool time_stretch_active )
287 if( time_stretch_active )
289 sample_buf_count = BIG_SAMPLE_BUF_COUNT;
290 resample_buf_count = BIG_RESAMPLE_BUF_COUNT;
291 sample_buf[0] = big_sample_buf[0];
292 sample_buf[1] = big_sample_buf[1];
293 resample_buf[0] = big_resample_buf[0];
294 resample_buf[1] = big_resample_buf[1];
296 else
298 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
299 resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
300 sample_buf[0] = small_sample_buf[0];
301 sample_buf[1] = small_sample_buf[1];
302 resample_buf[0] = small_resample_buf[0];
303 resample_buf[1] = small_resample_buf[1];
307 static void tdspeed_setup(struct dsp_config *dspc)
309 /* Assume timestretch will not be used */
310 dspc->tdspeed_active = false;
312 tdspeed_set_pointers( false );
314 if (!dsp_timestretch_available())
315 return; /* Timestretch not enabled or buffer not allocated */
317 if (dspc->tdspeed_percent == 0)
318 dspc->tdspeed_percent = PITCH_SPEED_100;
320 if (!tdspeed_config(
321 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
322 dspc->stereo_mode != STEREO_MONO,
323 dspc->tdspeed_percent))
324 return; /* Timestretch not possible or needed with these parameters */
326 /* Timestretch is to be used */
327 dspc->tdspeed_active = true;
329 tdspeed_set_pointers( true );
333 static int move_callback(int handle, void* current, void* new)
335 (void)handle;(void)current;
337 if ( big_sample_locks > 0 )
338 return BUFLIB_CB_CANNOT_MOVE;
340 big_sample_buf = new;
342 /* no allocation without timestretch enabled */
343 tdspeed_set_pointers( true );
344 return BUFLIB_CB_OK;
347 static void lock_sample_buf( bool lock )
349 if ( lock )
350 big_sample_locks++;
351 else
352 big_sample_locks--;
355 static struct buflib_callbacks ops = {
356 .move_callback = move_callback,
357 .shrink_callback = NULL,
361 void dsp_timestretch_enable(bool enabled)
363 /* Hook to set up timestretch buffer on first call to settings_apply() */
364 static int handle = -1;
365 if (enabled)
367 if (big_sample_buf)
368 return; /* already allocated and enabled */
370 /* Set up timestretch buffers */
371 big_sample_buf = &small_resample_buf[0];
372 handle = core_alloc_ex("resample buf",
373 2 * BIG_RESAMPLE_BUF_COUNT * sizeof(int32_t),
374 &ops);
375 big_sample_locks = 0;
376 enabled = handle >= 0;
378 if (enabled)
380 /* success, now setup tdspeed */
381 big_resample_buf = core_get_data(handle);
383 tdspeed_init();
384 tdspeed_setup(&AUDIO_DSP);
388 if (!enabled)
390 dsp_set_timestretch(PITCH_SPEED_100);
391 tdspeed_finish();
393 if (handle >= 0)
394 core_free(handle);
396 handle = -1;
397 big_sample_buf = NULL;
401 void dsp_set_timestretch(int32_t percent)
403 AUDIO_DSP.tdspeed_percent = percent;
404 tdspeed_setup(&AUDIO_DSP);
407 int32_t dsp_get_timestretch()
409 return AUDIO_DSP.tdspeed_percent;
412 bool dsp_timestretch_available()
414 return (global_settings.timestretch_enabled && big_sample_buf);
416 #endif /* HAVE_PITCHSCREEN */
418 /* Convert count samples to the internal format, if needed. Updates src
419 * to point past the samples "consumed" and dst is set to point to the
420 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
421 * is no point in processing the same data twice.
424 /* convert count 16-bit mono to 32-bit mono */
425 static void sample_input_lte_native_mono(
426 int count, const char *src[], int32_t *dst[])
428 const int16_t *s = (int16_t *) src[0];
429 const int16_t * const send = s + count;
430 int32_t *d = dst[0] = dst[1] = sample_buf[0];
431 int scale = WORD_SHIFT;
433 while (s < send)
435 *d++ = *s++ << scale;
438 src[0] = (char *)s;
441 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
442 static void sample_input_lte_native_i_stereo(
443 int count, const char *src[], int32_t *dst[])
445 const int32_t *s = (int32_t *) src[0];
446 const int32_t * const send = s + count;
447 int32_t *dl = dst[0] = sample_buf[0];
448 int32_t *dr = dst[1] = sample_buf[1];
449 int scale = WORD_SHIFT;
451 while (s < send)
453 int32_t slr = *s++;
454 #ifdef ROCKBOX_LITTLE_ENDIAN
455 *dl++ = (slr >> 16) << scale;
456 *dr++ = (int32_t)(int16_t)slr << scale;
457 #else /* ROCKBOX_BIG_ENDIAN */
458 *dl++ = (int32_t)(int16_t)slr << scale;
459 *dr++ = (slr >> 16) << scale;
460 #endif
463 src[0] = (char *)s;
466 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
467 static void sample_input_lte_native_ni_stereo(
468 int count, const char *src[], int32_t *dst[])
470 const int16_t *sl = (int16_t *) src[0];
471 const int16_t *sr = (int16_t *) src[1];
472 const int16_t * const slend = sl + count;
473 int32_t *dl = dst[0] = sample_buf[0];
474 int32_t *dr = dst[1] = sample_buf[1];
475 int scale = WORD_SHIFT;
477 while (sl < slend)
479 *dl++ = *sl++ << scale;
480 *dr++ = *sr++ << scale;
483 src[0] = (char *)sl;
484 src[1] = (char *)sr;
487 /* convert count 32-bit mono to 32-bit mono */
488 static void sample_input_gt_native_mono(
489 int count, const char *src[], int32_t *dst[])
491 dst[0] = dst[1] = (int32_t *)src[0];
492 src[0] = (char *)(dst[0] + count);
495 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
496 static void sample_input_gt_native_i_stereo(
497 int count, const char *src[], int32_t *dst[])
499 const int32_t *s = (int32_t *)src[0];
500 const int32_t * const send = s + 2*count;
501 int32_t *dl = dst[0] = sample_buf[0];
502 int32_t *dr = dst[1] = sample_buf[1];
504 while (s < send)
506 *dl++ = *s++;
507 *dr++ = *s++;
510 src[0] = (char *)send;
513 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
514 static void sample_input_gt_native_ni_stereo(
515 int count, const char *src[], int32_t *dst[])
517 dst[0] = (int32_t *)src[0];
518 dst[1] = (int32_t *)src[1];
519 src[0] = (char *)(dst[0] + count);
520 src[1] = (char *)(dst[1] + count);
524 * sample_input_new_format()
526 * set the to-native sample conversion function based on dsp sample parameters
528 * !DSPPARAMSYNC
529 * needs syncing with changes to the following dsp parameters:
530 * * dsp->stereo_mode (A/V)
531 * * dsp->sample_depth (A/V)
533 static void sample_input_new_format(struct dsp_config *dsp)
535 static const sample_input_fn_type sample_input_functions[] =
537 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
538 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
539 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
540 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
541 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
542 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
545 int convert = dsp->stereo_mode;
547 if (dsp->sample_depth > NATIVE_DEPTH)
548 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
550 dsp->input_samples = sample_input_functions[convert];
554 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
555 /* write mono internal format to output format */
556 static void sample_output_mono(int count, struct dsp_data *data,
557 const int32_t *src[], int16_t *dst)
559 const int32_t *s0 = src[0];
560 const int scale = data->output_scale;
561 const int dc_bias = 1 << (scale - 1);
563 while (count-- > 0)
565 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
566 *dst++ = lr;
567 *dst++ = lr;
570 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
572 /* write stereo internal format to output format */
573 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
574 static void sample_output_stereo(int count, struct dsp_data *data,
575 const int32_t *src[], int16_t *dst)
577 const int32_t *s0 = src[0];
578 const int32_t *s1 = src[1];
579 const int scale = data->output_scale;
580 const int dc_bias = 1 << (scale - 1);
582 while (count-- > 0)
584 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
585 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
588 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
591 * The "dither" code to convert the 24-bit samples produced by libmad was
592 * taken from the coolplayer project - coolplayer.sourceforge.net
594 * This function handles mono and stereo outputs.
596 static void sample_output_dithered(int count, struct dsp_data *data,
597 const int32_t *src[], int16_t *dst)
599 const int32_t mask = dither_mask;
600 const int32_t bias = dither_bias;
601 const int scale = data->output_scale;
602 const int32_t min = data->clip_min;
603 const int32_t max = data->clip_max;
604 const int32_t range = max - min;
605 int ch;
606 int16_t *d;
608 for (ch = 0; ch < data->num_channels; ch++)
610 struct dither_data * const dither = &dither_data[ch];
611 const int32_t *s = src[ch];
612 int i;
614 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
616 int32_t output, sample;
617 int32_t random;
619 /* Noise shape and bias (for correct rounding later) */
620 sample = *s;
621 sample += dither->error[0] - dither->error[1] + dither->error[2];
622 dither->error[2] = dither->error[1];
623 dither->error[1] = dither->error[0]/2;
625 output = sample + bias;
627 /* Dither, highpass triangle PDF */
628 random = dither->random*0x0019660dL + 0x3c6ef35fL;
629 output += (random & mask) - (dither->random & mask);
630 dither->random = random;
632 /* Round sample to output range */
633 output &= ~mask;
635 /* Error feedback */
636 dither->error[0] = sample - output;
638 /* Clip */
639 if ((uint32_t)(output - min) > (uint32_t)range)
641 int32_t c = min;
642 if (output > min)
643 c += range;
644 output = c;
647 /* Quantize and store */
648 *d = output >> scale;
652 if (data->num_channels == 2)
653 return;
655 /* Have to duplicate left samples into the right channel since
656 pcm buffer and hardware is interleaved stereo */
657 d = &dst[0];
659 while (count-- > 0)
661 int16_t s = *d++;
662 *d++ = s;
667 * sample_output_new_format()
669 * set the from-native to ouput sample conversion routine
671 * !DSPPARAMSYNC
672 * needs syncing with changes to the following dsp parameters:
673 * * dsp->stereo_mode (A/V)
674 * * dither_enabled (A)
676 static void sample_output_new_format(struct dsp_config *dsp)
678 static const sample_output_fn_type sample_output_functions[] =
680 sample_output_mono,
681 sample_output_stereo,
682 sample_output_dithered,
683 sample_output_dithered
686 int out = dsp->data.num_channels - 1;
688 if (dsp == &AUDIO_DSP && dither_enabled)
689 out += 2;
691 dsp->output_samples = sample_output_functions[out];
695 * Linear interpolation resampling that introduces a one sample delay because
696 * of our inability to look into the future at the end of a frame.
698 #ifndef DSP_HAVE_ASM_RESAMPLING
699 static int dsp_downsample(int count, struct dsp_data *data,
700 const int32_t *src[], int32_t *dst[])
702 int ch = data->num_channels - 1;
703 uint32_t delta = data->resample_data.delta;
704 uint32_t phase, pos;
705 int32_t *d;
707 /* Rolled channel loop actually showed slightly faster. */
710 /* Just initialize things and not worry too much about the relatively
711 * uncommon case of not being able to spit out a sample for the frame.
713 const int32_t *s = src[ch];
714 int32_t last = data->resample_data.last_sample[ch];
716 data->resample_data.last_sample[ch] = s[count - 1];
717 d = dst[ch];
718 phase = data->resample_data.phase;
719 pos = phase >> 16;
721 /* Do we need last sample of previous frame for interpolation? */
722 if (pos > 0)
723 last = s[pos - 1];
725 while (pos < (uint32_t)count)
727 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
728 phase += delta;
729 pos = phase >> 16;
730 last = s[pos - 1];
733 while (--ch >= 0);
735 /* Wrap phase accumulator back to start of next frame. */
736 data->resample_data.phase = phase - (count << 16);
737 return d - dst[0];
740 static int dsp_upsample(int count, struct dsp_data *data,
741 const int32_t *src[], int32_t *dst[])
743 int ch = data->num_channels - 1;
744 uint32_t delta = data->resample_data.delta;
745 uint32_t phase, pos;
746 int32_t *d;
748 /* Rolled channel loop actually showed slightly faster. */
751 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
752 const int32_t *s = src[ch];
753 int32_t last = data->resample_data.last_sample[ch];
755 data->resample_data.last_sample[ch] = s[count - 1];
756 d = dst[ch];
757 phase = data->resample_data.phase;
758 pos = phase >> 16;
760 while (pos == 0)
762 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
763 phase += delta;
764 pos = phase >> 16;
767 while (pos < (uint32_t)count)
769 last = s[pos - 1];
770 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
771 phase += delta;
772 pos = phase >> 16;
775 while (--ch >= 0);
777 /* Wrap phase accumulator back to start of next frame. */
778 data->resample_data.phase = phase & 0xffff;
779 return d - dst[0];
781 #endif /* DSP_HAVE_ASM_RESAMPLING */
783 static void resampler_new_delta(struct dsp_config *dsp)
785 dsp->data.resample_data.delta = (unsigned long)
786 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
788 if (dsp->frequency == NATIVE_FREQUENCY)
790 /* NOTE: If fully glitch-free transistions from no resampling to
791 resampling are desired, last_sample history should be maintained
792 even when not resampling. */
793 dsp->resample = NULL;
794 dsp->data.resample_data.phase = 0;
795 dsp->data.resample_data.last_sample[0] = 0;
796 dsp->data.resample_data.last_sample[1] = 0;
798 else if (dsp->frequency < NATIVE_FREQUENCY)
799 dsp->resample = dsp_upsample;
800 else
801 dsp->resample = dsp_downsample;
804 /* Resample count stereo samples. Updates the src array, if resampling is
805 * done, to refer to the resampled data. Returns number of stereo samples
806 * for further processing.
808 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
810 int32_t *dst[2] =
812 resample_buf[0],
813 resample_buf[1]
815 lock_sample_buf( true );
816 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
818 src[0] = dst[0];
819 src[1] = dst[dsp->data.num_channels - 1];
820 lock_sample_buf( false );
821 return count;
824 static void dither_init(struct dsp_config *dsp)
826 memset(dither_data, 0, sizeof (dither_data));
827 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
828 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
831 void dsp_dither_enable(bool enable)
833 struct dsp_config *dsp = &AUDIO_DSP;
834 dither_enabled = enable;
835 sample_output_new_format(dsp);
838 /* Applies crossfeed to the stereo signal in src.
839 * Crossfeed is a process where listening over speakers is simulated. This
840 * is good for old hard panned stereo records, which might be quite fatiguing
841 * to listen to on headphones with no crossfeed.
843 #ifndef DSP_HAVE_ASM_CROSSFEED
844 static void apply_crossfeed(int count, int32_t *buf[])
846 int32_t *hist_l = &crossfeed_data.history[0];
847 int32_t *hist_r = &crossfeed_data.history[2];
848 int32_t *delay = &crossfeed_data.delay[0][0];
849 int32_t *coefs = &crossfeed_data.coefs[0];
850 int32_t gain = crossfeed_data.gain;
851 int32_t *di = crossfeed_data.index;
853 int32_t acc;
854 int32_t left, right;
855 int i;
857 for (i = 0; i < count; i++)
859 left = buf[0][i];
860 right = buf[1][i];
862 /* Filter delayed sample from left speaker */
863 acc = FRACMUL(*di, coefs[0]);
864 acc += FRACMUL(hist_l[0], coefs[1]);
865 acc += FRACMUL(hist_l[1], coefs[2]);
866 /* Save filter history for left speaker */
867 hist_l[1] = acc;
868 hist_l[0] = *di;
869 *di++ = left;
870 /* Filter delayed sample from right speaker */
871 acc = FRACMUL(*di, coefs[0]);
872 acc += FRACMUL(hist_r[0], coefs[1]);
873 acc += FRACMUL(hist_r[1], coefs[2]);
874 /* Save filter history for right speaker */
875 hist_r[1] = acc;
876 hist_r[0] = *di;
877 *di++ = right;
878 /* Now add the attenuated direct sound and write to outputs */
879 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
880 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
882 /* Wrap delay line index if bigger than delay line size */
883 if (di >= delay + 13*2)
884 di = delay;
886 /* Write back local copies of data we've modified */
887 crossfeed_data.index = di;
889 #endif /* DSP_HAVE_ASM_CROSSFEED */
892 * dsp_set_crossfeed(bool enable)
894 * !DSPPARAMSYNC
895 * needs syncing with changes to the following dsp parameters:
896 * * dsp->stereo_mode (A)
898 void dsp_set_crossfeed(bool enable)
900 crossfeed_enabled = enable;
901 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
902 ? apply_crossfeed : NULL;
905 void dsp_set_crossfeed_direct_gain(int gain)
907 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
908 /* If gain is negative, the calculation overflowed and we need to clamp */
909 if (crossfeed_data.gain < 0)
910 crossfeed_data.gain = 0x7fffffff;
913 /* Both gains should be below 0 dB */
914 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
916 int32_t *c = crossfeed_data.coefs;
917 long scaler = get_replaygain_int(lf_gain * 10) << 7;
919 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
920 hf_gain -= lf_gain;
921 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
922 * point instead of shelf midpoint. This is for compatibility with the old
923 * crossfeed shelf filter and should be removed if crossfeed settings are
924 * ever made incompatible for any other good reason.
926 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
927 filter_shelf_coefs(cutoff, hf_gain, false, c);
928 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
929 * over 1 and can do this safely
931 c[0] = FRACMUL_SHL(c[0], scaler, 4);
932 c[1] = FRACMUL_SHL(c[1], scaler, 4);
933 c[2] <<= 4;
936 /* Apply a constant gain to the samples (e.g., for ReplayGain).
937 * Note that this must be called before the resampler.
939 #ifndef DSP_HAVE_ASM_APPLY_GAIN
940 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
942 const int32_t gain = data->gain;
943 int ch;
945 for (ch = 0; ch < data->num_channels; ch++)
947 int32_t *d = buf[ch];
948 int i;
950 for (i = 0; i < count; i++)
951 d[i] = FRACMUL_SHL(d[i], gain, 8);
954 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
956 /* Combine all gains to a global gain. */
957 static void set_gain(struct dsp_config *dsp)
959 /* gains are in S7.24 format */
960 dsp->data.gain = DEFAULT_GAIN;
962 /* Replay gain not relevant to voice */
963 if (dsp == &AUDIO_DSP && replaygain)
965 dsp->data.gain = replaygain;
968 if (dsp->eq_process && eq_precut)
970 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
973 #ifdef HAVE_SW_VOLUME_CONTROL
974 if (global_settings.volume < SW_VOLUME_MAX ||
975 global_settings.volume > SW_VOLUME_MIN)
977 int vol_gain = get_replaygain_int(global_settings.volume * 100);
978 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
980 #endif
982 if (dsp->data.gain == DEFAULT_GAIN)
984 dsp->data.gain = 0;
986 else
988 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
991 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
995 * Update the amount to cut the audio before applying the equalizer.
997 * @param precut to apply in decibels (multiplied by 10)
999 void dsp_set_eq_precut(int precut)
1001 eq_precut = get_replaygain_int(precut * -10);
1002 set_gain(&AUDIO_DSP);
1006 * Synchronize the equalizer filter coefficients with the global settings.
1008 * @param band the equalizer band to synchronize
1010 void dsp_set_eq_coefs(int band)
1012 const int *setting;
1013 long gain;
1014 unsigned long cutoff, q;
1016 /* Adjust setting pointer to the band we actually want to change */
1017 setting = &global_settings.eq_band0_cutoff + (band * 3);
1019 /* Convert user settings to format required by coef generator functions */
1020 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
1021 q = *setting++;
1022 gain = *setting++;
1024 if (q == 0)
1025 q = 1;
1027 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
1028 which it should be, since we're executed from the main thread. */
1030 /* Assume a band is disabled if the gain is zero */
1031 if (gain == 0)
1033 eq_data.enabled[band] = 0;
1035 else
1037 if (band == 0)
1038 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1039 else if (band == 4)
1040 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1041 else
1042 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1044 eq_data.enabled[band] = 1;
1048 /* Apply EQ filters to those bands that have got it switched on. */
1049 static void eq_process(int count, int32_t *buf[])
1051 static const int shifts[] =
1053 EQ_SHELF_SHIFT, /* low shelf */
1054 EQ_PEAK_SHIFT, /* peaking */
1055 EQ_PEAK_SHIFT, /* peaking */
1056 EQ_PEAK_SHIFT, /* peaking */
1057 EQ_SHELF_SHIFT, /* high shelf */
1059 unsigned int channels = AUDIO_DSP.data.num_channels;
1060 int i;
1062 /* filter configuration currently is 1 low shelf filter, 3 band peaking
1063 filters and 1 high shelf filter, in that order. we need to know this
1064 so we can choose the correct shift factor.
1066 for (i = 0; i < 5; i++)
1068 if (!eq_data.enabled[i])
1069 continue;
1070 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1075 * Use to enable the equalizer.
1077 * @param enable true to enable the equalizer
1079 void dsp_set_eq(bool enable)
1081 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1082 set_gain(&AUDIO_DSP);
1085 static void dsp_set_stereo_width(int value)
1087 long width, straight, cross;
1089 width = value * 0x7fffff / 100;
1091 if (value <= 100)
1093 straight = (0x7fffff + width) / 2;
1094 cross = straight - width;
1096 else
1098 /* straight = (1 + width) / (2 * width) */
1099 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1100 cross = straight - 0x7fffff;
1103 dsp_sw_gain = straight << 8;
1104 dsp_sw_cross = cross << 8;
1108 * Implements the different channel configurations and stereo width.
1111 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1112 * completeness. */
1113 #if 0
1114 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1116 /* The channels are each just themselves */
1117 (void)count; (void)buf;
1119 #endif
1121 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1122 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1124 int32_t *sl = buf[0], *sr = buf[1];
1126 while (count-- > 0)
1128 int32_t lr = *sl/2 + *sr/2;
1129 *sl++ = lr;
1130 *sr++ = lr;
1133 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1135 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1136 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1138 const int32_t gain = dsp_sw_gain;
1139 const int32_t cross = dsp_sw_cross;
1140 int32_t *sl = buf[0], *sr = buf[1];
1142 while (count-- > 0)
1144 int32_t l = *sl;
1145 int32_t r = *sr;
1146 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1147 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1150 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1152 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1154 /* Just copy over the other channel */
1155 memcpy(buf[1], buf[0], count * sizeof (*buf));
1158 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1160 /* Just copy over the other channel */
1161 memcpy(buf[0], buf[1], count * sizeof (*buf));
1164 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1165 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1167 int32_t *sl = buf[0], *sr = buf[1];
1169 while (count-- > 0)
1171 int32_t ch = *sl/2 - *sr/2;
1172 *sl++ = ch;
1173 *sr++ = -ch;
1176 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1178 static void dsp_set_channel_config(int value)
1180 static const channels_process_fn_type channels_process_functions[] =
1182 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1183 [SOUND_CHAN_STEREO] = NULL,
1184 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1185 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1186 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1187 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1188 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1191 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1192 AUDIO_DSP.stereo_mode == STEREO_MONO)
1194 value = SOUND_CHAN_STEREO;
1197 /* This doesn't apply to voice */
1198 channels_mode = value;
1199 AUDIO_DSP.channels_process = channels_process_functions[value];
1202 #if CONFIG_CODEC == SWCODEC
1204 #ifdef HAVE_SW_TONE_CONTROLS
1205 static void set_tone_controls(void)
1207 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1208 0xffffffff/NATIVE_FREQUENCY*3500,
1209 bass, treble, -prescale,
1210 AUDIO_DSP.tone_filter.coefs);
1211 /* Sync the voice dsp coefficients */
1212 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1213 sizeof (VOICE_DSP.tone_filter.coefs));
1215 #endif
1217 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1218 * code directly.
1220 int dsp_callback(int msg, intptr_t param)
1222 switch (msg)
1224 #ifdef HAVE_SW_TONE_CONTROLS
1225 case DSP_CALLBACK_SET_PRESCALE:
1226 prescale = param;
1227 set_tone_controls();
1228 break;
1229 /* prescaler is always set after calling any of these, so we wait with
1230 * calculating coefs until the above case is hit.
1232 case DSP_CALLBACK_SET_BASS:
1233 bass = param;
1234 break;
1235 case DSP_CALLBACK_SET_TREBLE:
1236 treble = param;
1237 break;
1238 #ifdef HAVE_SW_VOLUME_CONTROL
1239 case DSP_CALLBACK_SET_SW_VOLUME:
1240 set_gain(&AUDIO_DSP);
1241 break;
1242 #endif
1243 #endif
1244 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1245 dsp_set_channel_config(param);
1246 break;
1247 case DSP_CALLBACK_SET_STEREO_WIDTH:
1248 dsp_set_stereo_width(param);
1249 break;
1250 default:
1251 break;
1253 return 0;
1255 #endif
1257 /* Process and convert src audio to dst based on the DSP configuration,
1258 * reading count number of audio samples. dst is assumed to be large
1259 * enough; use dsp_output_count() to get the required number. src is an
1260 * array of pointers; for mono and interleaved stereo, it contains one
1261 * pointer to the start of the audio data and the other is ignored; for
1262 * non-interleaved stereo, it contains two pointers, one for each audio
1263 * channel. Returns number of bytes written to dst.
1265 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1267 static int32_t *tmp[2]; /* tdspeed_doit() needs it static */
1268 static long last_yield;
1269 long tick;
1270 int written = 0;
1272 #if defined(CPU_COLDFIRE)
1273 /* set emac unit for dsp processing, and save old macsr, we're running in
1274 codec thread context at this point, so can't clobber it */
1275 unsigned long old_macsr = coldfire_get_macsr();
1276 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1277 #endif
1279 if (new_gain)
1280 dsp_set_replaygain(); /* Gain has changed */
1282 /* Perform at least one yield before starting */
1283 last_yield = current_tick;
1284 yield();
1286 /* Testing function pointers for NULL is preferred since the pointer
1287 will be preloaded to be used for the call if not. */
1288 while (count > 0)
1290 int samples = MIN(sample_buf_count, count);
1291 count -= samples;
1293 dsp->input_samples(samples, src, tmp);
1295 #ifdef HAVE_PITCHSCREEN
1296 if (dsp->tdspeed_active)
1297 samples = tdspeed_doit(tmp, samples);
1298 #endif
1300 int chunk_offset = 0;
1301 while (samples > 0)
1303 int32_t *t2[2];
1304 t2[0] = tmp[0]+chunk_offset;
1305 t2[1] = tmp[1]+chunk_offset;
1307 int chunk = MIN(sample_buf_count, samples);
1308 chunk_offset += chunk;
1309 samples -= chunk;
1311 if (dsp->apply_gain)
1312 dsp->apply_gain(chunk, &dsp->data, t2);
1314 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1315 break; /* I'm pretty sure we're downsampling here */
1317 if (dsp->apply_crossfeed)
1318 dsp->apply_crossfeed(chunk, t2);
1320 if (dsp->eq_process)
1321 dsp->eq_process(chunk, t2);
1323 #ifdef HAVE_SW_TONE_CONTROLS
1324 if ((bass | treble) != 0)
1325 eq_filter(t2, &dsp->tone_filter, chunk,
1326 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1327 #endif
1329 if (dsp->channels_process)
1330 dsp->channels_process(chunk, t2);
1332 if (dsp->compressor_process)
1333 dsp->compressor_process(chunk, t2);
1335 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1337 written += chunk;
1338 dst += chunk * sizeof (int16_t) * 2;
1340 /* yield at least once each tick */
1341 tick = current_tick;
1342 if (TIME_AFTER(tick, last_yield))
1344 last_yield = tick;
1345 yield();
1350 #if defined(CPU_COLDFIRE)
1351 /* set old macsr again */
1352 coldfire_set_macsr(old_macsr);
1353 #endif
1354 return written;
1357 /* Given count number of input samples, calculate the maximum number of
1358 * samples of output data that would be generated (the calculation is not
1359 * entirely exact and rounds upwards to be on the safe side; during
1360 * resampling, the number of samples generated depends on the current state
1361 * of the resampler).
1363 /* dsp_input_size MUST be called afterwards */
1364 int dsp_output_count(struct dsp_config *dsp, int count)
1366 #ifdef HAVE_PITCHSCREEN
1367 if (dsp->tdspeed_active)
1368 count = tdspeed_est_output_size();
1369 #endif
1370 if (dsp->resample)
1372 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1373 + (dsp->frequency - 1)) / dsp->frequency);
1376 /* Now we have the resampled sample count which must not exceed
1377 * resample_buf_count to avoid resample buffer overflow. One
1378 * must call dsp_input_count() to get the correct input sample
1379 * count.
1381 if (count > resample_buf_count)
1382 count = resample_buf_count;
1384 return count;
1387 /* Given count output samples, calculate number of input samples
1388 * that would be consumed in order to fill the output buffer.
1390 int dsp_input_count(struct dsp_config *dsp, int count)
1392 /* count is now the number of resampled input samples. Convert to
1393 original input samples. */
1394 if (dsp->resample)
1396 /* Use the real resampling delta =
1397 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1398 * round towards zero to avoid buffer overflows. */
1399 count = (int)(((unsigned long)count *
1400 dsp->data.resample_data.delta) >> 16);
1403 #ifdef HAVE_PITCHSCREEN
1404 if (dsp->tdspeed_active)
1405 count = tdspeed_est_input_size(count);
1406 #endif
1408 return count;
1411 static void dsp_set_gain_var(long *var, long value)
1413 *var = value;
1414 new_gain = true;
1417 static void dsp_update_functions(struct dsp_config *dsp)
1419 sample_input_new_format(dsp);
1420 sample_output_new_format(dsp);
1421 if (dsp == &AUDIO_DSP)
1422 dsp_set_crossfeed(crossfeed_enabled);
1425 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1427 switch (setting)
1429 case DSP_MYDSP:
1430 switch (value)
1432 case CODEC_IDX_AUDIO:
1433 return (intptr_t)&AUDIO_DSP;
1434 case CODEC_IDX_VOICE:
1435 return (intptr_t)&VOICE_DSP;
1436 default:
1437 return (intptr_t)NULL;
1440 case DSP_SET_FREQUENCY:
1441 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1442 /* Fall through!!! */
1443 case DSP_SWITCH_FREQUENCY:
1444 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1445 /* Account for playback speed adjustment when setting dsp->frequency
1446 if we're called from the main audio thread. Voice UI thread should
1447 not need this feature.
1449 #ifdef HAVE_PITCHSCREEN
1450 if (dsp == &AUDIO_DSP)
1451 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1452 else
1453 #endif
1454 dsp->frequency = dsp->codec_frequency;
1456 resampler_new_delta(dsp);
1457 #ifdef HAVE_PITCHSCREEN
1458 tdspeed_setup(dsp);
1459 #endif
1460 break;
1462 case DSP_SET_SAMPLE_DEPTH:
1463 dsp->sample_depth = value;
1465 if (dsp->sample_depth <= NATIVE_DEPTH)
1467 dsp->frac_bits = WORD_FRACBITS;
1468 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1469 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1470 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1472 else
1474 dsp->frac_bits = value;
1475 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1476 dsp->data.clip_max = (1 << value) - 1;
1477 dsp->data.clip_min = -(1 << value);
1480 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1481 sample_input_new_format(dsp);
1482 dither_init(dsp);
1483 break;
1485 case DSP_SET_STEREO_MODE:
1486 dsp->stereo_mode = value;
1487 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1488 dsp_update_functions(dsp);
1489 #ifdef HAVE_PITCHSCREEN
1490 tdspeed_setup(dsp);
1491 #endif
1492 break;
1494 case DSP_RESET:
1495 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1496 dsp->data.num_channels = 2;
1497 dsp->sample_depth = NATIVE_DEPTH;
1498 dsp->frac_bits = WORD_FRACBITS;
1499 dsp->sample_bytes = sizeof (int16_t);
1500 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1501 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1502 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1503 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1505 if (dsp == &AUDIO_DSP)
1507 track_gain = 0;
1508 album_gain = 0;
1509 track_peak = 0;
1510 album_peak = 0;
1511 new_gain = true;
1514 dsp_update_functions(dsp);
1515 resampler_new_delta(dsp);
1516 #ifdef HAVE_PITCHSCREEN
1517 tdspeed_setup(dsp);
1518 #endif
1519 if (dsp == &AUDIO_DSP)
1520 release_gain = UNITY;
1521 break;
1523 case DSP_FLUSH:
1524 memset(&dsp->data.resample_data, 0,
1525 sizeof (dsp->data.resample_data));
1526 resampler_new_delta(dsp);
1527 dither_init(dsp);
1528 #ifdef HAVE_PITCHSCREEN
1529 tdspeed_setup(dsp);
1530 #endif
1531 if (dsp == &AUDIO_DSP)
1532 release_gain = UNITY;
1533 break;
1535 case DSP_SET_TRACK_GAIN:
1536 if (dsp == &AUDIO_DSP)
1537 dsp_set_gain_var(&track_gain, value);
1538 break;
1540 case DSP_SET_ALBUM_GAIN:
1541 if (dsp == &AUDIO_DSP)
1542 dsp_set_gain_var(&album_gain, value);
1543 break;
1545 case DSP_SET_TRACK_PEAK:
1546 if (dsp == &AUDIO_DSP)
1547 dsp_set_gain_var(&track_peak, value);
1548 break;
1550 case DSP_SET_ALBUM_PEAK:
1551 if (dsp == &AUDIO_DSP)
1552 dsp_set_gain_var(&album_peak, value);
1553 break;
1555 default:
1556 return 0;
1559 return 1;
1562 int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
1564 int type;
1566 bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
1567 || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1568 && global_settings.playlist_shuffle));
1570 type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
1571 : have_track_gain ? REPLAYGAIN_TRACK : -1;
1573 return type;
1576 void dsp_set_replaygain(void)
1578 long gain = 0;
1580 new_gain = false;
1582 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1583 global_settings.replaygain_noclip)
1585 bool track_mode = get_replaygain_mode(track_gain != 0,
1586 album_gain != 0) == REPLAYGAIN_TRACK;
1587 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1589 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1591 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1593 if (global_settings.replaygain_preamp)
1595 long preamp = get_replaygain_int(
1596 global_settings.replaygain_preamp * 10);
1598 gain = (long) (((int64_t) gain * preamp) >> 24);
1602 if (gain == 0)
1604 /* So that noclip can work even with no gain information. */
1605 gain = DEFAULT_GAIN;
1608 if (global_settings.replaygain_noclip && (peak != 0)
1609 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1611 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1614 if (gain == DEFAULT_GAIN)
1616 /* Nothing to do, disable processing. */
1617 gain = 0;
1621 /* Store in S7.24 format to simplify calculations. */
1622 replaygain = gain;
1623 set_gain(&AUDIO_DSP);
1626 /** SET COMPRESSOR
1627 * Called by the menu system to configure the compressor process */
1628 void dsp_set_compressor(void)
1630 static int curr_set[5];
1631 int new_set[5] = {
1632 global_settings.compressor_threshold,
1633 global_settings.compressor_makeup_gain,
1634 global_settings.compressor_ratio,
1635 global_settings.compressor_knee,
1636 global_settings.compressor_release_time};
1638 /* make menu values useful */
1639 int threshold = new_set[0];
1640 bool auto_gain = (new_set[1] == 1);
1641 const int comp_ratios[] = {2, 4, 6, 10, 0};
1642 int ratio = comp_ratios[new_set[2]];
1643 bool soft_knee = (new_set[3] == 1);
1644 int release = new_set[4] * NATIVE_FREQUENCY / 1000;
1646 bool changed = false;
1647 bool active = (threshold < 0);
1649 for (int i = 0; i < 5; i++)
1651 if (curr_set[i] != new_set[i])
1653 changed = true;
1654 curr_set[i] = new_set[i];
1656 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1657 switch (i)
1659 case 0:
1660 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1661 threshold, active ? "Yes" : "No");
1662 break;
1663 case 1:
1664 logf(" Compressor Makeup Gain: %s",
1665 auto_gain ? "Auto" : "Off");
1666 break;
1667 case 2:
1668 if (ratio)
1669 { logf(" Compressor Ratio: %d:1", ratio); }
1670 else
1671 { logf(" Compressor Ratio: Limit"); }
1672 break;
1673 case 3:
1674 logf(" Compressor Knee: %s", soft_knee?"Soft":"Hard");
1675 break;
1676 case 4:
1677 logf(" Compressor Release: %d", release);
1678 break;
1680 #endif
1684 if (changed && active)
1686 /* configure variables for compressor operation */
1687 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1688 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1689 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1690 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1691 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1692 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1693 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1694 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1695 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1697 struct curve_point
1699 int32_t db; /* S15.16 format */
1700 int32_t offset; /* S15.16 format */
1701 } db_curve[5];
1703 /** Set up the shape of the compression curve first as decibel values*/
1704 /* db_curve[0] = bottom of knee
1705 [1] = threshold
1706 [2] = top of knee
1707 [3] = 0 db input
1708 [4] = ~+12db input (2 bits clipping overhead) */
1710 db_curve[1].db = threshold << 16;
1711 if (soft_knee)
1713 /* bottom of knee is 3dB below the threshold for soft knee*/
1714 db_curve[0].db = db_curve[1].db - (3 << 16);
1715 /* top of knee is 3dB above the threshold for soft knee */
1716 db_curve[2].db = db_curve[1].db + (3 << 16);
1717 if (ratio)
1718 /* offset = -3db * (ratio - 1) / ratio */
1719 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1720 * (ratio - 1) / ratio);
1721 else
1722 /* offset = -3db for hard limit */
1723 db_curve[2].offset = (-3 << 16);
1725 else
1727 /* bottom of knee is at the threshold for hard knee */
1728 db_curve[0].db = threshold << 16;
1729 /* top of knee is at the threshold for hard knee */
1730 db_curve[2].db = threshold << 16;
1731 db_curve[2].offset = 0;
1734 /* Calculate 0db and ~+12db offsets */
1735 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1736 if (ratio)
1738 /* offset = threshold * (ratio - 1) / ratio */
1739 db_curve[3].offset = (int32_t)((long long)(threshold << 16)
1740 * (ratio - 1) / ratio);
1741 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1742 * (ratio - 1) / ratio) + db_curve[3].offset;
1744 else
1746 /* offset = threshold for hard limit */
1747 db_curve[3].offset = (threshold << 16);
1748 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1751 /** Now set up the comp_curve table with compression offsets in the form
1752 of gain factors in S7.24 format */
1753 /* comp_curve[0] is 0 (-infinity db) input */
1754 comp_curve[0] = UNITY;
1755 /* comp_curve[1 to 63] are intermediate compression values corresponding
1756 to the 6 MSB of the input values of a non-clipped signal */
1757 for (int i = 1; i < 64; i++)
1759 /* db constants are stored as positive numbers;
1760 make them negative here */
1761 int32_t this_db = -db[i];
1763 /* no compression below the knee */
1764 if (this_db <= db_curve[0].db)
1765 comp_curve[i] = UNITY;
1767 /* if soft knee and below top of knee,
1768 interpolate along soft knee slope */
1769 else if (soft_knee && (this_db <= db_curve[2].db))
1770 comp_curve[i] = fp_factor(fp_mul(
1771 ((this_db - db_curve[0].db) / 6),
1772 db_curve[2].offset, 16), 16) << 8;
1774 /* interpolate along ratio slope above the knee */
1775 else
1776 comp_curve[i] = fp_factor(fp_mul(
1777 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1778 db_curve[3].offset, 16), 16) << 8;
1780 /* comp_curve[64] is the compression level of a maximum level,
1781 non-clipped signal */
1782 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1784 /* comp_curve[65] is the compression level of a maximum level,
1785 clipped signal */
1786 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1788 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1789 logf("\n *** Compression Offsets ***");
1790 /* some settings for display only, not used in calculations */
1791 db_curve[0].offset = 0;
1792 db_curve[1].offset = 0;
1793 db_curve[3].db = 0;
1795 for (int i = 0; i <= 4; i++)
1797 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1798 (float)db_curve[i].db / (1 << 16),
1799 (float)db_curve[i].offset / (1 << 16));
1802 logf("\nGain factors:");
1803 for (int i = 1; i <= 65; i++)
1805 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1806 if (i % 4 == 0) debugf("\n");
1808 debugf("\n");
1809 #endif
1811 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1812 comp_makeup_gain = auto_gain ?
1813 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1814 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1816 /* calculate per-sample gain change a rate of 10db over release time */
1817 comp_rel_slope = 0xAF0BB2 / release;
1818 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1820 release_gain = UNITY;
1823 /* enable/disable the compressor */
1824 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1827 /** GET COMPRESSION GAIN
1828 * Returns the required gain factor in S7.24 format in order to compress the
1829 * sample in accordance with the compression curve. Always 1 or less.
1831 static inline int32_t get_compression_gain(int32_t sample)
1833 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1835 /* sample must be positive */
1836 if (sample < 0)
1837 sample = -(sample + 1);
1839 /* shift sample into 15 frac bit range */
1840 if (frac_bits_offset > 0)
1841 sample >>= frac_bits_offset;
1842 if (frac_bits_offset < 0)
1843 sample <<= -frac_bits_offset;
1845 /* normal case: sample isn't clipped */
1846 if (sample < (1 << 15))
1848 /* index is 6 MSB, rem is 9 LSB */
1849 int index = sample >> 9;
1850 int32_t rem = (sample & 0x1FF) << 22;
1852 /* interpolate from the compression curve:
1853 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1854 return comp_curve[index] - (FRACMUL(rem,
1855 (comp_curve[index] - comp_curve[index + 1])));
1857 /* sample is somewhat clipped, up to 2 bits of overhead */
1858 if (sample < (1 << 17))
1860 /* straight interpolation:
1861 higher gain - ((clipped portion of sample * 4/3
1862 / (1 << 31)) * (higher gain - lower gain)) */
1863 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1864 (comp_curve[64] - comp_curve[65])));
1867 /* sample is too clipped, return invalid value */
1868 return -1;
1871 /** COMPRESSOR PROCESS
1872 * Changes the gain of the samples according to the compressor curve
1874 static void compressor_process(int count, int32_t *buf[])
1876 const int num_chan = AUDIO_DSP.data.num_channels;
1877 int32_t *in_buf[2] = {buf[0], buf[1]};
1879 while (count-- > 0)
1881 int ch;
1882 /* use lowest (most compressed) gain factor of the output buffer
1883 sample pair for both samples (mono is also handled correctly here) */
1884 int32_t sample_gain = UNITY;
1885 for (ch = 0; ch < num_chan; ch++)
1887 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1888 if (this_gain < sample_gain)
1889 sample_gain = this_gain;
1892 /* perform release slope; skip if no compression and no release slope */
1893 if ((sample_gain != UNITY) || (release_gain != UNITY))
1895 /* if larger offset than previous slope, start new release slope */
1896 if ((sample_gain <= release_gain) && (sample_gain > 0))
1898 release_gain = sample_gain;
1900 else
1901 /* keep sloping towards unity gain (and ignore invalid value) */
1903 release_gain += comp_rel_slope;
1904 if (release_gain > UNITY)
1906 release_gain = UNITY;
1911 /* total gain factor is the product of release gain and makeup gain,
1912 but avoid computation if possible */
1913 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1914 (comp_makeup_gain == UNITY) ? release_gain :
1915 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1917 /* Implement the compressor: apply total gain factor (if any) to the
1918 output buffer sample pair/mono sample */
1919 if (total_gain != UNITY)
1921 for (ch = 0; ch < num_chan; ch++)
1923 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1926 in_buf[0]++;
1927 in_buf[1]++;