New tag %ss() which lets you get a substring of another tag.
[maemo-rb.git] / apps / dsp.c
blob3f1eb75200d9379f0cb1eced6d0b077bf151d7da
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 #define SMALL_SAMPLE_BUF_COUNT 128 /* Per channel */
49 #define DEFAULT_GAIN 0x01000000
51 /* enums to index conversion properly with stereo mode and other settings */
52 enum
54 SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED,
55 SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED,
56 SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO,
57 SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES,
58 SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES,
59 SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES,
60 SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES
63 enum
65 SAMPLE_OUTPUT_MONO = 0,
66 SAMPLE_OUTPUT_STEREO,
67 SAMPLE_OUTPUT_DITHERED_MONO,
68 SAMPLE_OUTPUT_DITHERED_STEREO
71 /****************************************************************************
72 * NOTE: Any assembly routines that use these structures must be updated
73 * if current data members are moved or changed.
75 struct resample_data
77 uint32_t delta; /* 00h */
78 uint32_t phase; /* 04h */
79 int32_t last_sample[2]; /* 08h */
80 /* 10h */
83 /* This is for passing needed data to assembly dsp routines. If another
84 * dsp parameter needs to be passed, add to the end of the structure
85 * and remove from dsp_config.
86 * If another function type becomes assembly optimized and requires dsp
87 * config info, add a pointer paramter of type "struct dsp_data *".
88 * If removing something from other than the end, reserve the spot or
89 * else update every implementation for every target.
90 * Be sure to add the offset of the new member for easy viewing as well. :)
91 * It is the first member of dsp_config and all members can be accessesed
92 * through the main aggregate but this is intended to make a safe haven
93 * for these items whereas the c part can be rearranged at will. dsp_data
94 * could even moved within dsp_config without disurbing the order.
96 struct dsp_data
98 int output_scale; /* 00h */
99 int num_channels; /* 04h */
100 struct resample_data resample_data; /* 08h */
101 int32_t clip_min; /* 18h */
102 int32_t clip_max; /* 1ch */
103 int32_t gain; /* 20h - Note that this is in S8.23 format. */
104 /* 24h */
107 /* No asm...yet */
108 struct dither_data
110 long error[3]; /* 00h */
111 long random; /* 0ch */
112 /* 10h */
115 struct crossfeed_data
117 int32_t gain; /* 00h - Direct path gain */
118 int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */
119 int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */
120 int32_t delay[13][2]; /* 20h */
121 int32_t *index; /* 88h - Current pointer into the delay line */
122 /* 8ch */
125 /* Current setup is one lowshelf filters three peaking filters and one
126 * highshelf filter. Varying the number of shelving filters make no sense,
127 * but adding peaking filters is possible.
129 struct eq_state
131 char enabled[5]; /* 00h - Flags for active filters */
132 struct eqfilter filters[5]; /* 08h - packing is 4? */
133 /* 10ch */
136 struct compressor_menu
138 int threshold; /* dB - from menu */
139 bool auto_gain; /* 0 = off, 1 = auto */
140 int ratio; /* from menu */
141 bool soft_knee; /* 0 = hard knee, 1 = soft knee */
142 int release; /* samples - from menu */
145 /* Include header with defines which functions are implemented in assembly
146 code for the target */
147 #include <dsp_asm.h>
149 /* Typedefs keep things much neater in this case */
150 typedef void (*sample_input_fn_type)(int count, const char *src[],
151 int32_t *dst[]);
152 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
153 const int32_t *src[], int32_t *dst[]);
154 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
155 const int32_t *src[], int16_t *dst);
157 /* Single-DSP channel processing in place */
158 typedef void (*channels_process_fn_type)(int count, int32_t *buf[]);
159 /* DSP local channel processing in place */
160 typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data,
161 int32_t *buf[]);
164 ***************************************************************************/
166 struct dsp_config
168 struct dsp_data data; /* Config members for use in asm routines */
169 long codec_frequency; /* Sample rate of data coming from the codec */
170 long frequency; /* Effective sample rate after pitch shift (if any) */
171 int sample_depth;
172 int sample_bytes;
173 int stereo_mode;
174 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
175 #ifdef HAVE_PITCHSCREEN
176 bool tdspeed_active; /* Timestretch is in use */
177 #endif
178 int frac_bits;
179 #ifdef HAVE_SW_TONE_CONTROLS
180 /* Filter struct for software bass/treble controls */
181 struct eqfilter tone_filter;
182 #endif
183 /* Functions that change depending upon settings - NULL if stage is
184 disabled */
185 sample_input_fn_type input_samples;
186 resample_fn_type resample;
187 sample_output_fn_type output_samples;
188 /* These will be NULL for the voice codec and is more economical that
189 way */
190 channels_process_dsp_fn_type apply_gain;
191 channels_process_fn_type apply_crossfeed;
192 channels_process_fn_type eq_process;
193 channels_process_fn_type channels_process;
194 channels_process_fn_type compressor_process;
197 /* General DSP config */
198 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
199 /* Dithering */
200 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
201 static long dither_mask IBSS_ATTR;
202 static long dither_bias IBSS_ATTR;
203 /* Crossfeed */
204 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
206 .index = (int32_t *)crossfeed_data.delay
209 /* Equalizer */
210 static struct eq_state eq_data; /* A */
212 /* Software tone controls */
213 #ifdef HAVE_SW_TONE_CONTROLS
214 static int prescale; /* A/V */
215 static int bass; /* A/V */
216 static int treble; /* A/V */
217 #endif
219 /* Settings applicable to audio codec only */
220 #ifdef HAVE_PITCHSCREEN
221 static int32_t pitch_ratio = PITCH_SPEED_100;
222 #endif
223 static int channels_mode;
224 long dsp_sw_gain;
225 long dsp_sw_cross;
226 static bool dither_enabled;
227 static long eq_precut;
228 static long track_gain;
229 static bool new_gain;
230 static long album_gain;
231 static long track_peak;
232 static long album_peak;
233 static long replaygain;
234 static bool crossfeed_enabled;
236 #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
237 #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
239 /* The internal format is 32-bit samples, non-interleaved, stereo. This
240 * format is similar to the raw output from several codecs, so the amount
241 * of copying needed is minimized for that case.
244 #define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
245 #define SMALL_RESAMPLE_BUF_COUNT (SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO)
246 #define BIG_SAMPLE_BUF_COUNT SMALL_RESAMPLE_BUF_COUNT
247 #define BIG_RESAMPLE_BUF_COUNT (BIG_SAMPLE_BUF_COUNT * RESAMPLE_RATIO)
249 static int32_t small_sample_buf[2][SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
250 static int32_t small_resample_buf[2][SMALL_RESAMPLE_BUF_COUNT] IBSS_ATTR;
252 #ifdef HAVE_PITCHSCREEN
253 static int32_t (* big_sample_buf)[BIG_SAMPLE_BUF_COUNT] = NULL;
254 static int32_t (* big_resample_buf)[BIG_RESAMPLE_BUF_COUNT] = NULL;
255 #endif
257 static int sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
258 static int32_t *sample_buf[2] = { small_sample_buf[0], small_sample_buf[1] };
259 static int resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
260 static int32_t *resample_buf[2] = { small_resample_buf[0], small_resample_buf[1] };
262 /* compressor */
263 static struct compressor_menu c_menu;
264 static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
265 static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
266 static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
267 static int32_t release_gain IBSS_ATTR; /* S7.24 format */
268 #define UNITY (1L << 24) /* unity gain in S7.24 format */
269 static void compressor_process(int count, int32_t *buf[]);
272 /* Clip sample to signed 16 bit range */
273 static inline int32_t clip_sample_16(int32_t sample)
275 if ((int16_t)sample != sample)
276 sample = 0x7fff ^ (sample >> 31);
277 return sample;
280 #ifdef HAVE_PITCHSCREEN
281 int32_t sound_get_pitch(void)
283 return pitch_ratio;
286 void sound_set_pitch(int32_t percent)
288 pitch_ratio = percent;
289 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
290 AUDIO_DSP.codec_frequency);
293 static void tdspeed_setup(struct dsp_config *dspc)
295 /* Assume timestretch will not be used */
296 dspc->tdspeed_active = false;
297 sample_buf[0] = small_sample_buf[0];
298 sample_buf[1] = small_sample_buf[1];
299 resample_buf[0] = small_resample_buf[0];
300 resample_buf[1] = small_resample_buf[1];
301 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
302 resample_buf_count = SMALL_RESAMPLE_BUF_COUNT;
304 if (!dsp_timestretch_available())
305 return; /* Timestretch not enabled or buffer not allocated */
307 if (dspc->tdspeed_percent == 0)
308 dspc->tdspeed_percent = PITCH_SPEED_100;
310 if (!tdspeed_config(
311 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
312 dspc->stereo_mode != STEREO_MONO,
313 dspc->tdspeed_percent))
314 return; /* Timestretch not possible or needed with these parameters */
316 /* Timestretch is to be used */
317 dspc->tdspeed_active = true;
318 sample_buf[0] = big_sample_buf[0];
319 sample_buf[1] = big_sample_buf[1];
320 resample_buf[0] = big_resample_buf[0];
321 resample_buf[1] = big_resample_buf[1];
322 sample_buf_count = BIG_SAMPLE_BUF_COUNT;
323 resample_buf_count = BIG_RESAMPLE_BUF_COUNT;
327 static int move_callback(int handle, void* current, void* new)
329 /* TODO */
330 (void)handle;(void)current;;
331 big_sample_buf = new;
332 return BUFLIB_CB_OK;
335 static struct buflib_callbacks ops = {
336 .move_callback = move_callback,
337 .shrink_callback = NULL,
341 void dsp_timestretch_enable(bool enabled)
343 /* Hook to set up timestretch buffer on first call to settings_apply() */
344 static int handle;
346 if (enabled)
348 if (big_sample_buf)
349 return; /* already allocated and enabled */
351 /* Set up timestretch buffers */
352 big_sample_buf = &small_resample_buf[0];
354 handle = core_alloc_ex("resample buf",
355 2 * BIG_RESAMPLE_BUF_COUNT * sizeof(int32_t),
356 &ops);
358 enabled = handle > 0;
360 if (enabled)
362 /* success, now setup tdspeed */
363 big_resample_buf = core_get_data(handle);
365 tdspeed_init();
366 tdspeed_setup(&AUDIO_DSP);
370 if (!enabled)
372 dsp_set_timestretch(PITCH_SPEED_100);
373 tdspeed_finish();
375 if (handle > 0)
376 core_free(handle);
378 handle = 0;
379 big_sample_buf = NULL;
383 void dsp_set_timestretch(int32_t percent)
385 AUDIO_DSP.tdspeed_percent = percent;
386 tdspeed_setup(&AUDIO_DSP);
389 int32_t dsp_get_timestretch()
391 return AUDIO_DSP.tdspeed_percent;
394 bool dsp_timestretch_available()
396 return (global_settings.timestretch_enabled && big_sample_buf);
398 #endif /* HAVE_PITCHSCREEN */
400 /* Convert count samples to the internal format, if needed. Updates src
401 * to point past the samples "consumed" and dst is set to point to the
402 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
403 * is no point in processing the same data twice.
406 /* convert count 16-bit mono to 32-bit mono */
407 static void sample_input_lte_native_mono(
408 int count, const char *src[], int32_t *dst[])
410 const int16_t *s = (int16_t *) src[0];
411 const int16_t * const send = s + count;
412 int32_t *d = dst[0] = dst[1] = sample_buf[0];
413 int scale = WORD_SHIFT;
415 while (s < send)
417 *d++ = *s++ << scale;
420 src[0] = (char *)s;
423 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
424 static void sample_input_lte_native_i_stereo(
425 int count, const char *src[], int32_t *dst[])
427 const int32_t *s = (int32_t *) src[0];
428 const int32_t * const send = s + count;
429 int32_t *dl = dst[0] = sample_buf[0];
430 int32_t *dr = dst[1] = sample_buf[1];
431 int scale = WORD_SHIFT;
433 while (s < send)
435 int32_t slr = *s++;
436 #ifdef ROCKBOX_LITTLE_ENDIAN
437 *dl++ = (slr >> 16) << scale;
438 *dr++ = (int32_t)(int16_t)slr << scale;
439 #else /* ROCKBOX_BIG_ENDIAN */
440 *dl++ = (int32_t)(int16_t)slr << scale;
441 *dr++ = (slr >> 16) << scale;
442 #endif
445 src[0] = (char *)s;
448 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
449 static void sample_input_lte_native_ni_stereo(
450 int count, const char *src[], int32_t *dst[])
452 const int16_t *sl = (int16_t *) src[0];
453 const int16_t *sr = (int16_t *) src[1];
454 const int16_t * const slend = sl + count;
455 int32_t *dl = dst[0] = sample_buf[0];
456 int32_t *dr = dst[1] = sample_buf[1];
457 int scale = WORD_SHIFT;
459 while (sl < slend)
461 *dl++ = *sl++ << scale;
462 *dr++ = *sr++ << scale;
465 src[0] = (char *)sl;
466 src[1] = (char *)sr;
469 /* convert count 32-bit mono to 32-bit mono */
470 static void sample_input_gt_native_mono(
471 int count, const char *src[], int32_t *dst[])
473 dst[0] = dst[1] = (int32_t *)src[0];
474 src[0] = (char *)(dst[0] + count);
477 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
478 static void sample_input_gt_native_i_stereo(
479 int count, const char *src[], int32_t *dst[])
481 const int32_t *s = (int32_t *)src[0];
482 const int32_t * const send = s + 2*count;
483 int32_t *dl = dst[0] = sample_buf[0];
484 int32_t *dr = dst[1] = sample_buf[1];
486 while (s < send)
488 *dl++ = *s++;
489 *dr++ = *s++;
492 src[0] = (char *)send;
495 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
496 static void sample_input_gt_native_ni_stereo(
497 int count, const char *src[], int32_t *dst[])
499 dst[0] = (int32_t *)src[0];
500 dst[1] = (int32_t *)src[1];
501 src[0] = (char *)(dst[0] + count);
502 src[1] = (char *)(dst[1] + count);
506 * sample_input_new_format()
508 * set the to-native sample conversion function based on dsp sample parameters
510 * !DSPPARAMSYNC
511 * needs syncing with changes to the following dsp parameters:
512 * * dsp->stereo_mode (A/V)
513 * * dsp->sample_depth (A/V)
515 static void sample_input_new_format(struct dsp_config *dsp)
517 static const sample_input_fn_type sample_input_functions[] =
519 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
520 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
521 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
522 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
523 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
524 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
527 int convert = dsp->stereo_mode;
529 if (dsp->sample_depth > NATIVE_DEPTH)
530 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
532 dsp->input_samples = sample_input_functions[convert];
536 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
537 /* write mono internal format to output format */
538 static void sample_output_mono(int count, struct dsp_data *data,
539 const int32_t *src[], int16_t *dst)
541 const int32_t *s0 = src[0];
542 const int scale = data->output_scale;
543 const int dc_bias = 1 << (scale - 1);
545 while (count-- > 0)
547 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
548 *dst++ = lr;
549 *dst++ = lr;
552 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
554 /* write stereo internal format to output format */
555 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
556 static void sample_output_stereo(int count, struct dsp_data *data,
557 const int32_t *src[], int16_t *dst)
559 const int32_t *s0 = src[0];
560 const int32_t *s1 = src[1];
561 const int scale = data->output_scale;
562 const int dc_bias = 1 << (scale - 1);
564 while (count-- > 0)
566 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
567 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
570 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
573 * The "dither" code to convert the 24-bit samples produced by libmad was
574 * taken from the coolplayer project - coolplayer.sourceforge.net
576 * This function handles mono and stereo outputs.
578 static void sample_output_dithered(int count, struct dsp_data *data,
579 const int32_t *src[], int16_t *dst)
581 const int32_t mask = dither_mask;
582 const int32_t bias = dither_bias;
583 const int scale = data->output_scale;
584 const int32_t min = data->clip_min;
585 const int32_t max = data->clip_max;
586 const int32_t range = max - min;
587 int ch;
588 int16_t *d;
590 for (ch = 0; ch < data->num_channels; ch++)
592 struct dither_data * const dither = &dither_data[ch];
593 const int32_t *s = src[ch];
594 int i;
596 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
598 int32_t output, sample;
599 int32_t random;
601 /* Noise shape and bias (for correct rounding later) */
602 sample = *s;
603 sample += dither->error[0] - dither->error[1] + dither->error[2];
604 dither->error[2] = dither->error[1];
605 dither->error[1] = dither->error[0]/2;
607 output = sample + bias;
609 /* Dither, highpass triangle PDF */
610 random = dither->random*0x0019660dL + 0x3c6ef35fL;
611 output += (random & mask) - (dither->random & mask);
612 dither->random = random;
614 /* Round sample to output range */
615 output &= ~mask;
617 /* Error feedback */
618 dither->error[0] = sample - output;
620 /* Clip */
621 if ((uint32_t)(output - min) > (uint32_t)range)
623 int32_t c = min;
624 if (output > min)
625 c += range;
626 output = c;
629 /* Quantize and store */
630 *d = output >> scale;
634 if (data->num_channels == 2)
635 return;
637 /* Have to duplicate left samples into the right channel since
638 pcm buffer and hardware is interleaved stereo */
639 d = &dst[0];
641 while (count-- > 0)
643 int16_t s = *d++;
644 *d++ = s;
649 * sample_output_new_format()
651 * set the from-native to ouput sample conversion routine
653 * !DSPPARAMSYNC
654 * needs syncing with changes to the following dsp parameters:
655 * * dsp->stereo_mode (A/V)
656 * * dither_enabled (A)
658 static void sample_output_new_format(struct dsp_config *dsp)
660 static const sample_output_fn_type sample_output_functions[] =
662 sample_output_mono,
663 sample_output_stereo,
664 sample_output_dithered,
665 sample_output_dithered
668 int out = dsp->data.num_channels - 1;
670 if (dsp == &AUDIO_DSP && dither_enabled)
671 out += 2;
673 dsp->output_samples = sample_output_functions[out];
677 * Linear interpolation resampling that introduces a one sample delay because
678 * of our inability to look into the future at the end of a frame.
680 #ifndef DSP_HAVE_ASM_RESAMPLING
681 static int dsp_downsample(int count, struct dsp_data *data,
682 const int32_t *src[], int32_t *dst[])
684 int ch = data->num_channels - 1;
685 uint32_t delta = data->resample_data.delta;
686 uint32_t phase, pos;
687 int32_t *d;
689 /* Rolled channel loop actually showed slightly faster. */
692 /* Just initialize things and not worry too much about the relatively
693 * uncommon case of not being able to spit out a sample for the frame.
695 const int32_t *s = src[ch];
696 int32_t last = data->resample_data.last_sample[ch];
698 data->resample_data.last_sample[ch] = s[count - 1];
699 d = dst[ch];
700 phase = data->resample_data.phase;
701 pos = phase >> 16;
703 /* Do we need last sample of previous frame for interpolation? */
704 if (pos > 0)
705 last = s[pos - 1];
707 while (pos < (uint32_t)count)
709 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
710 phase += delta;
711 pos = phase >> 16;
712 last = s[pos - 1];
715 while (--ch >= 0);
717 /* Wrap phase accumulator back to start of next frame. */
718 data->resample_data.phase = phase - (count << 16);
719 return d - dst[0];
722 static int dsp_upsample(int count, struct dsp_data *data,
723 const int32_t *src[], int32_t *dst[])
725 int ch = data->num_channels - 1;
726 uint32_t delta = data->resample_data.delta;
727 uint32_t phase, pos;
728 int32_t *d;
730 /* Rolled channel loop actually showed slightly faster. */
733 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
734 const int32_t *s = src[ch];
735 int32_t last = data->resample_data.last_sample[ch];
737 data->resample_data.last_sample[ch] = s[count - 1];
738 d = dst[ch];
739 phase = data->resample_data.phase;
740 pos = phase >> 16;
742 while (pos == 0)
744 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
745 phase += delta;
746 pos = phase >> 16;
749 while (pos < (uint32_t)count)
751 last = s[pos - 1];
752 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
753 phase += delta;
754 pos = phase >> 16;
757 while (--ch >= 0);
759 /* Wrap phase accumulator back to start of next frame. */
760 data->resample_data.phase = phase & 0xffff;
761 return d - dst[0];
763 #endif /* DSP_HAVE_ASM_RESAMPLING */
765 static void resampler_new_delta(struct dsp_config *dsp)
767 dsp->data.resample_data.delta = (unsigned long)
768 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
770 if (dsp->frequency == NATIVE_FREQUENCY)
772 /* NOTE: If fully glitch-free transistions from no resampling to
773 resampling are desired, last_sample history should be maintained
774 even when not resampling. */
775 dsp->resample = NULL;
776 dsp->data.resample_data.phase = 0;
777 dsp->data.resample_data.last_sample[0] = 0;
778 dsp->data.resample_data.last_sample[1] = 0;
780 else if (dsp->frequency < NATIVE_FREQUENCY)
781 dsp->resample = dsp_upsample;
782 else
783 dsp->resample = dsp_downsample;
786 /* Resample count stereo samples. Updates the src array, if resampling is
787 * done, to refer to the resampled data. Returns number of stereo samples
788 * for further processing.
790 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
792 int32_t *dst[2] =
794 resample_buf[0],
795 resample_buf[1]
798 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
800 src[0] = dst[0];
801 src[1] = dst[dsp->data.num_channels - 1];
803 return count;
806 static void dither_init(struct dsp_config *dsp)
808 memset(dither_data, 0, sizeof (dither_data));
809 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
810 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
813 void dsp_dither_enable(bool enable)
815 struct dsp_config *dsp = &AUDIO_DSP;
816 dither_enabled = enable;
817 sample_output_new_format(dsp);
820 /* Applies crossfeed to the stereo signal in src.
821 * Crossfeed is a process where listening over speakers is simulated. This
822 * is good for old hard panned stereo records, which might be quite fatiguing
823 * to listen to on headphones with no crossfeed.
825 #ifndef DSP_HAVE_ASM_CROSSFEED
826 static void apply_crossfeed(int count, int32_t *buf[])
828 int32_t *hist_l = &crossfeed_data.history[0];
829 int32_t *hist_r = &crossfeed_data.history[2];
830 int32_t *delay = &crossfeed_data.delay[0][0];
831 int32_t *coefs = &crossfeed_data.coefs[0];
832 int32_t gain = crossfeed_data.gain;
833 int32_t *di = crossfeed_data.index;
835 int32_t acc;
836 int32_t left, right;
837 int i;
839 for (i = 0; i < count; i++)
841 left = buf[0][i];
842 right = buf[1][i];
844 /* Filter delayed sample from left speaker */
845 acc = FRACMUL(*di, coefs[0]);
846 acc += FRACMUL(hist_l[0], coefs[1]);
847 acc += FRACMUL(hist_l[1], coefs[2]);
848 /* Save filter history for left speaker */
849 hist_l[1] = acc;
850 hist_l[0] = *di;
851 *di++ = left;
852 /* Filter delayed sample from right speaker */
853 acc = FRACMUL(*di, coefs[0]);
854 acc += FRACMUL(hist_r[0], coefs[1]);
855 acc += FRACMUL(hist_r[1], coefs[2]);
856 /* Save filter history for right speaker */
857 hist_r[1] = acc;
858 hist_r[0] = *di;
859 *di++ = right;
860 /* Now add the attenuated direct sound and write to outputs */
861 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
862 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
864 /* Wrap delay line index if bigger than delay line size */
865 if (di >= delay + 13*2)
866 di = delay;
868 /* Write back local copies of data we've modified */
869 crossfeed_data.index = di;
871 #endif /* DSP_HAVE_ASM_CROSSFEED */
874 * dsp_set_crossfeed(bool enable)
876 * !DSPPARAMSYNC
877 * needs syncing with changes to the following dsp parameters:
878 * * dsp->stereo_mode (A)
880 void dsp_set_crossfeed(bool enable)
882 crossfeed_enabled = enable;
883 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
884 ? apply_crossfeed : NULL;
887 void dsp_set_crossfeed_direct_gain(int gain)
889 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
890 /* If gain is negative, the calculation overflowed and we need to clamp */
891 if (crossfeed_data.gain < 0)
892 crossfeed_data.gain = 0x7fffffff;
895 /* Both gains should be below 0 dB */
896 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
898 int32_t *c = crossfeed_data.coefs;
899 long scaler = get_replaygain_int(lf_gain * 10) << 7;
901 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
902 hf_gain -= lf_gain;
903 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
904 * point instead of shelf midpoint. This is for compatibility with the old
905 * crossfeed shelf filter and should be removed if crossfeed settings are
906 * ever made incompatible for any other good reason.
908 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
909 filter_shelf_coefs(cutoff, hf_gain, false, c);
910 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
911 * over 1 and can do this safely
913 c[0] = FRACMUL_SHL(c[0], scaler, 4);
914 c[1] = FRACMUL_SHL(c[1], scaler, 4);
915 c[2] <<= 4;
918 /* Apply a constant gain to the samples (e.g., for ReplayGain).
919 * Note that this must be called before the resampler.
921 #ifndef DSP_HAVE_ASM_APPLY_GAIN
922 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
924 const int32_t gain = data->gain;
925 int ch;
927 for (ch = 0; ch < data->num_channels; ch++)
929 int32_t *d = buf[ch];
930 int i;
932 for (i = 0; i < count; i++)
933 d[i] = FRACMUL_SHL(d[i], gain, 8);
936 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
938 /* Combine all gains to a global gain. */
939 static void set_gain(struct dsp_config *dsp)
941 /* gains are in S7.24 format */
942 dsp->data.gain = DEFAULT_GAIN;
944 /* Replay gain not relevant to voice */
945 if (dsp == &AUDIO_DSP && replaygain)
947 dsp->data.gain = replaygain;
950 if (dsp->eq_process && eq_precut)
952 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
955 #ifdef HAVE_SW_VOLUME_CONTROL
956 if (global_settings.volume < SW_VOLUME_MAX ||
957 global_settings.volume > SW_VOLUME_MIN)
959 int vol_gain = get_replaygain_int(global_settings.volume * 100);
960 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
962 #endif
964 if (dsp->data.gain == DEFAULT_GAIN)
966 dsp->data.gain = 0;
968 else
970 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
973 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
977 * Update the amount to cut the audio before applying the equalizer.
979 * @param precut to apply in decibels (multiplied by 10)
981 void dsp_set_eq_precut(int precut)
983 eq_precut = get_replaygain_int(precut * -10);
984 set_gain(&AUDIO_DSP);
988 * Synchronize the equalizer filter coefficients with the global settings.
990 * @param band the equalizer band to synchronize
992 void dsp_set_eq_coefs(int band)
994 const int *setting;
995 long gain;
996 unsigned long cutoff, q;
998 /* Adjust setting pointer to the band we actually want to change */
999 setting = &global_settings.eq_band0_cutoff + (band * 3);
1001 /* Convert user settings to format required by coef generator functions */
1002 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
1003 q = *setting++;
1004 gain = *setting++;
1006 if (q == 0)
1007 q = 1;
1009 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
1010 which it should be, since we're executed from the main thread. */
1012 /* Assume a band is disabled if the gain is zero */
1013 if (gain == 0)
1015 eq_data.enabled[band] = 0;
1017 else
1019 if (band == 0)
1020 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1021 else if (band == 4)
1022 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1023 else
1024 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1026 eq_data.enabled[band] = 1;
1030 /* Apply EQ filters to those bands that have got it switched on. */
1031 static void eq_process(int count, int32_t *buf[])
1033 static const int shifts[] =
1035 EQ_SHELF_SHIFT, /* low shelf */
1036 EQ_PEAK_SHIFT, /* peaking */
1037 EQ_PEAK_SHIFT, /* peaking */
1038 EQ_PEAK_SHIFT, /* peaking */
1039 EQ_SHELF_SHIFT, /* high shelf */
1041 unsigned int channels = AUDIO_DSP.data.num_channels;
1042 int i;
1044 /* filter configuration currently is 1 low shelf filter, 3 band peaking
1045 filters and 1 high shelf filter, in that order. we need to know this
1046 so we can choose the correct shift factor.
1048 for (i = 0; i < 5; i++)
1050 if (!eq_data.enabled[i])
1051 continue;
1052 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1057 * Use to enable the equalizer.
1059 * @param enable true to enable the equalizer
1061 void dsp_set_eq(bool enable)
1063 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1064 set_gain(&AUDIO_DSP);
1067 static void dsp_set_stereo_width(int value)
1069 long width, straight, cross;
1071 width = value * 0x7fffff / 100;
1073 if (value <= 100)
1075 straight = (0x7fffff + width) / 2;
1076 cross = straight - width;
1078 else
1080 /* straight = (1 + width) / (2 * width) */
1081 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1082 cross = straight - 0x7fffff;
1085 dsp_sw_gain = straight << 8;
1086 dsp_sw_cross = cross << 8;
1090 * Implements the different channel configurations and stereo width.
1093 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1094 * completeness. */
1095 #if 0
1096 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1098 /* The channels are each just themselves */
1099 (void)count; (void)buf;
1101 #endif
1103 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1104 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1106 int32_t *sl = buf[0], *sr = buf[1];
1108 while (count-- > 0)
1110 int32_t lr = *sl/2 + *sr/2;
1111 *sl++ = lr;
1112 *sr++ = lr;
1115 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1117 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1118 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1120 const int32_t gain = dsp_sw_gain;
1121 const int32_t cross = dsp_sw_cross;
1122 int32_t *sl = buf[0], *sr = buf[1];
1124 while (count-- > 0)
1126 int32_t l = *sl;
1127 int32_t r = *sr;
1128 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1129 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1132 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1134 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1136 /* Just copy over the other channel */
1137 memcpy(buf[1], buf[0], count * sizeof (*buf));
1140 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1142 /* Just copy over the other channel */
1143 memcpy(buf[0], buf[1], count * sizeof (*buf));
1146 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1147 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1149 int32_t *sl = buf[0], *sr = buf[1];
1151 while (count-- > 0)
1153 int32_t ch = *sl/2 - *sr/2;
1154 *sl++ = ch;
1155 *sr++ = -ch;
1158 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1160 static void dsp_set_channel_config(int value)
1162 static const channels_process_fn_type channels_process_functions[] =
1164 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1165 [SOUND_CHAN_STEREO] = NULL,
1166 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1167 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1168 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1169 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1170 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1173 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1174 AUDIO_DSP.stereo_mode == STEREO_MONO)
1176 value = SOUND_CHAN_STEREO;
1179 /* This doesn't apply to voice */
1180 channels_mode = value;
1181 AUDIO_DSP.channels_process = channels_process_functions[value];
1184 #if CONFIG_CODEC == SWCODEC
1186 #ifdef HAVE_SW_TONE_CONTROLS
1187 static void set_tone_controls(void)
1189 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1190 0xffffffff/NATIVE_FREQUENCY*3500,
1191 bass, treble, -prescale,
1192 AUDIO_DSP.tone_filter.coefs);
1193 /* Sync the voice dsp coefficients */
1194 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1195 sizeof (VOICE_DSP.tone_filter.coefs));
1197 #endif
1199 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1200 * code directly.
1202 int dsp_callback(int msg, intptr_t param)
1204 switch (msg)
1206 #ifdef HAVE_SW_TONE_CONTROLS
1207 case DSP_CALLBACK_SET_PRESCALE:
1208 prescale = param;
1209 set_tone_controls();
1210 break;
1211 /* prescaler is always set after calling any of these, so we wait with
1212 * calculating coefs until the above case is hit.
1214 case DSP_CALLBACK_SET_BASS:
1215 bass = param;
1216 break;
1217 case DSP_CALLBACK_SET_TREBLE:
1218 treble = param;
1219 break;
1220 #ifdef HAVE_SW_VOLUME_CONTROL
1221 case DSP_CALLBACK_SET_SW_VOLUME:
1222 set_gain(&AUDIO_DSP);
1223 break;
1224 #endif
1225 #endif
1226 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1227 dsp_set_channel_config(param);
1228 break;
1229 case DSP_CALLBACK_SET_STEREO_WIDTH:
1230 dsp_set_stereo_width(param);
1231 break;
1232 default:
1233 break;
1235 return 0;
1237 #endif
1239 /* Process and convert src audio to dst based on the DSP configuration,
1240 * reading count number of audio samples. dst is assumed to be large
1241 * enough; use dsp_output_count() to get the required number. src is an
1242 * array of pointers; for mono and interleaved stereo, it contains one
1243 * pointer to the start of the audio data and the other is ignored; for
1244 * non-interleaved stereo, it contains two pointers, one for each audio
1245 * channel. Returns number of bytes written to dst.
1247 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1249 static int32_t *tmp[2]; /* tdspeed_doit() needs it static */
1250 static long last_yield;
1251 long tick;
1252 int written = 0;
1254 #if defined(CPU_COLDFIRE)
1255 /* set emac unit for dsp processing, and save old macsr, we're running in
1256 codec thread context at this point, so can't clobber it */
1257 unsigned long old_macsr = coldfire_get_macsr();
1258 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1259 #endif
1261 if (new_gain)
1262 dsp_set_replaygain(); /* Gain has changed */
1264 /* Perform at least one yield before starting */
1265 last_yield = current_tick;
1266 yield();
1268 /* Testing function pointers for NULL is preferred since the pointer
1269 will be preloaded to be used for the call if not. */
1270 while (count > 0)
1272 int samples = MIN(sample_buf_count, count);
1273 count -= samples;
1275 dsp->input_samples(samples, src, tmp);
1277 #ifdef HAVE_PITCHSCREEN
1278 if (dsp->tdspeed_active)
1279 samples = tdspeed_doit(tmp, samples);
1280 #endif
1282 int chunk_offset = 0;
1283 while (samples > 0)
1285 int32_t *t2[2];
1286 t2[0] = tmp[0]+chunk_offset;
1287 t2[1] = tmp[1]+chunk_offset;
1289 int chunk = MIN(sample_buf_count, samples);
1290 chunk_offset += chunk;
1291 samples -= chunk;
1293 if (dsp->apply_gain)
1294 dsp->apply_gain(chunk, &dsp->data, t2);
1296 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1297 break; /* I'm pretty sure we're downsampling here */
1299 if (dsp->apply_crossfeed)
1300 dsp->apply_crossfeed(chunk, t2);
1302 if (dsp->eq_process)
1303 dsp->eq_process(chunk, t2);
1305 #ifdef HAVE_SW_TONE_CONTROLS
1306 if ((bass | treble) != 0)
1307 eq_filter(t2, &dsp->tone_filter, chunk,
1308 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1309 #endif
1311 if (dsp->channels_process)
1312 dsp->channels_process(chunk, t2);
1314 if (dsp->compressor_process)
1315 dsp->compressor_process(chunk, t2);
1317 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1319 written += chunk;
1320 dst += chunk * sizeof (int16_t) * 2;
1322 /* yield at least once each tick */
1323 tick = current_tick;
1324 if (TIME_AFTER(tick, last_yield))
1326 last_yield = tick;
1327 yield();
1332 #if defined(CPU_COLDFIRE)
1333 /* set old macsr again */
1334 coldfire_set_macsr(old_macsr);
1335 #endif
1336 return written;
1339 /* Given count number of input samples, calculate the maximum number of
1340 * samples of output data that would be generated (the calculation is not
1341 * entirely exact and rounds upwards to be on the safe side; during
1342 * resampling, the number of samples generated depends on the current state
1343 * of the resampler).
1345 /* dsp_input_size MUST be called afterwards */
1346 int dsp_output_count(struct dsp_config *dsp, int count)
1348 #ifdef HAVE_PITCHSCREEN
1349 if (dsp->tdspeed_active)
1350 count = tdspeed_est_output_size();
1351 #endif
1352 if (dsp->resample)
1354 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1355 + (dsp->frequency - 1)) / dsp->frequency);
1358 /* Now we have the resampled sample count which must not exceed
1359 * resample_buf_count to avoid resample buffer overflow. One
1360 * must call dsp_input_count() to get the correct input sample
1361 * count.
1363 if (count > resample_buf_count)
1364 count = resample_buf_count;
1366 return count;
1369 /* Given count output samples, calculate number of input samples
1370 * that would be consumed in order to fill the output buffer.
1372 int dsp_input_count(struct dsp_config *dsp, int count)
1374 /* count is now the number of resampled input samples. Convert to
1375 original input samples. */
1376 if (dsp->resample)
1378 /* Use the real resampling delta =
1379 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1380 * round towards zero to avoid buffer overflows. */
1381 count = (int)(((unsigned long)count *
1382 dsp->data.resample_data.delta) >> 16);
1385 #ifdef HAVE_PITCHSCREEN
1386 if (dsp->tdspeed_active)
1387 count = tdspeed_est_input_size(count);
1388 #endif
1390 return count;
1393 static void dsp_set_gain_var(long *var, long value)
1395 *var = value;
1396 new_gain = true;
1399 static void dsp_update_functions(struct dsp_config *dsp)
1401 sample_input_new_format(dsp);
1402 sample_output_new_format(dsp);
1403 if (dsp == &AUDIO_DSP)
1404 dsp_set_crossfeed(crossfeed_enabled);
1407 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1409 switch (setting)
1411 case DSP_MYDSP:
1412 switch (value)
1414 case CODEC_IDX_AUDIO:
1415 return (intptr_t)&AUDIO_DSP;
1416 case CODEC_IDX_VOICE:
1417 return (intptr_t)&VOICE_DSP;
1418 default:
1419 return (intptr_t)NULL;
1422 case DSP_SET_FREQUENCY:
1423 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1424 /* Fall through!!! */
1425 case DSP_SWITCH_FREQUENCY:
1426 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1427 /* Account for playback speed adjustment when setting dsp->frequency
1428 if we're called from the main audio thread. Voice UI thread should
1429 not need this feature.
1431 #ifdef HAVE_PITCHSCREEN
1432 if (dsp == &AUDIO_DSP)
1433 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1434 else
1435 #endif
1436 dsp->frequency = dsp->codec_frequency;
1438 resampler_new_delta(dsp);
1439 #ifdef HAVE_PITCHSCREEN
1440 tdspeed_setup(dsp);
1441 #endif
1442 break;
1444 case DSP_SET_SAMPLE_DEPTH:
1445 dsp->sample_depth = value;
1447 if (dsp->sample_depth <= NATIVE_DEPTH)
1449 dsp->frac_bits = WORD_FRACBITS;
1450 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1451 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1452 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1454 else
1456 dsp->frac_bits = value;
1457 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1458 dsp->data.clip_max = (1 << value) - 1;
1459 dsp->data.clip_min = -(1 << value);
1462 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1463 sample_input_new_format(dsp);
1464 dither_init(dsp);
1465 break;
1467 case DSP_SET_STEREO_MODE:
1468 dsp->stereo_mode = value;
1469 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1470 dsp_update_functions(dsp);
1471 #ifdef HAVE_PITCHSCREEN
1472 tdspeed_setup(dsp);
1473 #endif
1474 break;
1476 case DSP_RESET:
1477 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1478 dsp->data.num_channels = 2;
1479 dsp->sample_depth = NATIVE_DEPTH;
1480 dsp->frac_bits = WORD_FRACBITS;
1481 dsp->sample_bytes = sizeof (int16_t);
1482 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1483 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1484 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1485 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1487 if (dsp == &AUDIO_DSP)
1489 track_gain = 0;
1490 album_gain = 0;
1491 track_peak = 0;
1492 album_peak = 0;
1493 new_gain = true;
1496 dsp_update_functions(dsp);
1497 resampler_new_delta(dsp);
1498 #ifdef HAVE_PITCHSCREEN
1499 tdspeed_setup(dsp);
1500 #endif
1501 if (dsp == &AUDIO_DSP)
1502 release_gain = UNITY;
1503 break;
1505 case DSP_FLUSH:
1506 memset(&dsp->data.resample_data, 0,
1507 sizeof (dsp->data.resample_data));
1508 resampler_new_delta(dsp);
1509 dither_init(dsp);
1510 #ifdef HAVE_PITCHSCREEN
1511 tdspeed_setup(dsp);
1512 #endif
1513 if (dsp == &AUDIO_DSP)
1514 release_gain = UNITY;
1515 break;
1517 case DSP_SET_TRACK_GAIN:
1518 if (dsp == &AUDIO_DSP)
1519 dsp_set_gain_var(&track_gain, value);
1520 break;
1522 case DSP_SET_ALBUM_GAIN:
1523 if (dsp == &AUDIO_DSP)
1524 dsp_set_gain_var(&album_gain, value);
1525 break;
1527 case DSP_SET_TRACK_PEAK:
1528 if (dsp == &AUDIO_DSP)
1529 dsp_set_gain_var(&track_peak, value);
1530 break;
1532 case DSP_SET_ALBUM_PEAK:
1533 if (dsp == &AUDIO_DSP)
1534 dsp_set_gain_var(&album_peak, value);
1535 break;
1537 default:
1538 return 0;
1541 return 1;
1544 int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
1546 int type;
1548 bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
1549 || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1550 && global_settings.playlist_shuffle));
1552 type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
1553 : have_track_gain ? REPLAYGAIN_TRACK : -1;
1555 return type;
1558 void dsp_set_replaygain(void)
1560 long gain = 0;
1562 new_gain = false;
1564 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1565 global_settings.replaygain_noclip)
1567 bool track_mode = get_replaygain_mode(track_gain != 0,
1568 album_gain != 0) == REPLAYGAIN_TRACK;
1569 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1571 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1573 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1575 if (global_settings.replaygain_preamp)
1577 long preamp = get_replaygain_int(
1578 global_settings.replaygain_preamp * 10);
1580 gain = (long) (((int64_t) gain * preamp) >> 24);
1584 if (gain == 0)
1586 /* So that noclip can work even with no gain information. */
1587 gain = DEFAULT_GAIN;
1590 if (global_settings.replaygain_noclip && (peak != 0)
1591 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1593 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1596 if (gain == DEFAULT_GAIN)
1598 /* Nothing to do, disable processing. */
1599 gain = 0;
1603 /* Store in S7.24 format to simplify calculations. */
1604 replaygain = gain;
1605 set_gain(&AUDIO_DSP);
1608 /** SET COMPRESSOR
1609 * Called by the menu system to configure the compressor process */
1610 void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
1611 int c_knee, int c_release)
1613 bool changed = false;
1614 bool active = (c_threshold < 0);
1615 bool new_auto_gain = (c_gain == 1);
1616 const int comp_ratio[] = {2, 4, 6, 10, 0};
1617 int new_ratio = comp_ratio[c_ratio];
1618 bool new_knee = (c_knee == 1);
1619 int new_release = c_release * NATIVE_FREQUENCY / 1000;
1621 if (c_menu.threshold != c_threshold)
1623 changed = true;
1624 c_menu.threshold = c_threshold;
1625 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1626 c_menu.threshold, active ? "Yes" : "No");
1629 if (c_menu.auto_gain != new_auto_gain)
1631 changed = true;
1632 c_menu.auto_gain = new_auto_gain;
1633 logf(" Compressor Makeup Gain: %s",
1634 c_menu.auto_gain ? "Auto" : "Off");
1637 if (c_menu.ratio != new_ratio)
1639 changed = true;
1640 c_menu.ratio = new_ratio;
1641 if (c_menu.ratio)
1642 { logf(" Compressor Ratio: %d:1", c_menu.ratio); }
1643 else
1644 { logf(" Compressor Ratio: Limit"); }
1647 if (c_menu.soft_knee != new_knee)
1649 changed = true;
1650 c_menu.soft_knee = new_knee;
1651 logf(" Compressor Knee: %s", c_menu.soft_knee==1?"Soft":"Hard");
1654 if (c_menu.release != new_release)
1656 changed = true;
1657 c_menu.release = new_release;
1658 logf(" Compressor Release: %d", c_menu.release);
1661 if (changed && active)
1663 /* configure variables for compressor operation */
1664 int i;
1665 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1666 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1667 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1668 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1669 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1670 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1671 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1672 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1673 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1675 struct curve_point
1677 int32_t db; /* S15.16 format */
1678 int32_t offset; /* S15.16 format */
1679 } db_curve[5];
1681 /** Set up the shape of the compression curve first as decibel values*/
1682 /* db_curve[0] = bottom of knee
1683 [1] = threshold
1684 [2] = top of knee
1685 [3] = 0 db input
1686 [4] = ~+12db input (2 bits clipping overhead) */
1688 db_curve[1].db = c_menu.threshold << 16;
1689 if (c_menu.soft_knee)
1691 /* bottom of knee is 3dB below the threshold for soft knee*/
1692 db_curve[0].db = db_curve[1].db - (3 << 16);
1693 /* top of knee is 3dB above the threshold for soft knee */
1694 db_curve[2].db = db_curve[1].db + (3 << 16);
1695 if (c_menu.ratio)
1696 /* offset = -3db * (ratio - 1) / ratio */
1697 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1698 * (c_menu.ratio - 1) / c_menu.ratio);
1699 else
1700 /* offset = -3db for hard limit */
1701 db_curve[2].offset = (-3 << 16);
1703 else
1705 /* bottom of knee is at the threshold for hard knee */
1706 db_curve[0].db = c_menu.threshold << 16;
1707 /* top of knee is at the threshold for hard knee */
1708 db_curve[2].db = c_menu.threshold << 16;
1709 db_curve[2].offset = 0;
1712 /* Calculate 0db and ~+12db offsets */
1713 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1714 if (c_menu.ratio)
1716 /* offset = threshold * (ratio - 1) / ratio */
1717 db_curve[3].offset = (int32_t)((long long)(c_menu.threshold << 16)
1718 * (c_menu.ratio - 1) / c_menu.ratio);
1719 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1720 * (c_menu.ratio - 1) / c_menu.ratio) + db_curve[3].offset;
1722 else
1724 /* offset = threshold for hard limit */
1725 db_curve[3].offset = (c_menu.threshold << 16);
1726 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1729 /** Now set up the comp_curve table with compression offsets in the form
1730 of gain factors in S7.24 format */
1731 /* comp_curve[0] is 0 (-infinity db) input */
1732 comp_curve[0] = UNITY;
1733 /* comp_curve[1 to 63] are intermediate compression values corresponding
1734 to the 6 MSB of the input values of a non-clipped signal */
1735 for (i = 1; i < 64; i++)
1737 /* db constants are stored as positive numbers;
1738 make them negative here */
1739 int32_t this_db = -db[i];
1741 /* no compression below the knee */
1742 if (this_db <= db_curve[0].db)
1743 comp_curve[i] = UNITY;
1745 /* if soft knee and below top of knee,
1746 interpolate along soft knee slope */
1747 else if (c_menu.soft_knee && (this_db <= db_curve[2].db))
1748 comp_curve[i] = fp_factor(fp_mul(
1749 ((this_db - db_curve[0].db) / 6),
1750 db_curve[2].offset, 16), 16) << 8;
1752 /* interpolate along ratio slope above the knee */
1753 else
1754 comp_curve[i] = fp_factor(fp_mul(
1755 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1756 db_curve[3].offset, 16), 16) << 8;
1758 /* comp_curve[64] is the compression level of a maximum level,
1759 non-clipped signal */
1760 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1762 /* comp_curve[65] is the compression level of a maximum level,
1763 clipped signal */
1764 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1766 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1767 logf("\n *** Compression Offsets ***");
1768 /* some settings for display only, not used in calculations */
1769 db_curve[0].offset = 0;
1770 db_curve[1].offset = 0;
1771 db_curve[3].db = 0;
1773 for (i = 0; i <= 4; i++)
1775 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1776 (float)db_curve[i].db / (1 << 16),
1777 (float)db_curve[i].offset / (1 << 16));
1780 logf("\nGain factors:");
1781 for (i = 1; i <= 65; i++)
1783 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1784 if (i % 4 == 0) debugf("\n");
1786 debugf("\n");
1787 #endif
1789 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1790 comp_makeup_gain = c_menu.auto_gain ?
1791 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1792 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1794 /* calculate per-sample gain change a rate of 10db over release time */
1795 comp_rel_slope = 0xAF0BB2 / c_menu.release;
1796 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1798 release_gain = UNITY;
1801 /* enable/disable the compressor */
1802 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1805 /** GET COMPRESSION GAIN
1806 * Returns the required gain factor in S7.24 format in order to compress the
1807 * sample in accordance with the compression curve. Always 1 or less.
1809 static inline int32_t get_compression_gain(int32_t sample)
1811 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1813 /* sample must be positive */
1814 if (sample < 0)
1815 sample = -(sample + 1);
1817 /* shift sample into 15 frac bit range */
1818 if (frac_bits_offset > 0)
1819 sample >>= frac_bits_offset;
1820 if (frac_bits_offset < 0)
1821 sample <<= -frac_bits_offset;
1823 /* normal case: sample isn't clipped */
1824 if (sample < (1 << 15))
1826 /* index is 6 MSB, rem is 9 LSB */
1827 int index = sample >> 9;
1828 int32_t rem = (sample & 0x1FF) << 22;
1830 /* interpolate from the compression curve:
1831 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1832 return comp_curve[index] - (FRACMUL(rem,
1833 (comp_curve[index] - comp_curve[index + 1])));
1835 /* sample is somewhat clipped, up to 2 bits of overhead */
1836 if (sample < (1 << 17))
1838 /* straight interpolation:
1839 higher gain - ((clipped portion of sample * 4/3
1840 / (1 << 31)) * (higher gain - lower gain)) */
1841 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1842 (comp_curve[64] - comp_curve[65])));
1845 /* sample is too clipped, return invalid value */
1846 return -1;
1849 /** COMPRESSOR PROCESS
1850 * Changes the gain of the samples according to the compressor curve
1852 static void compressor_process(int count, int32_t *buf[])
1854 const int num_chan = AUDIO_DSP.data.num_channels;
1855 int32_t *in_buf[2] = {buf[0], buf[1]};
1857 while (count-- > 0)
1859 int ch;
1860 /* use lowest (most compressed) gain factor of the output buffer
1861 sample pair for both samples (mono is also handled correctly here) */
1862 int32_t sample_gain = UNITY;
1863 for (ch = 0; ch < num_chan; ch++)
1865 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1866 if (this_gain < sample_gain)
1867 sample_gain = this_gain;
1870 /* perform release slope; skip if no compression and no release slope */
1871 if ((sample_gain != UNITY) || (release_gain != UNITY))
1873 /* if larger offset than previous slope, start new release slope */
1874 if ((sample_gain <= release_gain) && (sample_gain > 0))
1876 release_gain = sample_gain;
1878 else
1879 /* keep sloping towards unity gain (and ignore invalid value) */
1881 release_gain += comp_rel_slope;
1882 if (release_gain > UNITY)
1884 release_gain = UNITY;
1889 /* total gain factor is the product of release gain and makeup gain,
1890 but avoid computation if possible */
1891 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1892 (comp_makeup_gain == UNITY) ? release_gain :
1893 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1895 /* Implement the compressor: apply total gain factor (if any) to the
1896 output buffer sample pair/mono sample */
1897 if (total_gain != UNITY)
1899 for (ch = 0; ch < num_chan; ch++)
1901 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1904 in_buf[0]++;
1905 in_buf[1]++;