Cleanup quickscreen text drawing by using text alignment flags for viewports.
[kugel-rb.git] / apps / dsp.c
blobe0cea6d41b13c1d4b1d12abd516daecf38f75a0d
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 "playback.h"
30 #include "system.h"
31 #include "settings.h"
32 #include "replaygain.h"
33 #include "misc.h"
34 #include "tdspeed.h"
35 #include "buffer.h"
36 #include "fixedpoint.h"
37 #include "fracmul.h"
38 #include "pcmbuf.h"
40 /* Define LOGF_ENABLE to enable logf output in this file */
41 /*#define LOGF_ENABLE*/
42 #include "logf.h"
44 /* 16-bit samples are scaled based on these constants. The shift should be
45 * no more than 15.
47 #define WORD_SHIFT 12
48 #define WORD_FRACBITS 27
50 #define NATIVE_DEPTH 16
51 /* If the small buffer size changes, check the assembly code! */
52 #define SMALL_SAMPLE_BUF_COUNT 256
53 #define DEFAULT_GAIN 0x01000000
55 /* enums to index conversion properly with stereo mode and other settings */
56 enum
58 SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED,
59 SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED,
60 SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO,
61 SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES,
62 SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES,
63 SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES,
64 SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES
67 enum
69 SAMPLE_OUTPUT_MONO = 0,
70 SAMPLE_OUTPUT_STEREO,
71 SAMPLE_OUTPUT_DITHERED_MONO,
72 SAMPLE_OUTPUT_DITHERED_STEREO
75 /****************************************************************************
76 * NOTE: Any assembly routines that use these structures must be updated
77 * if current data members are moved or changed.
79 struct resample_data
81 uint32_t delta; /* 00h */
82 uint32_t phase; /* 04h */
83 int32_t last_sample[2]; /* 08h */
84 /* 10h */
87 /* This is for passing needed data to assembly dsp routines. If another
88 * dsp parameter needs to be passed, add to the end of the structure
89 * and remove from dsp_config.
90 * If another function type becomes assembly optimized and requires dsp
91 * config info, add a pointer paramter of type "struct dsp_data *".
92 * If removing something from other than the end, reserve the spot or
93 * else update every implementation for every target.
94 * Be sure to add the offset of the new member for easy viewing as well. :)
95 * It is the first member of dsp_config and all members can be accessesed
96 * through the main aggregate but this is intended to make a safe haven
97 * for these items whereas the c part can be rearranged at will. dsp_data
98 * could even moved within dsp_config without disurbing the order.
100 struct dsp_data
102 int output_scale; /* 00h */
103 int num_channels; /* 04h */
104 struct resample_data resample_data; /* 08h */
105 int32_t clip_min; /* 18h */
106 int32_t clip_max; /* 1ch */
107 int32_t gain; /* 20h - Note that this is in S8.23 format. */
108 /* 24h */
111 /* No asm...yet */
112 struct dither_data
114 long error[3]; /* 00h */
115 long random; /* 0ch */
116 /* 10h */
119 struct crossfeed_data
121 int32_t gain; /* 00h - Direct path gain */
122 int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */
123 int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */
124 int32_t delay[13][2]; /* 20h */
125 int32_t *index; /* 88h - Current pointer into the delay line */
126 /* 8ch */
129 /* Current setup is one lowshelf filters three peaking filters and one
130 * highshelf filter. Varying the number of shelving filters make no sense,
131 * but adding peaking filters is possible.
133 struct eq_state
135 char enabled[5]; /* 00h - Flags for active filters */
136 struct eqfilter filters[5]; /* 08h - packing is 4? */
137 /* 10ch */
140 struct compressor_menu
142 int threshold; /* dB - from menu */
143 int ratio; /* from menu */
144 int gain; /* dB - from menu */
145 bool soft_knee; /* 0 = hard knee, 1 = soft knee */
146 int release; /* samples - from menu */
149 /* Include header with defines which functions are implemented in assembly
150 code for the target */
151 #include <dsp_asm.h>
153 /* Typedefs keep things much neater in this case */
154 typedef void (*sample_input_fn_type)(int count, const char *src[],
155 int32_t *dst[]);
156 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
157 const int32_t *src[], int32_t *dst[]);
158 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
159 const int32_t *src[], int16_t *dst);
161 /* Single-DSP channel processing in place */
162 typedef void (*channels_process_fn_type)(int count, int32_t *buf[]);
163 /* DSP local channel processing in place */
164 typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data,
165 int32_t *buf[]);
168 ***************************************************************************/
170 struct dsp_config
172 struct dsp_data data; /* Config members for use in asm routines */
173 long codec_frequency; /* Sample rate of data coming from the codec */
174 long frequency; /* Effective sample rate after pitch shift (if any) */
175 int sample_depth;
176 int sample_bytes;
177 int stereo_mode;
178 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
179 bool tdspeed_active; /* Timestretch is in use */
180 int frac_bits;
181 #ifdef HAVE_SW_TONE_CONTROLS
182 /* Filter struct for software bass/treble controls */
183 struct eqfilter tone_filter;
184 #endif
185 /* Functions that change depending upon settings - NULL if stage is
186 disabled */
187 sample_input_fn_type input_samples;
188 resample_fn_type resample;
189 sample_output_fn_type output_samples;
190 /* These will be NULL for the voice codec and is more economical that
191 way */
192 channels_process_dsp_fn_type apply_gain;
193 channels_process_fn_type apply_crossfeed;
194 channels_process_fn_type eq_process;
195 channels_process_fn_type channels_process;
196 channels_process_fn_type compressor_process;
199 /* General DSP config */
200 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
201 /* Dithering */
202 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
203 static long dither_mask IBSS_ATTR;
204 static long dither_bias IBSS_ATTR;
205 /* Crossfeed */
206 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
208 .index = (int32_t *)crossfeed_data.delay
211 /* Equalizer */
212 static struct eq_state eq_data; /* A */
214 /* Software tone controls */
215 #ifdef HAVE_SW_TONE_CONTROLS
216 static int prescale; /* A/V */
217 static int bass; /* A/V */
218 static int treble; /* A/V */
219 #endif
221 /* Settings applicable to audio codec only */
222 static int32_t pitch_ratio = PITCH_SPEED_100;
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 */
246 static int32_t small_sample_buf[SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
247 static int32_t small_resample_buf[SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO] IBSS_ATTR;
249 static int32_t *big_sample_buf = NULL;
250 static int32_t *big_resample_buf = NULL;
251 static int big_sample_buf_count = -1; /* -1=unknown, 0=not available */
253 static int sample_buf_count;
254 static int32_t *sample_buf;
255 static int32_t *resample_buf;
257 #define SAMPLE_BUF_LEFT_CHANNEL 0
258 #define SAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2)
259 #define RESAMPLE_BUF_LEFT_CHANNEL 0
260 #define RESAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2 * RESAMPLE_RATIO)
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 int32_t sound_get_pitch(void)
282 return pitch_ratio;
285 void sound_set_pitch(int32_t percent)
287 pitch_ratio = percent;
288 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
289 AUDIO_DSP.codec_frequency);
292 static void tdspeed_setup(struct dsp_config *dspc)
294 /* Assume timestretch will not be used */
295 dspc->tdspeed_active = false;
296 sample_buf = small_sample_buf;
297 resample_buf = small_resample_buf;
298 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
300 if(!dsp_timestretch_available())
301 return; /* Timestretch not enabled or buffer not allocated */
302 if (dspc->tdspeed_percent == 0)
303 dspc->tdspeed_percent = PITCH_SPEED_100;
304 if (!tdspeed_config(
305 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
306 dspc->stereo_mode != STEREO_MONO,
307 dspc->tdspeed_percent))
308 return; /* Timestretch not possible or needed with these parameters */
310 /* Timestretch is to be used */
311 dspc->tdspeed_active = true;
312 sample_buf = big_sample_buf;
313 sample_buf_count = big_sample_buf_count;
314 resample_buf = big_resample_buf;
317 void dsp_timestretch_enable(bool enabled)
319 /* Hook to set up timestretch buffer on first call to settings_apply() */
320 if (big_sample_buf_count < 0) /* Only do something on first call */
322 if (enabled)
324 /* Set up timestretch buffers */
325 big_sample_buf_count = SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO;
326 big_sample_buf = small_resample_buf;
327 big_resample_buf = (int32_t *) buffer_alloc(big_sample_buf_count * RESAMPLE_RATIO * sizeof(int32_t));
329 else
331 /* Not enabled at startup, "big" buffers will never be available */
332 big_sample_buf_count = 0;
334 tdspeed_setup(&AUDIO_DSP);
338 void dsp_set_timestretch(int32_t percent)
340 AUDIO_DSP.tdspeed_percent = percent;
341 tdspeed_setup(&AUDIO_DSP);
344 int32_t dsp_get_timestretch()
346 return AUDIO_DSP.tdspeed_percent;
349 bool dsp_timestretch_available()
351 return (global_settings.timestretch_enabled && big_sample_buf_count > 0);
354 /* Convert count samples to the internal format, if needed. Updates src
355 * to point past the samples "consumed" and dst is set to point to the
356 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
357 * is no point in processing the same data twice.
360 /* convert count 16-bit mono to 32-bit mono */
361 static void sample_input_lte_native_mono(
362 int count, const char *src[], int32_t *dst[])
364 const int16_t *s = (int16_t *) src[0];
365 const int16_t * const send = s + count;
366 int32_t *d = dst[0] = dst[1] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
367 int scale = WORD_SHIFT;
369 while (s < send)
371 *d++ = *s++ << scale;
374 src[0] = (char *)s;
377 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
378 static void sample_input_lte_native_i_stereo(
379 int count, const char *src[], int32_t *dst[])
381 const int32_t *s = (int32_t *) src[0];
382 const int32_t * const send = s + count;
383 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
384 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
385 int scale = WORD_SHIFT;
387 while (s < send)
389 int32_t slr = *s++;
390 #ifdef ROCKBOX_LITTLE_ENDIAN
391 *dl++ = (slr >> 16) << scale;
392 *dr++ = (int32_t)(int16_t)slr << scale;
393 #else /* ROCKBOX_BIG_ENDIAN */
394 *dl++ = (int32_t)(int16_t)slr << scale;
395 *dr++ = (slr >> 16) << scale;
396 #endif
399 src[0] = (char *)s;
402 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
403 static void sample_input_lte_native_ni_stereo(
404 int count, const char *src[], int32_t *dst[])
406 const int16_t *sl = (int16_t *) src[0];
407 const int16_t *sr = (int16_t *) src[1];
408 const int16_t * const slend = sl + count;
409 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
410 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
411 int scale = WORD_SHIFT;
413 while (sl < slend)
415 *dl++ = *sl++ << scale;
416 *dr++ = *sr++ << scale;
419 src[0] = (char *)sl;
420 src[1] = (char *)sr;
423 /* convert count 32-bit mono to 32-bit mono */
424 static void sample_input_gt_native_mono(
425 int count, const char *src[], int32_t *dst[])
427 dst[0] = dst[1] = (int32_t *)src[0];
428 src[0] = (char *)(dst[0] + count);
431 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
432 static void sample_input_gt_native_i_stereo(
433 int count, const char *src[], int32_t *dst[])
435 const int32_t *s = (int32_t *)src[0];
436 const int32_t * const send = s + 2*count;
437 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
438 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
440 while (s < send)
442 *dl++ = *s++;
443 *dr++ = *s++;
446 src[0] = (char *)send;
449 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
450 static void sample_input_gt_native_ni_stereo(
451 int count, const char *src[], int32_t *dst[])
453 dst[0] = (int32_t *)src[0];
454 dst[1] = (int32_t *)src[1];
455 src[0] = (char *)(dst[0] + count);
456 src[1] = (char *)(dst[1] + count);
460 * sample_input_new_format()
462 * set the to-native sample conversion function based on dsp sample parameters
464 * !DSPPARAMSYNC
465 * needs syncing with changes to the following dsp parameters:
466 * * dsp->stereo_mode (A/V)
467 * * dsp->sample_depth (A/V)
469 static void sample_input_new_format(struct dsp_config *dsp)
471 static const sample_input_fn_type sample_input_functions[] =
473 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
474 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
475 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
476 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
477 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
478 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
481 int convert = dsp->stereo_mode;
483 if (dsp->sample_depth > NATIVE_DEPTH)
484 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
486 dsp->input_samples = sample_input_functions[convert];
490 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
491 /* write mono internal format to output format */
492 static void sample_output_mono(int count, struct dsp_data *data,
493 const int32_t *src[], int16_t *dst)
495 const int32_t *s0 = src[0];
496 const int scale = data->output_scale;
497 const int dc_bias = 1 << (scale - 1);
499 while (count-- > 0)
501 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
502 *dst++ = lr;
503 *dst++ = lr;
506 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
508 /* write stereo internal format to output format */
509 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
510 static void sample_output_stereo(int count, struct dsp_data *data,
511 const int32_t *src[], int16_t *dst)
513 const int32_t *s0 = src[0];
514 const int32_t *s1 = src[1];
515 const int scale = data->output_scale;
516 const int dc_bias = 1 << (scale - 1);
518 while (count-- > 0)
520 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
521 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
524 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
527 * The "dither" code to convert the 24-bit samples produced by libmad was
528 * taken from the coolplayer project - coolplayer.sourceforge.net
530 * This function handles mono and stereo outputs.
532 static void sample_output_dithered(int count, struct dsp_data *data,
533 const int32_t *src[], int16_t *dst)
535 const int32_t mask = dither_mask;
536 const int32_t bias = dither_bias;
537 const int scale = data->output_scale;
538 const int32_t min = data->clip_min;
539 const int32_t max = data->clip_max;
540 const int32_t range = max - min;
541 int ch;
542 int16_t *d;
544 for (ch = 0; ch < data->num_channels; ch++)
546 struct dither_data * const dither = &dither_data[ch];
547 const int32_t *s = src[ch];
548 int i;
550 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
552 int32_t output, sample;
553 int32_t random;
555 /* Noise shape and bias (for correct rounding later) */
556 sample = *s;
557 sample += dither->error[0] - dither->error[1] + dither->error[2];
558 dither->error[2] = dither->error[1];
559 dither->error[1] = dither->error[0]/2;
561 output = sample + bias;
563 /* Dither, highpass triangle PDF */
564 random = dither->random*0x0019660dL + 0x3c6ef35fL;
565 output += (random & mask) - (dither->random & mask);
566 dither->random = random;
568 /* Round sample to output range */
569 output &= ~mask;
571 /* Error feedback */
572 dither->error[0] = sample - output;
574 /* Clip */
575 if ((uint32_t)(output - min) > (uint32_t)range)
577 int32_t c = min;
578 if (output > min)
579 c += range;
580 output = c;
583 /* Quantize and store */
584 *d = output >> scale;
588 if (data->num_channels == 2)
589 return;
591 /* Have to duplicate left samples into the right channel since
592 pcm buffer and hardware is interleaved stereo */
593 d = &dst[0];
595 while (count-- > 0)
597 int16_t s = *d++;
598 *d++ = s;
603 * sample_output_new_format()
605 * set the from-native to ouput sample conversion routine
607 * !DSPPARAMSYNC
608 * needs syncing with changes to the following dsp parameters:
609 * * dsp->stereo_mode (A/V)
610 * * dither_enabled (A)
612 static void sample_output_new_format(struct dsp_config *dsp)
614 static const sample_output_fn_type sample_output_functions[] =
616 sample_output_mono,
617 sample_output_stereo,
618 sample_output_dithered,
619 sample_output_dithered
622 int out = dsp->data.num_channels - 1;
624 if (dsp == &AUDIO_DSP && dither_enabled)
625 out += 2;
627 dsp->output_samples = sample_output_functions[out];
631 * Linear interpolation resampling that introduces a one sample delay because
632 * of our inability to look into the future at the end of a frame.
634 #ifndef DSP_HAVE_ASM_RESAMPLING
635 static int dsp_downsample(int count, struct dsp_data *data,
636 const int32_t *src[], int32_t *dst[])
638 int ch = data->num_channels - 1;
639 uint32_t delta = data->resample_data.delta;
640 uint32_t phase, pos;
641 int32_t *d;
643 /* Rolled channel loop actually showed slightly faster. */
646 /* Just initialize things and not worry too much about the relatively
647 * uncommon case of not being able to spit out a sample for the frame.
649 const int32_t *s = src[ch];
650 int32_t last = data->resample_data.last_sample[ch];
652 data->resample_data.last_sample[ch] = s[count - 1];
653 d = dst[ch];
654 phase = data->resample_data.phase;
655 pos = phase >> 16;
657 /* Do we need last sample of previous frame for interpolation? */
658 if (pos > 0)
659 last = s[pos - 1];
661 while (pos < (uint32_t)count)
663 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
664 phase += delta;
665 pos = phase >> 16;
666 last = s[pos - 1];
669 while (--ch >= 0);
671 /* Wrap phase accumulator back to start of next frame. */
672 data->resample_data.phase = phase - (count << 16);
673 return d - dst[0];
676 static int dsp_upsample(int count, struct dsp_data *data,
677 const int32_t *src[], int32_t *dst[])
679 int ch = data->num_channels - 1;
680 uint32_t delta = data->resample_data.delta;
681 uint32_t phase, pos;
682 int32_t *d;
684 /* Rolled channel loop actually showed slightly faster. */
687 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
688 const int32_t *s = src[ch];
689 int32_t last = data->resample_data.last_sample[ch];
691 data->resample_data.last_sample[ch] = s[count - 1];
692 d = dst[ch];
693 phase = data->resample_data.phase;
694 pos = phase >> 16;
696 while (pos == 0)
698 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
699 phase += delta;
700 pos = phase >> 16;
703 while (pos < (uint32_t)count)
705 last = s[pos - 1];
706 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
707 phase += delta;
708 pos = phase >> 16;
711 while (--ch >= 0);
713 /* Wrap phase accumulator back to start of next frame. */
714 data->resample_data.phase = phase & 0xffff;
715 return d - dst[0];
717 #endif /* DSP_HAVE_ASM_RESAMPLING */
719 static void resampler_new_delta(struct dsp_config *dsp)
721 dsp->data.resample_data.delta = (unsigned long)
722 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
724 if (dsp->frequency == NATIVE_FREQUENCY)
726 /* NOTE: If fully glitch-free transistions from no resampling to
727 resampling are desired, last_sample history should be maintained
728 even when not resampling. */
729 dsp->resample = NULL;
730 dsp->data.resample_data.phase = 0;
731 dsp->data.resample_data.last_sample[0] = 0;
732 dsp->data.resample_data.last_sample[1] = 0;
734 else if (dsp->frequency < NATIVE_FREQUENCY)
735 dsp->resample = dsp_upsample;
736 else
737 dsp->resample = dsp_downsample;
740 /* Resample count stereo samples. Updates the src array, if resampling is
741 * done, to refer to the resampled data. Returns number of stereo samples
742 * for further processing.
744 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
746 int32_t *dst[2] =
748 &resample_buf[RESAMPLE_BUF_LEFT_CHANNEL],
749 &resample_buf[RESAMPLE_BUF_RIGHT_CHANNEL],
752 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
754 src[0] = dst[0];
755 src[1] = dst[dsp->data.num_channels - 1];
757 return count;
760 static void dither_init(struct dsp_config *dsp)
762 memset(dither_data, 0, sizeof (dither_data));
763 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
764 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
767 void dsp_dither_enable(bool enable)
769 struct dsp_config *dsp = &AUDIO_DSP;
770 dither_enabled = enable;
771 sample_output_new_format(dsp);
774 /* Applies crossfeed to the stereo signal in src.
775 * Crossfeed is a process where listening over speakers is simulated. This
776 * is good for old hard panned stereo records, which might be quite fatiguing
777 * to listen to on headphones with no crossfeed.
779 #ifndef DSP_HAVE_ASM_CROSSFEED
780 static void apply_crossfeed(int count, int32_t *buf[])
782 int32_t *hist_l = &crossfeed_data.history[0];
783 int32_t *hist_r = &crossfeed_data.history[2];
784 int32_t *delay = &crossfeed_data.delay[0][0];
785 int32_t *coefs = &crossfeed_data.coefs[0];
786 int32_t gain = crossfeed_data.gain;
787 int32_t *di = crossfeed_data.index;
789 int32_t acc;
790 int32_t left, right;
791 int i;
793 for (i = 0; i < count; i++)
795 left = buf[0][i];
796 right = buf[1][i];
798 /* Filter delayed sample from left speaker */
799 acc = FRACMUL(*di, coefs[0]);
800 acc += FRACMUL(hist_l[0], coefs[1]);
801 acc += FRACMUL(hist_l[1], coefs[2]);
802 /* Save filter history for left speaker */
803 hist_l[1] = acc;
804 hist_l[0] = *di;
805 *di++ = left;
806 /* Filter delayed sample from right speaker */
807 acc = FRACMUL(*di, coefs[0]);
808 acc += FRACMUL(hist_r[0], coefs[1]);
809 acc += FRACMUL(hist_r[1], coefs[2]);
810 /* Save filter history for right speaker */
811 hist_r[1] = acc;
812 hist_r[0] = *di;
813 *di++ = right;
814 /* Now add the attenuated direct sound and write to outputs */
815 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
816 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
818 /* Wrap delay line index if bigger than delay line size */
819 if (di >= delay + 13*2)
820 di = delay;
822 /* Write back local copies of data we've modified */
823 crossfeed_data.index = di;
825 #endif /* DSP_HAVE_ASM_CROSSFEED */
828 * dsp_set_crossfeed(bool enable)
830 * !DSPPARAMSYNC
831 * needs syncing with changes to the following dsp parameters:
832 * * dsp->stereo_mode (A)
834 void dsp_set_crossfeed(bool enable)
836 crossfeed_enabled = enable;
837 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
838 ? apply_crossfeed : NULL;
841 void dsp_set_crossfeed_direct_gain(int gain)
843 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
844 /* If gain is negative, the calculation overflowed and we need to clamp */
845 if (crossfeed_data.gain < 0)
846 crossfeed_data.gain = 0x7fffffff;
849 /* Both gains should be below 0 dB */
850 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
852 int32_t *c = crossfeed_data.coefs;
853 long scaler = get_replaygain_int(lf_gain * 10) << 7;
855 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
856 hf_gain -= lf_gain;
857 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
858 * point instead of shelf midpoint. This is for compatibility with the old
859 * crossfeed shelf filter and should be removed if crossfeed settings are
860 * ever made incompatible for any other good reason.
862 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
863 filter_shelf_coefs(cutoff, hf_gain, false, c);
864 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
865 * over 1 and can do this safely
867 c[0] = FRACMUL_SHL(c[0], scaler, 4);
868 c[1] = FRACMUL_SHL(c[1], scaler, 4);
869 c[2] <<= 4;
872 /* Apply a constant gain to the samples (e.g., for ReplayGain).
873 * Note that this must be called before the resampler.
875 #ifndef DSP_HAVE_ASM_APPLY_GAIN
876 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
878 const int32_t gain = data->gain;
879 int ch;
881 for (ch = 0; ch < data->num_channels; ch++)
883 int32_t *d = buf[ch];
884 int i;
886 for (i = 0; i < count; i++)
887 d[i] = FRACMUL_SHL(d[i], gain, 8);
890 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
892 /* Combine all gains to a global gain. */
893 static void set_gain(struct dsp_config *dsp)
895 /* gains are in S7.24 format */
896 dsp->data.gain = DEFAULT_GAIN;
898 /* Replay gain not relevant to voice */
899 if (dsp == &AUDIO_DSP && replaygain)
901 dsp->data.gain = replaygain;
904 if (dsp->eq_process && eq_precut)
906 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
909 #ifdef HAVE_SW_VOLUME_CONTROL
910 if (global_settings.volume < SW_VOLUME_MAX ||
911 global_settings.volume > SW_VOLUME_MIN)
913 int vol_gain = get_replaygain_int(global_settings.volume * 100);
914 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
916 #endif
918 if (dsp->data.gain == DEFAULT_GAIN)
920 dsp->data.gain = 0;
922 else
924 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
927 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
931 * Update the amount to cut the audio before applying the equalizer.
933 * @param precut to apply in decibels (multiplied by 10)
935 void dsp_set_eq_precut(int precut)
937 eq_precut = get_replaygain_int(precut * -10);
938 set_gain(&AUDIO_DSP);
942 * Synchronize the equalizer filter coefficients with the global settings.
944 * @param band the equalizer band to synchronize
946 void dsp_set_eq_coefs(int band)
948 const int *setting;
949 long gain;
950 unsigned long cutoff, q;
952 /* Adjust setting pointer to the band we actually want to change */
953 setting = &global_settings.eq_band0_cutoff + (band * 3);
955 /* Convert user settings to format required by coef generator functions */
956 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
957 q = *setting++;
958 gain = *setting++;
960 if (q == 0)
961 q = 1;
963 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
964 which it should be, since we're executed from the main thread. */
966 /* Assume a band is disabled if the gain is zero */
967 if (gain == 0)
969 eq_data.enabled[band] = 0;
971 else
973 if (band == 0)
974 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
975 else if (band == 4)
976 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
977 else
978 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
980 eq_data.enabled[band] = 1;
984 /* Apply EQ filters to those bands that have got it switched on. */
985 static void eq_process(int count, int32_t *buf[])
987 static const int shifts[] =
989 EQ_SHELF_SHIFT, /* low shelf */
990 EQ_PEAK_SHIFT, /* peaking */
991 EQ_PEAK_SHIFT, /* peaking */
992 EQ_PEAK_SHIFT, /* peaking */
993 EQ_SHELF_SHIFT, /* high shelf */
995 unsigned int channels = AUDIO_DSP.data.num_channels;
996 int i;
998 /* filter configuration currently is 1 low shelf filter, 3 band peaking
999 filters and 1 high shelf filter, in that order. we need to know this
1000 so we can choose the correct shift factor.
1002 for (i = 0; i < 5; i++)
1004 if (!eq_data.enabled[i])
1005 continue;
1006 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1011 * Use to enable the equalizer.
1013 * @param enable true to enable the equalizer
1015 void dsp_set_eq(bool enable)
1017 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1018 set_gain(&AUDIO_DSP);
1021 static void dsp_set_stereo_width(int value)
1023 long width, straight, cross;
1025 width = value * 0x7fffff / 100;
1027 if (value <= 100)
1029 straight = (0x7fffff + width) / 2;
1030 cross = straight - width;
1032 else
1034 /* straight = (1 + width) / (2 * width) */
1035 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1036 cross = straight - 0x7fffff;
1039 dsp_sw_gain = straight << 8;
1040 dsp_sw_cross = cross << 8;
1044 * Implements the different channel configurations and stereo width.
1047 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1048 * completeness. */
1049 #if 0
1050 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1052 /* The channels are each just themselves */
1053 (void)count; (void)buf;
1055 #endif
1057 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1058 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1060 int32_t *sl = buf[0], *sr = buf[1];
1062 while (count-- > 0)
1064 int32_t lr = *sl/2 + *sr/2;
1065 *sl++ = lr;
1066 *sr++ = lr;
1069 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1071 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1072 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1074 const int32_t gain = dsp_sw_gain;
1075 const int32_t cross = dsp_sw_cross;
1076 int32_t *sl = buf[0], *sr = buf[1];
1078 while (count-- > 0)
1080 int32_t l = *sl;
1081 int32_t r = *sr;
1082 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1083 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1086 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1088 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1090 /* Just copy over the other channel */
1091 memcpy(buf[1], buf[0], count * sizeof (*buf));
1094 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1096 /* Just copy over the other channel */
1097 memcpy(buf[0], buf[1], count * sizeof (*buf));
1100 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1101 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1103 int32_t *sl = buf[0], *sr = buf[1];
1105 while (count-- > 0)
1107 int32_t ch = *sl/2 - *sr/2;
1108 *sl++ = ch;
1109 *sr++ = -ch;
1112 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1114 static void dsp_set_channel_config(int value)
1116 static const channels_process_fn_type channels_process_functions[] =
1118 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1119 [SOUND_CHAN_STEREO] = NULL,
1120 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1121 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1122 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1123 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1124 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1127 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1128 AUDIO_DSP.stereo_mode == STEREO_MONO)
1130 value = SOUND_CHAN_STEREO;
1133 /* This doesn't apply to voice */
1134 channels_mode = value;
1135 AUDIO_DSP.channels_process = channels_process_functions[value];
1138 #if CONFIG_CODEC == SWCODEC
1140 #ifdef HAVE_SW_TONE_CONTROLS
1141 static void set_tone_controls(void)
1143 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1144 0xffffffff/NATIVE_FREQUENCY*3500,
1145 bass, treble, -prescale,
1146 AUDIO_DSP.tone_filter.coefs);
1147 /* Sync the voice dsp coefficients */
1148 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1149 sizeof (VOICE_DSP.tone_filter.coefs));
1151 #endif
1153 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1154 * code directly.
1156 int dsp_callback(int msg, intptr_t param)
1158 switch (msg)
1160 #ifdef HAVE_SW_TONE_CONTROLS
1161 case DSP_CALLBACK_SET_PRESCALE:
1162 prescale = param;
1163 set_tone_controls();
1164 break;
1165 /* prescaler is always set after calling any of these, so we wait with
1166 * calculating coefs until the above case is hit.
1168 case DSP_CALLBACK_SET_BASS:
1169 bass = param;
1170 break;
1171 case DSP_CALLBACK_SET_TREBLE:
1172 treble = param;
1173 break;
1174 #ifdef HAVE_SW_VOLUME_CONTROL
1175 case DSP_CALLBACK_SET_SW_VOLUME:
1176 set_gain(&AUDIO_DSP);
1177 break;
1178 #endif
1179 #endif
1180 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1181 dsp_set_channel_config(param);
1182 break;
1183 case DSP_CALLBACK_SET_STEREO_WIDTH:
1184 dsp_set_stereo_width(param);
1185 break;
1186 default:
1187 break;
1189 return 0;
1191 #endif
1193 /* Process and convert src audio to dst based on the DSP configuration,
1194 * reading count number of audio samples. dst is assumed to be large
1195 * enough; use dsp_output_count() to get the required number. src is an
1196 * array of pointers; for mono and interleaved stereo, it contains one
1197 * pointer to the start of the audio data and the other is ignored; for
1198 * non-interleaved stereo, it contains two pointers, one for each audio
1199 * channel. Returns number of bytes written to dst.
1201 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1203 int32_t *tmp[2];
1204 static long last_yield;
1205 long tick;
1206 int written = 0;
1208 #if defined(CPU_COLDFIRE)
1209 /* set emac unit for dsp processing, and save old macsr, we're running in
1210 codec thread context at this point, so can't clobber it */
1211 unsigned long old_macsr = coldfire_get_macsr();
1212 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1213 #endif
1215 if (new_gain)
1216 dsp_set_replaygain(); /* Gain has changed */
1218 /* Perform at least one yield before starting */
1219 last_yield = current_tick;
1220 yield();
1222 /* Testing function pointers for NULL is preferred since the pointer
1223 will be preloaded to be used for the call if not. */
1224 while (count > 0)
1226 int samples = MIN(sample_buf_count/2, count);
1227 count -= samples;
1229 dsp->input_samples(samples, src, tmp);
1231 if (dsp->tdspeed_active)
1232 samples = tdspeed_doit(tmp, samples);
1234 int chunk_offset = 0;
1235 while (samples > 0)
1237 int32_t *t2[2];
1238 t2[0] = tmp[0]+chunk_offset;
1239 t2[1] = tmp[1]+chunk_offset;
1241 int chunk = MIN(sample_buf_count/2, samples);
1242 chunk_offset += chunk;
1243 samples -= chunk;
1245 if (dsp->apply_gain)
1246 dsp->apply_gain(chunk, &dsp->data, t2);
1248 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1249 break; /* I'm pretty sure we're downsampling here */
1251 if (dsp->apply_crossfeed)
1252 dsp->apply_crossfeed(chunk, t2);
1254 if (dsp->eq_process)
1255 dsp->eq_process(chunk, t2);
1257 #ifdef HAVE_SW_TONE_CONTROLS
1258 if ((bass | treble) != 0)
1259 eq_filter(t2, &dsp->tone_filter, chunk,
1260 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1261 #endif
1263 if (dsp->channels_process)
1264 dsp->channels_process(chunk, t2);
1266 if (dsp->compressor_process)
1267 dsp->compressor_process(chunk, t2);
1269 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1271 written += chunk;
1272 dst += chunk * sizeof (int16_t) * 2;
1274 /* yield at least once each tick */
1275 tick = current_tick;
1276 if (TIME_AFTER(tick, last_yield))
1278 last_yield = tick;
1279 yield();
1284 #if defined(CPU_COLDFIRE)
1285 /* set old macsr again */
1286 coldfire_set_macsr(old_macsr);
1287 #endif
1288 return written;
1291 /* Given count number of input samples, calculate the maximum number of
1292 * samples of output data that would be generated (the calculation is not
1293 * entirely exact and rounds upwards to be on the safe side; during
1294 * resampling, the number of samples generated depends on the current state
1295 * of the resampler).
1297 /* dsp_input_size MUST be called afterwards */
1298 int dsp_output_count(struct dsp_config *dsp, int count)
1300 if (dsp->tdspeed_active)
1301 count = tdspeed_est_output_size();
1302 if (dsp->resample)
1304 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1305 + (dsp->frequency - 1)) / dsp->frequency);
1308 /* Now we have the resampled sample count which must not exceed
1309 * RESAMPLE_BUF_RIGHT_CHANNEL to avoid resample buffer overflow. One
1310 * must call dsp_input_count() to get the correct input sample
1311 * count.
1313 if (count > RESAMPLE_BUF_RIGHT_CHANNEL)
1314 count = RESAMPLE_BUF_RIGHT_CHANNEL;
1316 return count;
1319 /* Given count output samples, calculate number of input samples
1320 * that would be consumed in order to fill the output buffer.
1322 int dsp_input_count(struct dsp_config *dsp, int count)
1324 /* count is now the number of resampled input samples. Convert to
1325 original input samples. */
1326 if (dsp->resample)
1328 /* Use the real resampling delta =
1329 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1330 * round towards zero to avoid buffer overflows. */
1331 count = (int)(((unsigned long)count *
1332 dsp->data.resample_data.delta) >> 16);
1335 if (dsp->tdspeed_active)
1336 count = tdspeed_est_input_size(count);
1338 return count;
1341 static void dsp_set_gain_var(long *var, long value)
1343 *var = value;
1344 new_gain = true;
1347 static void dsp_update_functions(struct dsp_config *dsp)
1349 sample_input_new_format(dsp);
1350 sample_output_new_format(dsp);
1351 if (dsp == &AUDIO_DSP)
1352 dsp_set_crossfeed(crossfeed_enabled);
1355 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1357 switch (setting)
1359 case DSP_MYDSP:
1360 switch (value)
1362 case CODEC_IDX_AUDIO:
1363 return (intptr_t)&AUDIO_DSP;
1364 case CODEC_IDX_VOICE:
1365 return (intptr_t)&VOICE_DSP;
1366 default:
1367 return (intptr_t)NULL;
1370 case DSP_SET_FREQUENCY:
1371 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1372 /* Fall through!!! */
1373 case DSP_SWITCH_FREQUENCY:
1374 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1375 /* Account for playback speed adjustment when setting dsp->frequency
1376 if we're called from the main audio thread. Voice UI thread should
1377 not need this feature.
1379 if (dsp == &AUDIO_DSP)
1380 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1381 else
1382 dsp->frequency = dsp->codec_frequency;
1384 resampler_new_delta(dsp);
1385 tdspeed_setup(dsp);
1386 break;
1388 case DSP_SET_SAMPLE_DEPTH:
1389 dsp->sample_depth = value;
1391 if (dsp->sample_depth <= NATIVE_DEPTH)
1393 dsp->frac_bits = WORD_FRACBITS;
1394 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1395 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1396 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1398 else
1400 dsp->frac_bits = value;
1401 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1402 dsp->data.clip_max = (1 << value) - 1;
1403 dsp->data.clip_min = -(1 << value);
1406 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1407 sample_input_new_format(dsp);
1408 dither_init(dsp);
1409 break;
1411 case DSP_SET_STEREO_MODE:
1412 dsp->stereo_mode = value;
1413 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1414 dsp_update_functions(dsp);
1415 tdspeed_setup(dsp);
1416 break;
1418 case DSP_RESET:
1419 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1420 dsp->data.num_channels = 2;
1421 dsp->sample_depth = NATIVE_DEPTH;
1422 dsp->frac_bits = WORD_FRACBITS;
1423 dsp->sample_bytes = sizeof (int16_t);
1424 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1425 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1426 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1427 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1429 if (dsp == &AUDIO_DSP)
1431 track_gain = 0;
1432 album_gain = 0;
1433 track_peak = 0;
1434 album_peak = 0;
1435 new_gain = true;
1438 dsp_update_functions(dsp);
1439 resampler_new_delta(dsp);
1440 tdspeed_setup(dsp);
1441 if (dsp == &AUDIO_DSP)
1442 release_gain = UNITY;
1443 break;
1445 case DSP_FLUSH:
1446 memset(&dsp->data.resample_data, 0,
1447 sizeof (dsp->data.resample_data));
1448 resampler_new_delta(dsp);
1449 dither_init(dsp);
1450 tdspeed_setup(dsp);
1451 if (dsp == &AUDIO_DSP)
1452 release_gain = UNITY;
1453 break;
1455 case DSP_SET_TRACK_GAIN:
1456 if (dsp == &AUDIO_DSP)
1457 dsp_set_gain_var(&track_gain, value);
1458 break;
1460 case DSP_SET_ALBUM_GAIN:
1461 if (dsp == &AUDIO_DSP)
1462 dsp_set_gain_var(&album_gain, value);
1463 break;
1465 case DSP_SET_TRACK_PEAK:
1466 if (dsp == &AUDIO_DSP)
1467 dsp_set_gain_var(&track_peak, value);
1468 break;
1470 case DSP_SET_ALBUM_PEAK:
1471 if (dsp == &AUDIO_DSP)
1472 dsp_set_gain_var(&album_peak, value);
1473 break;
1475 default:
1476 return 0;
1479 return 1;
1482 void dsp_set_replaygain(void)
1484 long gain = 0;
1486 new_gain = false;
1488 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1489 global_settings.replaygain_noclip)
1491 bool track_mode = get_replaygain_mode(track_gain != 0,
1492 album_gain != 0) == REPLAYGAIN_TRACK;
1493 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1495 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1497 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1499 if (global_settings.replaygain_preamp)
1501 long preamp = get_replaygain_int(
1502 global_settings.replaygain_preamp * 10);
1504 gain = (long) (((int64_t) gain * preamp) >> 24);
1508 if (gain == 0)
1510 /* So that noclip can work even with no gain information. */
1511 gain = DEFAULT_GAIN;
1514 if (global_settings.replaygain_noclip && (peak != 0)
1515 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1517 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1520 if (gain == DEFAULT_GAIN)
1522 /* Nothing to do, disable processing. */
1523 gain = 0;
1527 /* Store in S7.24 format to simplify calculations. */
1528 replaygain = gain;
1529 set_gain(&AUDIO_DSP);
1532 /** SET COMPRESSOR
1533 * Called by the menu system to configure the compressor process */
1534 void dsp_set_compressor(int c_threshold, int c_ratio, int c_gain,
1535 int c_knee, int c_release)
1537 bool changed = false;
1538 bool active = (c_threshold < 0);
1539 const int comp_ratio[] = {2, 4, 6, 10, 0};
1540 int new_ratio = comp_ratio[c_ratio];
1541 bool new_knee = (c_knee == 1);
1542 int new_release = c_release * NATIVE_FREQUENCY / 1000;
1544 if (c_menu.threshold != c_threshold)
1546 changed = true;
1547 c_menu.threshold = c_threshold;
1548 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1549 c_menu.threshold, active ? "Yes" : "No");
1552 if (c_menu.ratio != new_ratio)
1554 changed = true;
1555 c_menu.ratio = new_ratio;
1556 if (c_menu.ratio)
1558 logf(" Compressor Ratio: %d:1", c_menu.ratio);
1560 else
1562 logf(" Compressor Ratio: Limit");
1566 if (c_menu.gain != c_gain)
1568 changed = true;
1569 c_menu.gain = c_gain;
1570 if (c_menu.gain >= 0)
1572 logf(" Compressor Makeup Gain: %d dB", c_menu.gain);
1574 else
1576 logf(" Compressor Makeup Gain: Auto");
1580 if (c_menu.soft_knee != new_knee)
1582 changed = true;
1583 c_menu.soft_knee = new_knee;
1584 logf(" Compressor Knee: %s", c_menu.soft_knee==1?"Soft":"Hard");
1587 if (c_menu.release != new_release)
1589 changed = true;
1590 c_menu.release = new_release;
1591 logf(" Compressor Release: %d", c_menu.release);
1594 if (changed && active)
1596 /* configure variables for compressor operation */
1597 int i;
1598 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1599 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1600 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1601 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1602 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1603 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1604 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1605 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1606 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1608 struct curve_point
1610 int32_t db; /* S15.16 format */
1611 int32_t offset; /* S15.16 format */
1612 } db_curve[5];
1614 /** Set up the shape of the compression curve first as decibel values*/
1615 /* db_curve[0] = bottom of knee
1616 [1] = threshold
1617 [2] = top of knee
1618 [3] = 0 db input
1619 [4] = ~+12db input (2 bits clipping overhead) */
1621 db_curve[1].db = c_menu.threshold << 16;
1622 if (c_menu.soft_knee)
1624 /* bottom of knee is 3dB below the threshold for soft knee*/
1625 db_curve[0].db = db_curve[1].db - (3 << 16);
1626 /* top of knee is 3dB above the threshold for soft knee */
1627 db_curve[2].db = db_curve[1].db + (3 << 16);
1628 if (c_menu.ratio)
1629 /* offset = -3db * (ratio - 1) / ratio */
1630 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1631 * (c_menu.ratio - 1) / c_menu.ratio);
1632 else
1633 /* offset = -3db for hard limit */
1634 db_curve[2].offset = (-3 << 16);
1636 else
1638 /* bottom of knee is at the threshold for hard knee */
1639 db_curve[0].db = c_menu.threshold << 16;
1640 /* top of knee is at the threshold for hard knee */
1641 db_curve[2].db = c_menu.threshold << 16;
1642 db_curve[2].offset = 0;
1645 /* Calculate 0db and ~+12db offsets */
1646 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1647 if (c_menu.ratio)
1649 /* offset = threshold * (ratio - 1) / ratio */
1650 db_curve[3].offset = (int32_t)((long long)(c_menu.threshold << 16)
1651 * (c_menu.ratio - 1) / c_menu.ratio);
1652 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1653 * (c_menu.ratio - 1) / c_menu.ratio) + db_curve[3].offset;
1655 else
1657 /* offset = threshold for hard limit */
1658 db_curve[3].offset = (c_menu.threshold << 16);
1659 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1662 /** Now set up the comp_curve table with compression offsets in the form
1663 of gain factors in S7.24 format */
1664 /* comp_curve[0] is 0 (-infinity db) input */
1665 comp_curve[0] = UNITY;
1666 /* comp_curve[1 to 63] are intermediate compression values corresponding
1667 to the 6 MSB of the input values of a non-clipped signal */
1668 for (i = 1; i < 64; i++)
1670 /* db constants are stored as positive numbers;
1671 make them negative here */
1672 int32_t this_db = -db[i];
1674 /* no compression below the knee */
1675 if (this_db <= db_curve[0].db)
1676 comp_curve[i] = UNITY;
1678 /* if soft knee and below top of knee,
1679 interpolate along soft knee slope */
1680 else if (c_menu.soft_knee && (this_db <= db_curve[2].db))
1681 comp_curve[i] = fp_factor(fp_mul(
1682 ((this_db - db_curve[0].db) / 6),
1683 db_curve[2].offset, 16), 16) << 8;
1685 /* interpolate along ratio slope above the knee */
1686 else
1687 comp_curve[i] = fp_factor(fp_mul(
1688 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1689 db_curve[3].offset, 16), 16) << 8;
1691 /* comp_curve[64] is the compression level of a maximum level,
1692 non-clipped signal */
1693 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1695 /* comp_curve[65] is the compression level of a maximum level,
1696 clipped signal */
1697 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1699 #if defined(SIMULATOR) && defined(LOGF_ENABLE)
1700 logf("\n *** Compression Offsets ***");
1701 /* some settings for display only, not used in calculations */
1702 db_curve[0].offset = 0;
1703 db_curve[1].offset = 0;
1704 db_curve[3].db = 0;
1706 for (i = 0; i <= 4; i++)
1708 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1709 (float)db_curve[i].db / (1 << 16),
1710 (float)db_curve[i].offset / (1 << 16));
1713 logf("\nGain factors:");
1714 for (i = 1; i <= 65; i++)
1716 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1717 if (i % 4 == 0) debugf("\n");
1719 debugf("\n");
1720 #endif
1722 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1723 int32_t db_makeup = (c_menu.gain == -1) ?
1724 -(db_curve[3].offset) - 0x199A : c_menu.gain << 16;
1725 comp_makeup_gain = fp_factor(db_makeup, 16) << 8;
1726 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1728 /* calculate per-sample gain change a rate of 10db over release time */
1729 comp_rel_slope = 0xAF0BB2 / c_menu.release;
1730 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1732 release_gain = UNITY;
1735 /* enable/disable the compressor */
1736 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1739 /** GET COMPRESSION GAIN
1740 * Returns the required gain factor in S7.24 format in order to compress the
1741 * sample in accordance with the compression curve. Always 1 or less.
1743 static inline int32_t get_compression_gain(int32_t sample)
1745 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1747 /* sample must be positive */
1748 if (sample < 0)
1749 sample = -(sample + 1);
1751 /* shift sample into 15 frac bit range */
1752 if (frac_bits_offset > 0)
1753 sample >>= frac_bits_offset;
1754 if (frac_bits_offset < 0)
1755 sample <<= -frac_bits_offset;
1757 /* normal case: sample isn't clipped */
1758 if (sample < (1 << 15))
1760 /* index is 6 MSB, rem is 9 LSB */
1761 int index = sample >> 9;
1762 int32_t rem = (sample & 0x1FF) << 22;
1764 /* interpolate from the compression curve:
1765 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1766 return comp_curve[index] - (FRACMUL(rem,
1767 (comp_curve[index] - comp_curve[index + 1])));
1769 /* sample is somewhat clipped, up to 2 bits of overhead */
1770 if (sample < (1 << 17))
1772 /* straight interpolation:
1773 higher gain - ((clipped portion of sample * 4/3
1774 / (1 << 31)) * (higher gain - lower gain)) */
1775 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1776 (comp_curve[64] - comp_curve[65])));
1779 /* sample is too clipped, return invalid value */
1780 return -1;
1783 /** COMPRESSOR PROCESS
1784 * Changes the gain of the samples according to the compressor curve
1786 static void compressor_process(int count, int32_t *buf[])
1788 const int num_chan = AUDIO_DSP.data.num_channels;
1789 int32_t *in_buf[2] = {buf[0], buf[1]};
1791 while (count-- > 0)
1793 int ch;
1794 /* use lowest (most compressed) gain factor of the output buffer
1795 sample pair for both samples (mono is also handled correctly here) */
1796 int32_t sample_gain = UNITY;
1797 for (ch = 0; ch < num_chan; ch++)
1799 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1800 if (this_gain < sample_gain)
1801 sample_gain = this_gain;
1804 /* perform release slope; skip if no compression and no release slope */
1805 if ((sample_gain != UNITY) || (release_gain != UNITY))
1807 /* if larger offset than previous slope, start new release slope */
1808 if ((sample_gain <= release_gain) && (sample_gain > 0))
1810 release_gain = sample_gain;
1812 else
1813 /* keep sloping towards unity gain (and ignore invalid value) */
1815 release_gain += comp_rel_slope;
1816 if (release_gain > UNITY)
1818 release_gain = UNITY;
1823 /* total gain factor is the product of release gain and makeup gain,
1824 but avoid computation if possible */
1825 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1826 (comp_makeup_gain == UNITY) ? release_gain :
1827 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1829 /* Implement the compressor: apply total gain factor (if any) to the
1830 output buffer sample pair/mono sample */
1831 if (total_gain != UNITY)
1833 for (ch = 0; ch < num_chan; ch++)
1835 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1838 in_buf[0]++;
1839 in_buf[1]++;