GSoC/Buflib: Add buflib memory alocator to the core.
[kugel-rb.git] / apps / dsp.c
bloba728dd75ea2ad23033121505f8ba555011d47fa9
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
22 #include <stdbool.h>
23 #include <inttypes.h>
24 #include <string.h>
25 #include <sound.h>
26 #include "dsp.h"
27 #include "eq.h"
28 #include "kernel.h"
29 #include "system.h"
30 #include "settings.h"
31 #include "replaygain.h"
32 #include "tdspeed.h"
33 #include "core_alloc.h"
34 #include "fixedpoint.h"
35 #include "fracmul.h"
37 /* Define LOGF_ENABLE to enable logf output in this file */
38 /*#define LOGF_ENABLE*/
39 #include "logf.h"
41 /* 16-bit samples are scaled based on these constants. The shift should be
42 * no more than 15.
44 #define WORD_SHIFT 12
45 #define WORD_FRACBITS 27
47 #define NATIVE_DEPTH 16
48 /* If the small buffer size changes, check the assembly code! */
49 #define SMALL_SAMPLE_BUF_COUNT 256
50 #define DEFAULT_GAIN 0x01000000
52 /* enums to index conversion properly with stereo mode and other settings */
53 enum
55 SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED,
56 SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED,
57 SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO,
58 SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES,
59 SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES,
60 SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES,
61 SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES
64 enum
66 SAMPLE_OUTPUT_MONO = 0,
67 SAMPLE_OUTPUT_STEREO,
68 SAMPLE_OUTPUT_DITHERED_MONO,
69 SAMPLE_OUTPUT_DITHERED_STEREO
72 /****************************************************************************
73 * NOTE: Any assembly routines that use these structures must be updated
74 * if current data members are moved or changed.
76 struct resample_data
78 uint32_t delta; /* 00h */
79 uint32_t phase; /* 04h */
80 int32_t last_sample[2]; /* 08h */
81 /* 10h */
84 /* This is for passing needed data to assembly dsp routines. If another
85 * dsp parameter needs to be passed, add to the end of the structure
86 * and remove from dsp_config.
87 * If another function type becomes assembly optimized and requires dsp
88 * config info, add a pointer paramter of type "struct dsp_data *".
89 * If removing something from other than the end, reserve the spot or
90 * else update every implementation for every target.
91 * Be sure to add the offset of the new member for easy viewing as well. :)
92 * It is the first member of dsp_config and all members can be accessesed
93 * through the main aggregate but this is intended to make a safe haven
94 * for these items whereas the c part can be rearranged at will. dsp_data
95 * could even moved within dsp_config without disurbing the order.
97 struct dsp_data
99 int output_scale; /* 00h */
100 int num_channels; /* 04h */
101 struct resample_data resample_data; /* 08h */
102 int32_t clip_min; /* 18h */
103 int32_t clip_max; /* 1ch */
104 int32_t gain; /* 20h - Note that this is in S8.23 format. */
105 /* 24h */
108 /* No asm...yet */
109 struct dither_data
111 long error[3]; /* 00h */
112 long random; /* 0ch */
113 /* 10h */
116 struct crossfeed_data
118 int32_t gain; /* 00h - Direct path gain */
119 int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */
120 int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */
121 int32_t delay[13][2]; /* 20h */
122 int32_t *index; /* 88h - Current pointer into the delay line */
123 /* 8ch */
126 /* Current setup is one lowshelf filters three peaking filters and one
127 * highshelf filter. Varying the number of shelving filters make no sense,
128 * but adding peaking filters is possible.
130 struct eq_state
132 char enabled[5]; /* 00h - Flags for active filters */
133 struct eqfilter filters[5]; /* 08h - packing is 4? */
134 /* 10ch */
137 struct compressor_menu
139 int threshold; /* dB - from menu */
140 bool auto_gain; /* 0 = off, 1 = auto */
141 int ratio; /* from menu */
142 bool soft_knee; /* 0 = hard knee, 1 = soft knee */
143 int release; /* samples - from menu */
146 /* Include header with defines which functions are implemented in assembly
147 code for the target */
148 #include <dsp_asm.h>
150 /* Typedefs keep things much neater in this case */
151 typedef void (*sample_input_fn_type)(int count, const char *src[],
152 int32_t *dst[]);
153 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
154 const int32_t *src[], int32_t *dst[]);
155 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
156 const int32_t *src[], int16_t *dst);
158 /* Single-DSP channel processing in place */
159 typedef void (*channels_process_fn_type)(int count, int32_t *buf[]);
160 /* DSP local channel processing in place */
161 typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data,
162 int32_t *buf[]);
165 ***************************************************************************/
167 struct dsp_config
169 struct dsp_data data; /* Config members for use in asm routines */
170 long codec_frequency; /* Sample rate of data coming from the codec */
171 long frequency; /* Effective sample rate after pitch shift (if any) */
172 int sample_depth;
173 int sample_bytes;
174 int stereo_mode;
175 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
176 #ifdef HAVE_PITCHSCREEN
177 bool tdspeed_active; /* Timestretch is in use */
178 #endif
179 int frac_bits;
180 #ifdef HAVE_SW_TONE_CONTROLS
181 /* Filter struct for software bass/treble controls */
182 struct eqfilter tone_filter;
183 #endif
184 /* Functions that change depending upon settings - NULL if stage is
185 disabled */
186 sample_input_fn_type input_samples;
187 resample_fn_type resample;
188 sample_output_fn_type output_samples;
189 /* These will be NULL for the voice codec and is more economical that
190 way */
191 channels_process_dsp_fn_type apply_gain;
192 channels_process_fn_type apply_crossfeed;
193 channels_process_fn_type eq_process;
194 channels_process_fn_type channels_process;
195 channels_process_fn_type compressor_process;
198 /* General DSP config */
199 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
200 /* Dithering */
201 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
202 static long dither_mask IBSS_ATTR;
203 static long dither_bias IBSS_ATTR;
204 /* Crossfeed */
205 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
207 .index = (int32_t *)crossfeed_data.delay
210 /* Equalizer */
211 static struct eq_state eq_data; /* A */
213 /* Software tone controls */
214 #ifdef HAVE_SW_TONE_CONTROLS
215 static int prescale; /* A/V */
216 static int bass; /* A/V */
217 static int treble; /* A/V */
218 #endif
220 /* Settings applicable to audio codec only */
221 #ifdef HAVE_PITCHSCREEN
222 static int32_t pitch_ratio = PITCH_SPEED_100;
223 #endif
224 static int channels_mode;
225 long dsp_sw_gain;
226 long dsp_sw_cross;
227 static bool dither_enabled;
228 static long eq_precut;
229 static long track_gain;
230 static bool new_gain;
231 static long album_gain;
232 static long track_peak;
233 static long album_peak;
234 static long replaygain;
235 static bool crossfeed_enabled;
237 #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
238 #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
240 /* The internal format is 32-bit samples, non-interleaved, stereo. This
241 * format is similar to the raw output from several codecs, so the amount
242 * of copying needed is minimized for that case.
245 #define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
247 static int32_t small_sample_buf[SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
248 static int32_t small_resample_buf[SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO] IBSS_ATTR;
250 #ifdef HAVE_PITCHSCREEN
251 static int32_t *big_sample_buf = NULL;
252 static int32_t *big_resample_buf = NULL;
253 static int big_sample_buf_count = -1; /* -1=unknown, 0=not available */
254 #endif
256 static int sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
257 static int32_t *sample_buf = small_sample_buf;
258 static int32_t *resample_buf = small_resample_buf;
260 #define SAMPLE_BUF_LEFT_CHANNEL 0
261 #define SAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2)
262 #define RESAMPLE_BUF_LEFT_CHANNEL 0
263 #define RESAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2 * RESAMPLE_RATIO)
265 /* compressor */
266 static struct compressor_menu c_menu;
267 static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
268 static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
269 static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
270 static int32_t release_gain IBSS_ATTR; /* S7.24 format */
271 #define UNITY (1L << 24) /* unity gain in S7.24 format */
272 static void compressor_process(int count, int32_t *buf[]);
275 /* Clip sample to signed 16 bit range */
276 static inline int32_t clip_sample_16(int32_t sample)
278 if ((int16_t)sample != sample)
279 sample = 0x7fff ^ (sample >> 31);
280 return sample;
283 #ifdef HAVE_PITCHSCREEN
284 int32_t sound_get_pitch(void)
286 return pitch_ratio;
289 void sound_set_pitch(int32_t percent)
291 pitch_ratio = percent;
292 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
293 AUDIO_DSP.codec_frequency);
296 static void tdspeed_setup(struct dsp_config *dspc)
298 /* Assume timestretch will not be used */
299 dspc->tdspeed_active = false;
300 sample_buf = small_sample_buf;
301 resample_buf = small_resample_buf;
302 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
304 if(!dsp_timestretch_available())
305 return; /* Timestretch not enabled or buffer not allocated */
306 if (dspc->tdspeed_percent == 0)
307 dspc->tdspeed_percent = PITCH_SPEED_100;
308 if (!tdspeed_config(
309 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
310 dspc->stereo_mode != STEREO_MONO,
311 dspc->tdspeed_percent))
312 return; /* Timestretch not possible or needed with these parameters */
314 /* Timestretch is to be used */
315 dspc->tdspeed_active = true;
316 sample_buf = big_sample_buf;
317 sample_buf_count = big_sample_buf_count;
318 resample_buf = big_resample_buf;
321 void dsp_timestretch_enable(bool enabled)
323 /* Hook to set up timestretch buffer on first call to settings_apply() */
324 if (big_sample_buf_count < 0) /* Only do something on first call */
326 if (enabled)
328 int handle;
329 /* Set up timestretch buffers */
330 big_sample_buf_count = SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO;
331 big_sample_buf = small_resample_buf;
332 handle = core_alloc("resample buf",
333 big_sample_buf_count * RESAMPLE_RATIO * sizeof(int32_t));
334 if (handle > 0)
335 big_resample_buf = core_get_data(handle);
336 else
337 big_sample_buf_count = 0;
339 else
341 /* Not enabled at startup, "big" buffers will never be available */
342 big_sample_buf_count = 0;
344 tdspeed_setup(&AUDIO_DSP);
348 void dsp_set_timestretch(int32_t percent)
350 AUDIO_DSP.tdspeed_percent = percent;
351 tdspeed_setup(&AUDIO_DSP);
354 int32_t dsp_get_timestretch()
356 return AUDIO_DSP.tdspeed_percent;
359 bool dsp_timestretch_available()
361 return (global_settings.timestretch_enabled && big_sample_buf_count > 0);
363 #endif
365 /* Convert count samples to the internal format, if needed. Updates src
366 * to point past the samples "consumed" and dst is set to point to the
367 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
368 * is no point in processing the same data twice.
371 /* convert count 16-bit mono to 32-bit mono */
372 static void sample_input_lte_native_mono(
373 int count, const char *src[], int32_t *dst[])
375 const int16_t *s = (int16_t *) src[0];
376 const int16_t * const send = s + count;
377 int32_t *d = dst[0] = dst[1] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
378 int scale = WORD_SHIFT;
380 while (s < send)
382 *d++ = *s++ << scale;
385 src[0] = (char *)s;
388 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
389 static void sample_input_lte_native_i_stereo(
390 int count, const char *src[], int32_t *dst[])
392 const int32_t *s = (int32_t *) src[0];
393 const int32_t * const send = s + count;
394 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
395 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
396 int scale = WORD_SHIFT;
398 while (s < send)
400 int32_t slr = *s++;
401 #ifdef ROCKBOX_LITTLE_ENDIAN
402 *dl++ = (slr >> 16) << scale;
403 *dr++ = (int32_t)(int16_t)slr << scale;
404 #else /* ROCKBOX_BIG_ENDIAN */
405 *dl++ = (int32_t)(int16_t)slr << scale;
406 *dr++ = (slr >> 16) << scale;
407 #endif
410 src[0] = (char *)s;
413 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
414 static void sample_input_lte_native_ni_stereo(
415 int count, const char *src[], int32_t *dst[])
417 const int16_t *sl = (int16_t *) src[0];
418 const int16_t *sr = (int16_t *) src[1];
419 const int16_t * const slend = sl + count;
420 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
421 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
422 int scale = WORD_SHIFT;
424 while (sl < slend)
426 *dl++ = *sl++ << scale;
427 *dr++ = *sr++ << scale;
430 src[0] = (char *)sl;
431 src[1] = (char *)sr;
434 /* convert count 32-bit mono to 32-bit mono */
435 static void sample_input_gt_native_mono(
436 int count, const char *src[], int32_t *dst[])
438 dst[0] = dst[1] = (int32_t *)src[0];
439 src[0] = (char *)(dst[0] + count);
442 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
443 static void sample_input_gt_native_i_stereo(
444 int count, const char *src[], int32_t *dst[])
446 const int32_t *s = (int32_t *)src[0];
447 const int32_t * const send = s + 2*count;
448 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
449 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
451 while (s < send)
453 *dl++ = *s++;
454 *dr++ = *s++;
457 src[0] = (char *)send;
460 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
461 static void sample_input_gt_native_ni_stereo(
462 int count, const char *src[], int32_t *dst[])
464 dst[0] = (int32_t *)src[0];
465 dst[1] = (int32_t *)src[1];
466 src[0] = (char *)(dst[0] + count);
467 src[1] = (char *)(dst[1] + count);
471 * sample_input_new_format()
473 * set the to-native sample conversion function based on dsp sample parameters
475 * !DSPPARAMSYNC
476 * needs syncing with changes to the following dsp parameters:
477 * * dsp->stereo_mode (A/V)
478 * * dsp->sample_depth (A/V)
480 static void sample_input_new_format(struct dsp_config *dsp)
482 static const sample_input_fn_type sample_input_functions[] =
484 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
485 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
486 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
487 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
488 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
489 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
492 int convert = dsp->stereo_mode;
494 if (dsp->sample_depth > NATIVE_DEPTH)
495 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
497 dsp->input_samples = sample_input_functions[convert];
501 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
502 /* write mono internal format to output format */
503 static void sample_output_mono(int count, struct dsp_data *data,
504 const int32_t *src[], int16_t *dst)
506 const int32_t *s0 = src[0];
507 const int scale = data->output_scale;
508 const int dc_bias = 1 << (scale - 1);
510 while (count-- > 0)
512 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
513 *dst++ = lr;
514 *dst++ = lr;
517 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
519 /* write stereo internal format to output format */
520 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
521 static void sample_output_stereo(int count, struct dsp_data *data,
522 const int32_t *src[], int16_t *dst)
524 const int32_t *s0 = src[0];
525 const int32_t *s1 = src[1];
526 const int scale = data->output_scale;
527 const int dc_bias = 1 << (scale - 1);
529 while (count-- > 0)
531 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
532 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
535 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
538 * The "dither" code to convert the 24-bit samples produced by libmad was
539 * taken from the coolplayer project - coolplayer.sourceforge.net
541 * This function handles mono and stereo outputs.
543 static void sample_output_dithered(int count, struct dsp_data *data,
544 const int32_t *src[], int16_t *dst)
546 const int32_t mask = dither_mask;
547 const int32_t bias = dither_bias;
548 const int scale = data->output_scale;
549 const int32_t min = data->clip_min;
550 const int32_t max = data->clip_max;
551 const int32_t range = max - min;
552 int ch;
553 int16_t *d;
555 for (ch = 0; ch < data->num_channels; ch++)
557 struct dither_data * const dither = &dither_data[ch];
558 const int32_t *s = src[ch];
559 int i;
561 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
563 int32_t output, sample;
564 int32_t random;
566 /* Noise shape and bias (for correct rounding later) */
567 sample = *s;
568 sample += dither->error[0] - dither->error[1] + dither->error[2];
569 dither->error[2] = dither->error[1];
570 dither->error[1] = dither->error[0]/2;
572 output = sample + bias;
574 /* Dither, highpass triangle PDF */
575 random = dither->random*0x0019660dL + 0x3c6ef35fL;
576 output += (random & mask) - (dither->random & mask);
577 dither->random = random;
579 /* Round sample to output range */
580 output &= ~mask;
582 /* Error feedback */
583 dither->error[0] = sample - output;
585 /* Clip */
586 if ((uint32_t)(output - min) > (uint32_t)range)
588 int32_t c = min;
589 if (output > min)
590 c += range;
591 output = c;
594 /* Quantize and store */
595 *d = output >> scale;
599 if (data->num_channels == 2)
600 return;
602 /* Have to duplicate left samples into the right channel since
603 pcm buffer and hardware is interleaved stereo */
604 d = &dst[0];
606 while (count-- > 0)
608 int16_t s = *d++;
609 *d++ = s;
614 * sample_output_new_format()
616 * set the from-native to ouput sample conversion routine
618 * !DSPPARAMSYNC
619 * needs syncing with changes to the following dsp parameters:
620 * * dsp->stereo_mode (A/V)
621 * * dither_enabled (A)
623 static void sample_output_new_format(struct dsp_config *dsp)
625 static const sample_output_fn_type sample_output_functions[] =
627 sample_output_mono,
628 sample_output_stereo,
629 sample_output_dithered,
630 sample_output_dithered
633 int out = dsp->data.num_channels - 1;
635 if (dsp == &AUDIO_DSP && dither_enabled)
636 out += 2;
638 dsp->output_samples = sample_output_functions[out];
642 * Linear interpolation resampling that introduces a one sample delay because
643 * of our inability to look into the future at the end of a frame.
645 #ifndef DSP_HAVE_ASM_RESAMPLING
646 static int dsp_downsample(int count, struct dsp_data *data,
647 const int32_t *src[], int32_t *dst[])
649 int ch = data->num_channels - 1;
650 uint32_t delta = data->resample_data.delta;
651 uint32_t phase, pos;
652 int32_t *d;
654 /* Rolled channel loop actually showed slightly faster. */
657 /* Just initialize things and not worry too much about the relatively
658 * uncommon case of not being able to spit out a sample for the frame.
660 const int32_t *s = src[ch];
661 int32_t last = data->resample_data.last_sample[ch];
663 data->resample_data.last_sample[ch] = s[count - 1];
664 d = dst[ch];
665 phase = data->resample_data.phase;
666 pos = phase >> 16;
668 /* Do we need last sample of previous frame for interpolation? */
669 if (pos > 0)
670 last = s[pos - 1];
672 while (pos < (uint32_t)count)
674 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
675 phase += delta;
676 pos = phase >> 16;
677 last = s[pos - 1];
680 while (--ch >= 0);
682 /* Wrap phase accumulator back to start of next frame. */
683 data->resample_data.phase = phase - (count << 16);
684 return d - dst[0];
687 static int dsp_upsample(int count, struct dsp_data *data,
688 const int32_t *src[], int32_t *dst[])
690 int ch = data->num_channels - 1;
691 uint32_t delta = data->resample_data.delta;
692 uint32_t phase, pos;
693 int32_t *d;
695 /* Rolled channel loop actually showed slightly faster. */
698 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
699 const int32_t *s = src[ch];
700 int32_t last = data->resample_data.last_sample[ch];
702 data->resample_data.last_sample[ch] = s[count - 1];
703 d = dst[ch];
704 phase = data->resample_data.phase;
705 pos = phase >> 16;
707 while (pos == 0)
709 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
710 phase += delta;
711 pos = phase >> 16;
714 while (pos < (uint32_t)count)
716 last = s[pos - 1];
717 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
718 phase += delta;
719 pos = phase >> 16;
722 while (--ch >= 0);
724 /* Wrap phase accumulator back to start of next frame. */
725 data->resample_data.phase = phase & 0xffff;
726 return d - dst[0];
728 #endif /* DSP_HAVE_ASM_RESAMPLING */
730 static void resampler_new_delta(struct dsp_config *dsp)
732 dsp->data.resample_data.delta = (unsigned long)
733 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
735 if (dsp->frequency == NATIVE_FREQUENCY)
737 /* NOTE: If fully glitch-free transistions from no resampling to
738 resampling are desired, last_sample history should be maintained
739 even when not resampling. */
740 dsp->resample = NULL;
741 dsp->data.resample_data.phase = 0;
742 dsp->data.resample_data.last_sample[0] = 0;
743 dsp->data.resample_data.last_sample[1] = 0;
745 else if (dsp->frequency < NATIVE_FREQUENCY)
746 dsp->resample = dsp_upsample;
747 else
748 dsp->resample = dsp_downsample;
751 /* Resample count stereo samples. Updates the src array, if resampling is
752 * done, to refer to the resampled data. Returns number of stereo samples
753 * for further processing.
755 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
757 int32_t *dst[2] =
759 &resample_buf[RESAMPLE_BUF_LEFT_CHANNEL],
760 &resample_buf[RESAMPLE_BUF_RIGHT_CHANNEL],
763 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
765 src[0] = dst[0];
766 src[1] = dst[dsp->data.num_channels - 1];
768 return count;
771 static void dither_init(struct dsp_config *dsp)
773 memset(dither_data, 0, sizeof (dither_data));
774 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
775 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
778 void dsp_dither_enable(bool enable)
780 struct dsp_config *dsp = &AUDIO_DSP;
781 dither_enabled = enable;
782 sample_output_new_format(dsp);
785 /* Applies crossfeed to the stereo signal in src.
786 * Crossfeed is a process where listening over speakers is simulated. This
787 * is good for old hard panned stereo records, which might be quite fatiguing
788 * to listen to on headphones with no crossfeed.
790 #ifndef DSP_HAVE_ASM_CROSSFEED
791 static void apply_crossfeed(int count, int32_t *buf[])
793 int32_t *hist_l = &crossfeed_data.history[0];
794 int32_t *hist_r = &crossfeed_data.history[2];
795 int32_t *delay = &crossfeed_data.delay[0][0];
796 int32_t *coefs = &crossfeed_data.coefs[0];
797 int32_t gain = crossfeed_data.gain;
798 int32_t *di = crossfeed_data.index;
800 int32_t acc;
801 int32_t left, right;
802 int i;
804 for (i = 0; i < count; i++)
806 left = buf[0][i];
807 right = buf[1][i];
809 /* Filter delayed sample from left speaker */
810 acc = FRACMUL(*di, coefs[0]);
811 acc += FRACMUL(hist_l[0], coefs[1]);
812 acc += FRACMUL(hist_l[1], coefs[2]);
813 /* Save filter history for left speaker */
814 hist_l[1] = acc;
815 hist_l[0] = *di;
816 *di++ = left;
817 /* Filter delayed sample from right speaker */
818 acc = FRACMUL(*di, coefs[0]);
819 acc += FRACMUL(hist_r[0], coefs[1]);
820 acc += FRACMUL(hist_r[1], coefs[2]);
821 /* Save filter history for right speaker */
822 hist_r[1] = acc;
823 hist_r[0] = *di;
824 *di++ = right;
825 /* Now add the attenuated direct sound and write to outputs */
826 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
827 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
829 /* Wrap delay line index if bigger than delay line size */
830 if (di >= delay + 13*2)
831 di = delay;
833 /* Write back local copies of data we've modified */
834 crossfeed_data.index = di;
836 #endif /* DSP_HAVE_ASM_CROSSFEED */
839 * dsp_set_crossfeed(bool enable)
841 * !DSPPARAMSYNC
842 * needs syncing with changes to the following dsp parameters:
843 * * dsp->stereo_mode (A)
845 void dsp_set_crossfeed(bool enable)
847 crossfeed_enabled = enable;
848 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
849 ? apply_crossfeed : NULL;
852 void dsp_set_crossfeed_direct_gain(int gain)
854 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
855 /* If gain is negative, the calculation overflowed and we need to clamp */
856 if (crossfeed_data.gain < 0)
857 crossfeed_data.gain = 0x7fffffff;
860 /* Both gains should be below 0 dB */
861 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
863 int32_t *c = crossfeed_data.coefs;
864 long scaler = get_replaygain_int(lf_gain * 10) << 7;
866 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
867 hf_gain -= lf_gain;
868 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
869 * point instead of shelf midpoint. This is for compatibility with the old
870 * crossfeed shelf filter and should be removed if crossfeed settings are
871 * ever made incompatible for any other good reason.
873 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
874 filter_shelf_coefs(cutoff, hf_gain, false, c);
875 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
876 * over 1 and can do this safely
878 c[0] = FRACMUL_SHL(c[0], scaler, 4);
879 c[1] = FRACMUL_SHL(c[1], scaler, 4);
880 c[2] <<= 4;
883 /* Apply a constant gain to the samples (e.g., for ReplayGain).
884 * Note that this must be called before the resampler.
886 #ifndef DSP_HAVE_ASM_APPLY_GAIN
887 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
889 const int32_t gain = data->gain;
890 int ch;
892 for (ch = 0; ch < data->num_channels; ch++)
894 int32_t *d = buf[ch];
895 int i;
897 for (i = 0; i < count; i++)
898 d[i] = FRACMUL_SHL(d[i], gain, 8);
901 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
903 /* Combine all gains to a global gain. */
904 static void set_gain(struct dsp_config *dsp)
906 /* gains are in S7.24 format */
907 dsp->data.gain = DEFAULT_GAIN;
909 /* Replay gain not relevant to voice */
910 if (dsp == &AUDIO_DSP && replaygain)
912 dsp->data.gain = replaygain;
915 if (dsp->eq_process && eq_precut)
917 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
920 #ifdef HAVE_SW_VOLUME_CONTROL
921 if (global_settings.volume < SW_VOLUME_MAX ||
922 global_settings.volume > SW_VOLUME_MIN)
924 int vol_gain = get_replaygain_int(global_settings.volume * 100);
925 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
927 #endif
929 if (dsp->data.gain == DEFAULT_GAIN)
931 dsp->data.gain = 0;
933 else
935 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
938 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
942 * Update the amount to cut the audio before applying the equalizer.
944 * @param precut to apply in decibels (multiplied by 10)
946 void dsp_set_eq_precut(int precut)
948 eq_precut = get_replaygain_int(precut * -10);
949 set_gain(&AUDIO_DSP);
953 * Synchronize the equalizer filter coefficients with the global settings.
955 * @param band the equalizer band to synchronize
957 void dsp_set_eq_coefs(int band)
959 const int *setting;
960 long gain;
961 unsigned long cutoff, q;
963 /* Adjust setting pointer to the band we actually want to change */
964 setting = &global_settings.eq_band0_cutoff + (band * 3);
966 /* Convert user settings to format required by coef generator functions */
967 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
968 q = *setting++;
969 gain = *setting++;
971 if (q == 0)
972 q = 1;
974 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
975 which it should be, since we're executed from the main thread. */
977 /* Assume a band is disabled if the gain is zero */
978 if (gain == 0)
980 eq_data.enabled[band] = 0;
982 else
984 if (band == 0)
985 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
986 else if (band == 4)
987 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
988 else
989 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
991 eq_data.enabled[band] = 1;
995 /* Apply EQ filters to those bands that have got it switched on. */
996 static void eq_process(int count, int32_t *buf[])
998 static const int shifts[] =
1000 EQ_SHELF_SHIFT, /* low shelf */
1001 EQ_PEAK_SHIFT, /* peaking */
1002 EQ_PEAK_SHIFT, /* peaking */
1003 EQ_PEAK_SHIFT, /* peaking */
1004 EQ_SHELF_SHIFT, /* high shelf */
1006 unsigned int channels = AUDIO_DSP.data.num_channels;
1007 int i;
1009 /* filter configuration currently is 1 low shelf filter, 3 band peaking
1010 filters and 1 high shelf filter, in that order. we need to know this
1011 so we can choose the correct shift factor.
1013 for (i = 0; i < 5; i++)
1015 if (!eq_data.enabled[i])
1016 continue;
1017 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1022 * Use to enable the equalizer.
1024 * @param enable true to enable the equalizer
1026 void dsp_set_eq(bool enable)
1028 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1029 set_gain(&AUDIO_DSP);
1032 static void dsp_set_stereo_width(int value)
1034 long width, straight, cross;
1036 width = value * 0x7fffff / 100;
1038 if (value <= 100)
1040 straight = (0x7fffff + width) / 2;
1041 cross = straight - width;
1043 else
1045 /* straight = (1 + width) / (2 * width) */
1046 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1047 cross = straight - 0x7fffff;
1050 dsp_sw_gain = straight << 8;
1051 dsp_sw_cross = cross << 8;
1055 * Implements the different channel configurations and stereo width.
1058 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1059 * completeness. */
1060 #if 0
1061 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1063 /* The channels are each just themselves */
1064 (void)count; (void)buf;
1066 #endif
1068 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1069 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1071 int32_t *sl = buf[0], *sr = buf[1];
1073 while (count-- > 0)
1075 int32_t lr = *sl/2 + *sr/2;
1076 *sl++ = lr;
1077 *sr++ = lr;
1080 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1082 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1083 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1085 const int32_t gain = dsp_sw_gain;
1086 const int32_t cross = dsp_sw_cross;
1087 int32_t *sl = buf[0], *sr = buf[1];
1089 while (count-- > 0)
1091 int32_t l = *sl;
1092 int32_t r = *sr;
1093 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1094 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1097 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1099 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1101 /* Just copy over the other channel */
1102 memcpy(buf[1], buf[0], count * sizeof (*buf));
1105 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1107 /* Just copy over the other channel */
1108 memcpy(buf[0], buf[1], count * sizeof (*buf));
1111 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1112 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1114 int32_t *sl = buf[0], *sr = buf[1];
1116 while (count-- > 0)
1118 int32_t ch = *sl/2 - *sr/2;
1119 *sl++ = ch;
1120 *sr++ = -ch;
1123 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1125 static void dsp_set_channel_config(int value)
1127 static const channels_process_fn_type channels_process_functions[] =
1129 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1130 [SOUND_CHAN_STEREO] = NULL,
1131 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1132 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1133 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1134 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1135 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1138 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1139 AUDIO_DSP.stereo_mode == STEREO_MONO)
1141 value = SOUND_CHAN_STEREO;
1144 /* This doesn't apply to voice */
1145 channels_mode = value;
1146 AUDIO_DSP.channels_process = channels_process_functions[value];
1149 #if CONFIG_CODEC == SWCODEC
1151 #ifdef HAVE_SW_TONE_CONTROLS
1152 static void set_tone_controls(void)
1154 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1155 0xffffffff/NATIVE_FREQUENCY*3500,
1156 bass, treble, -prescale,
1157 AUDIO_DSP.tone_filter.coefs);
1158 /* Sync the voice dsp coefficients */
1159 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1160 sizeof (VOICE_DSP.tone_filter.coefs));
1162 #endif
1164 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1165 * code directly.
1167 int dsp_callback(int msg, intptr_t param)
1169 switch (msg)
1171 #ifdef HAVE_SW_TONE_CONTROLS
1172 case DSP_CALLBACK_SET_PRESCALE:
1173 prescale = param;
1174 set_tone_controls();
1175 break;
1176 /* prescaler is always set after calling any of these, so we wait with
1177 * calculating coefs until the above case is hit.
1179 case DSP_CALLBACK_SET_BASS:
1180 bass = param;
1181 break;
1182 case DSP_CALLBACK_SET_TREBLE:
1183 treble = param;
1184 break;
1185 #ifdef HAVE_SW_VOLUME_CONTROL
1186 case DSP_CALLBACK_SET_SW_VOLUME:
1187 set_gain(&AUDIO_DSP);
1188 break;
1189 #endif
1190 #endif
1191 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1192 dsp_set_channel_config(param);
1193 break;
1194 case DSP_CALLBACK_SET_STEREO_WIDTH:
1195 dsp_set_stereo_width(param);
1196 break;
1197 default:
1198 break;
1200 return 0;
1202 #endif
1204 /* Process and convert src audio to dst based on the DSP configuration,
1205 * reading count number of audio samples. dst is assumed to be large
1206 * enough; use dsp_output_count() to get the required number. src is an
1207 * array of pointers; for mono and interleaved stereo, it contains one
1208 * pointer to the start of the audio data and the other is ignored; for
1209 * non-interleaved stereo, it contains two pointers, one for each audio
1210 * channel. Returns number of bytes written to dst.
1212 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1214 int32_t *tmp[2];
1215 static long last_yield;
1216 long tick;
1217 int written = 0;
1219 #if defined(CPU_COLDFIRE)
1220 /* set emac unit for dsp processing, and save old macsr, we're running in
1221 codec thread context at this point, so can't clobber it */
1222 unsigned long old_macsr = coldfire_get_macsr();
1223 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1224 #endif
1226 if (new_gain)
1227 dsp_set_replaygain(); /* Gain has changed */
1229 /* Perform at least one yield before starting */
1230 last_yield = current_tick;
1231 yield();
1233 /* Testing function pointers for NULL is preferred since the pointer
1234 will be preloaded to be used for the call if not. */
1235 while (count > 0)
1237 int samples = MIN(sample_buf_count/2, count);
1238 count -= samples;
1240 dsp->input_samples(samples, src, tmp);
1242 #ifdef HAVE_PITCHSCREEN
1243 if (dsp->tdspeed_active)
1244 samples = tdspeed_doit(tmp, samples);
1245 #endif
1247 int chunk_offset = 0;
1248 while (samples > 0)
1250 int32_t *t2[2];
1251 t2[0] = tmp[0]+chunk_offset;
1252 t2[1] = tmp[1]+chunk_offset;
1254 int chunk = MIN(sample_buf_count/2, samples);
1255 chunk_offset += chunk;
1256 samples -= chunk;
1258 if (dsp->apply_gain)
1259 dsp->apply_gain(chunk, &dsp->data, t2);
1261 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1262 break; /* I'm pretty sure we're downsampling here */
1264 if (dsp->apply_crossfeed)
1265 dsp->apply_crossfeed(chunk, t2);
1267 if (dsp->eq_process)
1268 dsp->eq_process(chunk, t2);
1270 #ifdef HAVE_SW_TONE_CONTROLS
1271 if ((bass | treble) != 0)
1272 eq_filter(t2, &dsp->tone_filter, chunk,
1273 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1274 #endif
1276 if (dsp->channels_process)
1277 dsp->channels_process(chunk, t2);
1279 if (dsp->compressor_process)
1280 dsp->compressor_process(chunk, t2);
1282 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1284 written += chunk;
1285 dst += chunk * sizeof (int16_t) * 2;
1287 /* yield at least once each tick */
1288 tick = current_tick;
1289 if (TIME_AFTER(tick, last_yield))
1291 last_yield = tick;
1292 yield();
1297 #if defined(CPU_COLDFIRE)
1298 /* set old macsr again */
1299 coldfire_set_macsr(old_macsr);
1300 #endif
1301 return written;
1304 /* Given count number of input samples, calculate the maximum number of
1305 * samples of output data that would be generated (the calculation is not
1306 * entirely exact and rounds upwards to be on the safe side; during
1307 * resampling, the number of samples generated depends on the current state
1308 * of the resampler).
1310 /* dsp_input_size MUST be called afterwards */
1311 int dsp_output_count(struct dsp_config *dsp, int count)
1313 #ifdef HAVE_PITCHSCREEN
1314 if (dsp->tdspeed_active)
1315 count = tdspeed_est_output_size();
1316 #endif
1317 if (dsp->resample)
1319 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1320 + (dsp->frequency - 1)) / dsp->frequency);
1323 /* Now we have the resampled sample count which must not exceed
1324 * RESAMPLE_BUF_RIGHT_CHANNEL to avoid resample buffer overflow. One
1325 * must call dsp_input_count() to get the correct input sample
1326 * count.
1328 if (count > RESAMPLE_BUF_RIGHT_CHANNEL)
1329 count = RESAMPLE_BUF_RIGHT_CHANNEL;
1331 return count;
1334 /* Given count output samples, calculate number of input samples
1335 * that would be consumed in order to fill the output buffer.
1337 int dsp_input_count(struct dsp_config *dsp, int count)
1339 /* count is now the number of resampled input samples. Convert to
1340 original input samples. */
1341 if (dsp->resample)
1343 /* Use the real resampling delta =
1344 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1345 * round towards zero to avoid buffer overflows. */
1346 count = (int)(((unsigned long)count *
1347 dsp->data.resample_data.delta) >> 16);
1350 #ifdef HAVE_PITCHSCREEN
1351 if (dsp->tdspeed_active)
1352 count = tdspeed_est_input_size(count);
1353 #endif
1355 return count;
1358 static void dsp_set_gain_var(long *var, long value)
1360 *var = value;
1361 new_gain = true;
1364 static void dsp_update_functions(struct dsp_config *dsp)
1366 sample_input_new_format(dsp);
1367 sample_output_new_format(dsp);
1368 if (dsp == &AUDIO_DSP)
1369 dsp_set_crossfeed(crossfeed_enabled);
1372 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1374 switch (setting)
1376 case DSP_MYDSP:
1377 switch (value)
1379 case CODEC_IDX_AUDIO:
1380 return (intptr_t)&AUDIO_DSP;
1381 case CODEC_IDX_VOICE:
1382 return (intptr_t)&VOICE_DSP;
1383 default:
1384 return (intptr_t)NULL;
1387 case DSP_SET_FREQUENCY:
1388 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1389 /* Fall through!!! */
1390 case DSP_SWITCH_FREQUENCY:
1391 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1392 /* Account for playback speed adjustment when setting dsp->frequency
1393 if we're called from the main audio thread. Voice UI thread should
1394 not need this feature.
1396 #ifdef HAVE_PITCHSCREEN
1397 if (dsp == &AUDIO_DSP)
1398 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1399 else
1400 #endif
1401 dsp->frequency = dsp->codec_frequency;
1403 resampler_new_delta(dsp);
1404 #ifdef HAVE_PITCHSCREEN
1405 tdspeed_setup(dsp);
1406 #endif
1407 break;
1409 case DSP_SET_SAMPLE_DEPTH:
1410 dsp->sample_depth = value;
1412 if (dsp->sample_depth <= NATIVE_DEPTH)
1414 dsp->frac_bits = WORD_FRACBITS;
1415 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1416 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1417 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1419 else
1421 dsp->frac_bits = value;
1422 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1423 dsp->data.clip_max = (1 << value) - 1;
1424 dsp->data.clip_min = -(1 << value);
1427 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1428 sample_input_new_format(dsp);
1429 dither_init(dsp);
1430 break;
1432 case DSP_SET_STEREO_MODE:
1433 dsp->stereo_mode = value;
1434 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1435 dsp_update_functions(dsp);
1436 #ifdef HAVE_PITCHSCREEN
1437 tdspeed_setup(dsp);
1438 #endif
1439 break;
1441 case DSP_RESET:
1442 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1443 dsp->data.num_channels = 2;
1444 dsp->sample_depth = NATIVE_DEPTH;
1445 dsp->frac_bits = WORD_FRACBITS;
1446 dsp->sample_bytes = sizeof (int16_t);
1447 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1448 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1449 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1450 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1452 if (dsp == &AUDIO_DSP)
1454 track_gain = 0;
1455 album_gain = 0;
1456 track_peak = 0;
1457 album_peak = 0;
1458 new_gain = true;
1461 dsp_update_functions(dsp);
1462 resampler_new_delta(dsp);
1463 #ifdef HAVE_PITCHSCREEN
1464 tdspeed_setup(dsp);
1465 #endif
1466 if (dsp == &AUDIO_DSP)
1467 release_gain = UNITY;
1468 break;
1470 case DSP_FLUSH:
1471 memset(&dsp->data.resample_data, 0,
1472 sizeof (dsp->data.resample_data));
1473 resampler_new_delta(dsp);
1474 dither_init(dsp);
1475 #ifdef HAVE_PITCHSCREEN
1476 tdspeed_setup(dsp);
1477 #endif
1478 if (dsp == &AUDIO_DSP)
1479 release_gain = UNITY;
1480 break;
1482 case DSP_SET_TRACK_GAIN:
1483 if (dsp == &AUDIO_DSP)
1484 dsp_set_gain_var(&track_gain, value);
1485 break;
1487 case DSP_SET_ALBUM_GAIN:
1488 if (dsp == &AUDIO_DSP)
1489 dsp_set_gain_var(&album_gain, value);
1490 break;
1492 case DSP_SET_TRACK_PEAK:
1493 if (dsp == &AUDIO_DSP)
1494 dsp_set_gain_var(&track_peak, value);
1495 break;
1497 case DSP_SET_ALBUM_PEAK:
1498 if (dsp == &AUDIO_DSP)
1499 dsp_set_gain_var(&album_peak, value);
1500 break;
1502 default:
1503 return 0;
1506 return 1;
1509 int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
1511 int type;
1513 bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
1514 || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1515 && global_settings.playlist_shuffle));
1517 type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
1518 : have_track_gain ? REPLAYGAIN_TRACK : -1;
1520 return type;
1523 void dsp_set_replaygain(void)
1525 long gain = 0;
1527 new_gain = false;
1529 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1530 global_settings.replaygain_noclip)
1532 bool track_mode = get_replaygain_mode(track_gain != 0,
1533 album_gain != 0) == REPLAYGAIN_TRACK;
1534 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1536 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1538 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1540 if (global_settings.replaygain_preamp)
1542 long preamp = get_replaygain_int(
1543 global_settings.replaygain_preamp * 10);
1545 gain = (long) (((int64_t) gain * preamp) >> 24);
1549 if (gain == 0)
1551 /* So that noclip can work even with no gain information. */
1552 gain = DEFAULT_GAIN;
1555 if (global_settings.replaygain_noclip && (peak != 0)
1556 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1558 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1561 if (gain == DEFAULT_GAIN)
1563 /* Nothing to do, disable processing. */
1564 gain = 0;
1568 /* Store in S7.24 format to simplify calculations. */
1569 replaygain = gain;
1570 set_gain(&AUDIO_DSP);
1573 /** SET COMPRESSOR
1574 * Called by the menu system to configure the compressor process */
1575 void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
1576 int c_knee, int c_release)
1578 bool changed = false;
1579 bool active = (c_threshold < 0);
1580 bool new_auto_gain = (c_gain == 1);
1581 const int comp_ratio[] = {2, 4, 6, 10, 0};
1582 int new_ratio = comp_ratio[c_ratio];
1583 bool new_knee = (c_knee == 1);
1584 int new_release = c_release * NATIVE_FREQUENCY / 1000;
1586 if (c_menu.threshold != c_threshold)
1588 changed = true;
1589 c_menu.threshold = c_threshold;
1590 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1591 c_menu.threshold, active ? "Yes" : "No");
1594 if (c_menu.auto_gain != new_auto_gain)
1596 changed = true;
1597 c_menu.auto_gain = new_auto_gain;
1598 logf(" Compressor Makeup Gain: %s",
1599 c_menu.auto_gain ? "Auto" : "Off");
1602 if (c_menu.ratio != new_ratio)
1604 changed = true;
1605 c_menu.ratio = new_ratio;
1606 if (c_menu.ratio)
1607 { logf(" Compressor Ratio: %d:1", c_menu.ratio); }
1608 else
1609 { logf(" Compressor Ratio: Limit"); }
1612 if (c_menu.soft_knee != new_knee)
1614 changed = true;
1615 c_menu.soft_knee = new_knee;
1616 logf(" Compressor Knee: %s", c_menu.soft_knee==1?"Soft":"Hard");
1619 if (c_menu.release != new_release)
1621 changed = true;
1622 c_menu.release = new_release;
1623 logf(" Compressor Release: %d", c_menu.release);
1626 if (changed && active)
1628 /* configure variables for compressor operation */
1629 int i;
1630 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1631 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1632 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1633 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1634 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1635 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1636 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1637 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1638 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1640 struct curve_point
1642 int32_t db; /* S15.16 format */
1643 int32_t offset; /* S15.16 format */
1644 } db_curve[5];
1646 /** Set up the shape of the compression curve first as decibel values*/
1647 /* db_curve[0] = bottom of knee
1648 [1] = threshold
1649 [2] = top of knee
1650 [3] = 0 db input
1651 [4] = ~+12db input (2 bits clipping overhead) */
1653 db_curve[1].db = c_menu.threshold << 16;
1654 if (c_menu.soft_knee)
1656 /* bottom of knee is 3dB below the threshold for soft knee*/
1657 db_curve[0].db = db_curve[1].db - (3 << 16);
1658 /* top of knee is 3dB above the threshold for soft knee */
1659 db_curve[2].db = db_curve[1].db + (3 << 16);
1660 if (c_menu.ratio)
1661 /* offset = -3db * (ratio - 1) / ratio */
1662 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1663 * (c_menu.ratio - 1) / c_menu.ratio);
1664 else
1665 /* offset = -3db for hard limit */
1666 db_curve[2].offset = (-3 << 16);
1668 else
1670 /* bottom of knee is at the threshold for hard knee */
1671 db_curve[0].db = c_menu.threshold << 16;
1672 /* top of knee is at the threshold for hard knee */
1673 db_curve[2].db = c_menu.threshold << 16;
1674 db_curve[2].offset = 0;
1677 /* Calculate 0db and ~+12db offsets */
1678 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1679 if (c_menu.ratio)
1681 /* offset = threshold * (ratio - 1) / ratio */
1682 db_curve[3].offset = (int32_t)((long long)(c_menu.threshold << 16)
1683 * (c_menu.ratio - 1) / c_menu.ratio);
1684 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1685 * (c_menu.ratio - 1) / c_menu.ratio) + db_curve[3].offset;
1687 else
1689 /* offset = threshold for hard limit */
1690 db_curve[3].offset = (c_menu.threshold << 16);
1691 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1694 /** Now set up the comp_curve table with compression offsets in the form
1695 of gain factors in S7.24 format */
1696 /* comp_curve[0] is 0 (-infinity db) input */
1697 comp_curve[0] = UNITY;
1698 /* comp_curve[1 to 63] are intermediate compression values corresponding
1699 to the 6 MSB of the input values of a non-clipped signal */
1700 for (i = 1; i < 64; i++)
1702 /* db constants are stored as positive numbers;
1703 make them negative here */
1704 int32_t this_db = -db[i];
1706 /* no compression below the knee */
1707 if (this_db <= db_curve[0].db)
1708 comp_curve[i] = UNITY;
1710 /* if soft knee and below top of knee,
1711 interpolate along soft knee slope */
1712 else if (c_menu.soft_knee && (this_db <= db_curve[2].db))
1713 comp_curve[i] = fp_factor(fp_mul(
1714 ((this_db - db_curve[0].db) / 6),
1715 db_curve[2].offset, 16), 16) << 8;
1717 /* interpolate along ratio slope above the knee */
1718 else
1719 comp_curve[i] = fp_factor(fp_mul(
1720 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1721 db_curve[3].offset, 16), 16) << 8;
1723 /* comp_curve[64] is the compression level of a maximum level,
1724 non-clipped signal */
1725 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1727 /* comp_curve[65] is the compression level of a maximum level,
1728 clipped signal */
1729 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1731 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1732 logf("\n *** Compression Offsets ***");
1733 /* some settings for display only, not used in calculations */
1734 db_curve[0].offset = 0;
1735 db_curve[1].offset = 0;
1736 db_curve[3].db = 0;
1738 for (i = 0; i <= 4; i++)
1740 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1741 (float)db_curve[i].db / (1 << 16),
1742 (float)db_curve[i].offset / (1 << 16));
1745 logf("\nGain factors:");
1746 for (i = 1; i <= 65; i++)
1748 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1749 if (i % 4 == 0) debugf("\n");
1751 debugf("\n");
1752 #endif
1754 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1755 comp_makeup_gain = c_menu.auto_gain ?
1756 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1757 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1759 /* calculate per-sample gain change a rate of 10db over release time */
1760 comp_rel_slope = 0xAF0BB2 / c_menu.release;
1761 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1763 release_gain = UNITY;
1766 /* enable/disable the compressor */
1767 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1770 /** GET COMPRESSION GAIN
1771 * Returns the required gain factor in S7.24 format in order to compress the
1772 * sample in accordance with the compression curve. Always 1 or less.
1774 static inline int32_t get_compression_gain(int32_t sample)
1776 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1778 /* sample must be positive */
1779 if (sample < 0)
1780 sample = -(sample + 1);
1782 /* shift sample into 15 frac bit range */
1783 if (frac_bits_offset > 0)
1784 sample >>= frac_bits_offset;
1785 if (frac_bits_offset < 0)
1786 sample <<= -frac_bits_offset;
1788 /* normal case: sample isn't clipped */
1789 if (sample < (1 << 15))
1791 /* index is 6 MSB, rem is 9 LSB */
1792 int index = sample >> 9;
1793 int32_t rem = (sample & 0x1FF) << 22;
1795 /* interpolate from the compression curve:
1796 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1797 return comp_curve[index] - (FRACMUL(rem,
1798 (comp_curve[index] - comp_curve[index + 1])));
1800 /* sample is somewhat clipped, up to 2 bits of overhead */
1801 if (sample < (1 << 17))
1803 /* straight interpolation:
1804 higher gain - ((clipped portion of sample * 4/3
1805 / (1 << 31)) * (higher gain - lower gain)) */
1806 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1807 (comp_curve[64] - comp_curve[65])));
1810 /* sample is too clipped, return invalid value */
1811 return -1;
1814 /** COMPRESSOR PROCESS
1815 * Changes the gain of the samples according to the compressor curve
1817 static void compressor_process(int count, int32_t *buf[])
1819 const int num_chan = AUDIO_DSP.data.num_channels;
1820 int32_t *in_buf[2] = {buf[0], buf[1]};
1822 while (count-- > 0)
1824 int ch;
1825 /* use lowest (most compressed) gain factor of the output buffer
1826 sample pair for both samples (mono is also handled correctly here) */
1827 int32_t sample_gain = UNITY;
1828 for (ch = 0; ch < num_chan; ch++)
1830 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1831 if (this_gain < sample_gain)
1832 sample_gain = this_gain;
1835 /* perform release slope; skip if no compression and no release slope */
1836 if ((sample_gain != UNITY) || (release_gain != UNITY))
1838 /* if larger offset than previous slope, start new release slope */
1839 if ((sample_gain <= release_gain) && (sample_gain > 0))
1841 release_gain = sample_gain;
1843 else
1844 /* keep sloping towards unity gain (and ignore invalid value) */
1846 release_gain += comp_rel_slope;
1847 if (release_gain > UNITY)
1849 release_gain = UNITY;
1854 /* total gain factor is the product of release gain and makeup gain,
1855 but avoid computation if possible */
1856 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1857 (comp_makeup_gain == UNITY) ? release_gain :
1858 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1860 /* Implement the compressor: apply total gain factor (if any) to the
1861 output buffer sample pair/mono sample */
1862 if (total_gain != UNITY)
1864 for (ch = 0; ch < num_chan; ch++)
1866 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1869 in_buf[0]++;
1870 in_buf[1]++;