GSoC/Buflib: Enable compaction in buflib.
[kugel-rb.git] / apps / dsp.c
blob167c0434270c6df5bab528478e3de95e9f94deaf
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2005 Miika Pekkarinen
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
21 #include "config.h"
22 #include <stdbool.h>
23 #include <inttypes.h>
24 #include <string.h>
25 #include <sound.h>
26 #include "dsp.h"
27 #include "eq.h"
28 #include "kernel.h"
29 #include "system.h"
30 #include "settings.h"
31 #include "replaygain.h"
32 #include "tdspeed.h"
33 #include "core_alloc.h"
34 #include "fixedpoint.h"
35 #include "fracmul.h"
37 /* Define LOGF_ENABLE to enable logf output in this file */
38 /*#define LOGF_ENABLE*/
39 #include "logf.h"
41 /* 16-bit samples are scaled based on these constants. The shift should be
42 * no more than 15.
44 #define WORD_SHIFT 12
45 #define WORD_FRACBITS 27
47 #define NATIVE_DEPTH 16
48 /* If the small buffer size changes, check the assembly code! */
49 #define SMALL_SAMPLE_BUF_COUNT 256
50 #define DEFAULT_GAIN 0x01000000
52 /* enums to index conversion properly with stereo mode and other settings */
53 enum
55 SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED,
56 SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED,
57 SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO,
58 SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES,
59 SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES,
60 SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES,
61 SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES
64 enum
66 SAMPLE_OUTPUT_MONO = 0,
67 SAMPLE_OUTPUT_STEREO,
68 SAMPLE_OUTPUT_DITHERED_MONO,
69 SAMPLE_OUTPUT_DITHERED_STEREO
72 /****************************************************************************
73 * NOTE: Any assembly routines that use these structures must be updated
74 * if current data members are moved or changed.
76 struct resample_data
78 uint32_t delta; /* 00h */
79 uint32_t phase; /* 04h */
80 int32_t last_sample[2]; /* 08h */
81 /* 10h */
84 /* This is for passing needed data to assembly dsp routines. If another
85 * dsp parameter needs to be passed, add to the end of the structure
86 * and remove from dsp_config.
87 * If another function type becomes assembly optimized and requires dsp
88 * config info, add a pointer paramter of type "struct dsp_data *".
89 * If removing something from other than the end, reserve the spot or
90 * else update every implementation for every target.
91 * Be sure to add the offset of the new member for easy viewing as well. :)
92 * It is the first member of dsp_config and all members can be accessesed
93 * through the main aggregate but this is intended to make a safe haven
94 * for these items whereas the c part can be rearranged at will. dsp_data
95 * could even moved within dsp_config without disurbing the order.
97 struct dsp_data
99 int output_scale; /* 00h */
100 int num_channels; /* 04h */
101 struct resample_data resample_data; /* 08h */
102 int32_t clip_min; /* 18h */
103 int32_t clip_max; /* 1ch */
104 int32_t gain; /* 20h - Note that this is in S8.23 format. */
105 /* 24h */
108 /* No asm...yet */
109 struct dither_data
111 long error[3]; /* 00h */
112 long random; /* 0ch */
113 /* 10h */
116 struct crossfeed_data
118 int32_t gain; /* 00h - Direct path gain */
119 int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */
120 int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */
121 int32_t delay[13][2]; /* 20h */
122 int32_t *index; /* 88h - Current pointer into the delay line */
123 /* 8ch */
126 /* Current setup is one lowshelf filters three peaking filters and one
127 * highshelf filter. Varying the number of shelving filters make no sense,
128 * but adding peaking filters is possible.
130 struct eq_state
132 char enabled[5]; /* 00h - Flags for active filters */
133 struct eqfilter filters[5]; /* 08h - packing is 4? */
134 /* 10ch */
137 struct compressor_menu
139 int threshold; /* dB - from menu */
140 bool auto_gain; /* 0 = off, 1 = auto */
141 int ratio; /* from menu */
142 bool soft_knee; /* 0 = hard knee, 1 = soft knee */
143 int release; /* samples - from menu */
146 /* Include header with defines which functions are implemented in assembly
147 code for the target */
148 #include <dsp_asm.h>
150 /* Typedefs keep things much neater in this case */
151 typedef void (*sample_input_fn_type)(int count, const char *src[],
152 int32_t *dst[]);
153 typedef int (*resample_fn_type)(int count, struct dsp_data *data,
154 const int32_t *src[], int32_t *dst[]);
155 typedef void (*sample_output_fn_type)(int count, struct dsp_data *data,
156 const int32_t *src[], int16_t *dst);
158 /* Single-DSP channel processing in place */
159 typedef void (*channels_process_fn_type)(int count, int32_t *buf[]);
160 /* DSP local channel processing in place */
161 typedef void (*channels_process_dsp_fn_type)(int count, struct dsp_data *data,
162 int32_t *buf[]);
165 ***************************************************************************/
167 struct dsp_config
169 struct dsp_data data; /* Config members for use in asm routines */
170 long codec_frequency; /* Sample rate of data coming from the codec */
171 long frequency; /* Effective sample rate after pitch shift (if any) */
172 int sample_depth;
173 int sample_bytes;
174 int stereo_mode;
175 int32_t tdspeed_percent; /* Speed% * PITCH_SPEED_PRECISION */
176 #ifdef HAVE_PITCHSCREEN
177 bool tdspeed_active; /* Timestretch is in use */
178 #endif
179 int frac_bits;
180 #ifdef HAVE_SW_TONE_CONTROLS
181 /* Filter struct for software bass/treble controls */
182 struct eqfilter tone_filter;
183 #endif
184 /* Functions that change depending upon settings - NULL if stage is
185 disabled */
186 sample_input_fn_type input_samples;
187 resample_fn_type resample;
188 sample_output_fn_type output_samples;
189 /* These will be NULL for the voice codec and is more economical that
190 way */
191 channels_process_dsp_fn_type apply_gain;
192 channels_process_fn_type apply_crossfeed;
193 channels_process_fn_type eq_process;
194 channels_process_fn_type channels_process;
195 channels_process_fn_type compressor_process;
198 /* General DSP config */
199 static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */
200 /* Dithering */
201 static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */
202 static long dither_mask IBSS_ATTR;
203 static long dither_bias IBSS_ATTR;
204 /* Crossfeed */
205 struct crossfeed_data crossfeed_data IDATA_ATTR = /* A */
207 .index = (int32_t *)crossfeed_data.delay
210 /* Equalizer */
211 static struct eq_state eq_data; /* A */
213 /* Software tone controls */
214 #ifdef HAVE_SW_TONE_CONTROLS
215 static int prescale; /* A/V */
216 static int bass; /* A/V */
217 static int treble; /* A/V */
218 #endif
220 /* Settings applicable to audio codec only */
221 #ifdef HAVE_PITCHSCREEN
222 static int32_t pitch_ratio = PITCH_SPEED_100;
223 #endif
224 static int channels_mode;
225 long dsp_sw_gain;
226 long dsp_sw_cross;
227 static bool dither_enabled;
228 static long eq_precut;
229 static long track_gain;
230 static bool new_gain;
231 static long album_gain;
232 static long track_peak;
233 static long album_peak;
234 static long replaygain;
235 static bool crossfeed_enabled;
237 #define AUDIO_DSP (dsp_conf[CODEC_IDX_AUDIO])
238 #define VOICE_DSP (dsp_conf[CODEC_IDX_VOICE])
240 /* The internal format is 32-bit samples, non-interleaved, stereo. This
241 * format is similar to the raw output from several codecs, so the amount
242 * of copying needed is minimized for that case.
245 #define RESAMPLE_RATIO 4 /* Enough for 11,025 Hz -> 44,100 Hz */
247 static int32_t small_sample_buf[SMALL_SAMPLE_BUF_COUNT] IBSS_ATTR;
248 static int32_t small_resample_buf[SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO] IBSS_ATTR;
250 #ifdef HAVE_PITCHSCREEN
251 static int32_t *big_sample_buf = NULL;
252 static int32_t *big_resample_buf = NULL;
253 static int big_sample_buf_count = -1; /* -1=unknown, 0=not available */
254 #endif
256 static int sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
257 static int32_t *sample_buf = small_sample_buf;
258 static int32_t *resample_buf = small_resample_buf;
260 #define SAMPLE_BUF_LEFT_CHANNEL 0
261 #define SAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2)
262 #define RESAMPLE_BUF_LEFT_CHANNEL 0
263 #define RESAMPLE_BUF_RIGHT_CHANNEL (sample_buf_count/2 * RESAMPLE_RATIO)
265 /* compressor */
266 static struct compressor_menu c_menu;
267 static int32_t comp_rel_slope IBSS_ATTR; /* S7.24 format */
268 static int32_t comp_makeup_gain IBSS_ATTR; /* S7.24 format */
269 static int32_t comp_curve[66] IBSS_ATTR; /* S7.24 format */
270 static int32_t release_gain IBSS_ATTR; /* S7.24 format */
271 #define UNITY (1L << 24) /* unity gain in S7.24 format */
272 static void compressor_process(int count, int32_t *buf[]);
275 /* Clip sample to signed 16 bit range */
276 static inline int32_t clip_sample_16(int32_t sample)
278 if ((int16_t)sample != sample)
279 sample = 0x7fff ^ (sample >> 31);
280 return sample;
283 #ifdef HAVE_PITCHSCREEN
284 int32_t sound_get_pitch(void)
286 return pitch_ratio;
289 void sound_set_pitch(int32_t percent)
291 pitch_ratio = percent;
292 dsp_configure(&AUDIO_DSP, DSP_SWITCH_FREQUENCY,
293 AUDIO_DSP.codec_frequency);
296 static void tdspeed_setup(struct dsp_config *dspc)
298 /* Assume timestretch will not be used */
299 dspc->tdspeed_active = false;
300 sample_buf = small_sample_buf;
301 resample_buf = small_resample_buf;
302 sample_buf_count = SMALL_SAMPLE_BUF_COUNT;
304 if(!dsp_timestretch_available())
305 return; /* Timestretch not enabled or buffer not allocated */
306 if (dspc->tdspeed_percent == 0)
307 dspc->tdspeed_percent = PITCH_SPEED_100;
308 if (!tdspeed_config(
309 dspc->codec_frequency == 0 ? NATIVE_FREQUENCY : dspc->codec_frequency,
310 dspc->stereo_mode != STEREO_MONO,
311 dspc->tdspeed_percent))
312 return; /* Timestretch not possible or needed with these parameters */
314 /* Timestretch is to be used */
315 dspc->tdspeed_active = true;
316 sample_buf = big_sample_buf;
317 sample_buf_count = big_sample_buf_count;
318 resample_buf = big_resample_buf;
322 static int move_callback(int handle, void* current, void* new)
324 /* TODO */
325 (void)handle;(void)current;;
326 big_sample_buf = new;
327 return BUFLIB_CB_OK;
330 static struct buflib_callbacks ops = {
331 .move_callback = move_callback,
332 .shrink_callback = NULL,
336 void dsp_timestretch_enable(bool enabled)
338 /* Hook to set up timestretch buffer on first call to settings_apply() */
339 static int handle;
340 if (enabled)
342 if (big_sample_buf_count > 0)
343 return; /* already allocated and enabled */
344 /* Set up timestretch buffers */
345 big_sample_buf_count = SMALL_SAMPLE_BUF_COUNT * RESAMPLE_RATIO;
346 big_sample_buf = small_resample_buf;
347 handle = core_alloc_ex("resample buf",
348 big_sample_buf_count * RESAMPLE_RATIO * sizeof(int32_t), &ops);
349 if (handle > 0)
350 { /* success, now setup tdspeed */
351 big_resample_buf = core_get_data(handle);
352 tdspeed_init();
353 tdspeed_setup(&AUDIO_DSP);
356 if (!enabled || (handle <= 0)) /* disable */
358 dsp_set_timestretch(PITCH_SPEED_100);
359 tdspeed_finish();
360 if (handle > 0)
361 core_free(handle);
362 handle = 0;
363 big_sample_buf = NULL;
364 big_sample_buf_count = 0;
368 void dsp_set_timestretch(int32_t percent)
370 AUDIO_DSP.tdspeed_percent = percent;
371 tdspeed_setup(&AUDIO_DSP);
374 int32_t dsp_get_timestretch()
376 return AUDIO_DSP.tdspeed_percent;
379 bool dsp_timestretch_available()
381 return (global_settings.timestretch_enabled && big_sample_buf_count > 0);
383 #endif
385 /* Convert count samples to the internal format, if needed. Updates src
386 * to point past the samples "consumed" and dst is set to point to the
387 * samples to consume. Note that for mono, dst[0] equals dst[1], as there
388 * is no point in processing the same data twice.
391 /* convert count 16-bit mono to 32-bit mono */
392 static void sample_input_lte_native_mono(
393 int count, const char *src[], int32_t *dst[])
395 const int16_t *s = (int16_t *) src[0];
396 const int16_t * const send = s + count;
397 int32_t *d = dst[0] = dst[1] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
398 int scale = WORD_SHIFT;
400 while (s < send)
402 *d++ = *s++ << scale;
405 src[0] = (char *)s;
408 /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */
409 static void sample_input_lte_native_i_stereo(
410 int count, const char *src[], int32_t *dst[])
412 const int32_t *s = (int32_t *) src[0];
413 const int32_t * const send = s + count;
414 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
415 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
416 int scale = WORD_SHIFT;
418 while (s < send)
420 int32_t slr = *s++;
421 #ifdef ROCKBOX_LITTLE_ENDIAN
422 *dl++ = (slr >> 16) << scale;
423 *dr++ = (int32_t)(int16_t)slr << scale;
424 #else /* ROCKBOX_BIG_ENDIAN */
425 *dl++ = (int32_t)(int16_t)slr << scale;
426 *dr++ = (slr >> 16) << scale;
427 #endif
430 src[0] = (char *)s;
433 /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */
434 static void sample_input_lte_native_ni_stereo(
435 int count, const char *src[], int32_t *dst[])
437 const int16_t *sl = (int16_t *) src[0];
438 const int16_t *sr = (int16_t *) src[1];
439 const int16_t * const slend = sl + count;
440 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
441 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
442 int scale = WORD_SHIFT;
444 while (sl < slend)
446 *dl++ = *sl++ << scale;
447 *dr++ = *sr++ << scale;
450 src[0] = (char *)sl;
451 src[1] = (char *)sr;
454 /* convert count 32-bit mono to 32-bit mono */
455 static void sample_input_gt_native_mono(
456 int count, const char *src[], int32_t *dst[])
458 dst[0] = dst[1] = (int32_t *)src[0];
459 src[0] = (char *)(dst[0] + count);
462 /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */
463 static void sample_input_gt_native_i_stereo(
464 int count, const char *src[], int32_t *dst[])
466 const int32_t *s = (int32_t *)src[0];
467 const int32_t * const send = s + 2*count;
468 int32_t *dl = dst[0] = &sample_buf[SAMPLE_BUF_LEFT_CHANNEL];
469 int32_t *dr = dst[1] = &sample_buf[SAMPLE_BUF_RIGHT_CHANNEL];
471 while (s < send)
473 *dl++ = *s++;
474 *dr++ = *s++;
477 src[0] = (char *)send;
480 /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */
481 static void sample_input_gt_native_ni_stereo(
482 int count, const char *src[], int32_t *dst[])
484 dst[0] = (int32_t *)src[0];
485 dst[1] = (int32_t *)src[1];
486 src[0] = (char *)(dst[0] + count);
487 src[1] = (char *)(dst[1] + count);
491 * sample_input_new_format()
493 * set the to-native sample conversion function based on dsp sample parameters
495 * !DSPPARAMSYNC
496 * needs syncing with changes to the following dsp parameters:
497 * * dsp->stereo_mode (A/V)
498 * * dsp->sample_depth (A/V)
500 static void sample_input_new_format(struct dsp_config *dsp)
502 static const sample_input_fn_type sample_input_functions[] =
504 [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo,
505 [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo,
506 [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono,
507 [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo,
508 [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo,
509 [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono,
512 int convert = dsp->stereo_mode;
514 if (dsp->sample_depth > NATIVE_DEPTH)
515 convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX;
517 dsp->input_samples = sample_input_functions[convert];
521 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO
522 /* write mono internal format to output format */
523 static void sample_output_mono(int count, struct dsp_data *data,
524 const int32_t *src[], int16_t *dst)
526 const int32_t *s0 = src[0];
527 const int scale = data->output_scale;
528 const int dc_bias = 1 << (scale - 1);
530 while (count-- > 0)
532 int32_t lr = clip_sample_16((*s0++ + dc_bias) >> scale);
533 *dst++ = lr;
534 *dst++ = lr;
537 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */
539 /* write stereo internal format to output format */
540 #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO
541 static void sample_output_stereo(int count, struct dsp_data *data,
542 const int32_t *src[], int16_t *dst)
544 const int32_t *s0 = src[0];
545 const int32_t *s1 = src[1];
546 const int scale = data->output_scale;
547 const int dc_bias = 1 << (scale - 1);
549 while (count-- > 0)
551 *dst++ = clip_sample_16((*s0++ + dc_bias) >> scale);
552 *dst++ = clip_sample_16((*s1++ + dc_bias) >> scale);
555 #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */
558 * The "dither" code to convert the 24-bit samples produced by libmad was
559 * taken from the coolplayer project - coolplayer.sourceforge.net
561 * This function handles mono and stereo outputs.
563 static void sample_output_dithered(int count, struct dsp_data *data,
564 const int32_t *src[], int16_t *dst)
566 const int32_t mask = dither_mask;
567 const int32_t bias = dither_bias;
568 const int scale = data->output_scale;
569 const int32_t min = data->clip_min;
570 const int32_t max = data->clip_max;
571 const int32_t range = max - min;
572 int ch;
573 int16_t *d;
575 for (ch = 0; ch < data->num_channels; ch++)
577 struct dither_data * const dither = &dither_data[ch];
578 const int32_t *s = src[ch];
579 int i;
581 for (i = 0, d = &dst[ch]; i < count; i++, s++, d += 2)
583 int32_t output, sample;
584 int32_t random;
586 /* Noise shape and bias (for correct rounding later) */
587 sample = *s;
588 sample += dither->error[0] - dither->error[1] + dither->error[2];
589 dither->error[2] = dither->error[1];
590 dither->error[1] = dither->error[0]/2;
592 output = sample + bias;
594 /* Dither, highpass triangle PDF */
595 random = dither->random*0x0019660dL + 0x3c6ef35fL;
596 output += (random & mask) - (dither->random & mask);
597 dither->random = random;
599 /* Round sample to output range */
600 output &= ~mask;
602 /* Error feedback */
603 dither->error[0] = sample - output;
605 /* Clip */
606 if ((uint32_t)(output - min) > (uint32_t)range)
608 int32_t c = min;
609 if (output > min)
610 c += range;
611 output = c;
614 /* Quantize and store */
615 *d = output >> scale;
619 if (data->num_channels == 2)
620 return;
622 /* Have to duplicate left samples into the right channel since
623 pcm buffer and hardware is interleaved stereo */
624 d = &dst[0];
626 while (count-- > 0)
628 int16_t s = *d++;
629 *d++ = s;
634 * sample_output_new_format()
636 * set the from-native to ouput sample conversion routine
638 * !DSPPARAMSYNC
639 * needs syncing with changes to the following dsp parameters:
640 * * dsp->stereo_mode (A/V)
641 * * dither_enabled (A)
643 static void sample_output_new_format(struct dsp_config *dsp)
645 static const sample_output_fn_type sample_output_functions[] =
647 sample_output_mono,
648 sample_output_stereo,
649 sample_output_dithered,
650 sample_output_dithered
653 int out = dsp->data.num_channels - 1;
655 if (dsp == &AUDIO_DSP && dither_enabled)
656 out += 2;
658 dsp->output_samples = sample_output_functions[out];
662 * Linear interpolation resampling that introduces a one sample delay because
663 * of our inability to look into the future at the end of a frame.
665 #ifndef DSP_HAVE_ASM_RESAMPLING
666 static int dsp_downsample(int count, struct dsp_data *data,
667 const int32_t *src[], int32_t *dst[])
669 int ch = data->num_channels - 1;
670 uint32_t delta = data->resample_data.delta;
671 uint32_t phase, pos;
672 int32_t *d;
674 /* Rolled channel loop actually showed slightly faster. */
677 /* Just initialize things and not worry too much about the relatively
678 * uncommon case of not being able to spit out a sample for the frame.
680 const int32_t *s = src[ch];
681 int32_t last = data->resample_data.last_sample[ch];
683 data->resample_data.last_sample[ch] = s[count - 1];
684 d = dst[ch];
685 phase = data->resample_data.phase;
686 pos = phase >> 16;
688 /* Do we need last sample of previous frame for interpolation? */
689 if (pos > 0)
690 last = s[pos - 1];
692 while (pos < (uint32_t)count)
694 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
695 phase += delta;
696 pos = phase >> 16;
697 last = s[pos - 1];
700 while (--ch >= 0);
702 /* Wrap phase accumulator back to start of next frame. */
703 data->resample_data.phase = phase - (count << 16);
704 return d - dst[0];
707 static int dsp_upsample(int count, struct dsp_data *data,
708 const int32_t *src[], int32_t *dst[])
710 int ch = data->num_channels - 1;
711 uint32_t delta = data->resample_data.delta;
712 uint32_t phase, pos;
713 int32_t *d;
715 /* Rolled channel loop actually showed slightly faster. */
718 /* Should always be able to output a sample for a ratio up to RESAMPLE_RATIO */
719 const int32_t *s = src[ch];
720 int32_t last = data->resample_data.last_sample[ch];
722 data->resample_data.last_sample[ch] = s[count - 1];
723 d = dst[ch];
724 phase = data->resample_data.phase;
725 pos = phase >> 16;
727 while (pos == 0)
729 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[0] - last);
730 phase += delta;
731 pos = phase >> 16;
734 while (pos < (uint32_t)count)
736 last = s[pos - 1];
737 *d++ = last + FRACMUL((phase & 0xffff) << 15, s[pos] - last);
738 phase += delta;
739 pos = phase >> 16;
742 while (--ch >= 0);
744 /* Wrap phase accumulator back to start of next frame. */
745 data->resample_data.phase = phase & 0xffff;
746 return d - dst[0];
748 #endif /* DSP_HAVE_ASM_RESAMPLING */
750 static void resampler_new_delta(struct dsp_config *dsp)
752 dsp->data.resample_data.delta = (unsigned long)
753 dsp->frequency * 65536LL / NATIVE_FREQUENCY;
755 if (dsp->frequency == NATIVE_FREQUENCY)
757 /* NOTE: If fully glitch-free transistions from no resampling to
758 resampling are desired, last_sample history should be maintained
759 even when not resampling. */
760 dsp->resample = NULL;
761 dsp->data.resample_data.phase = 0;
762 dsp->data.resample_data.last_sample[0] = 0;
763 dsp->data.resample_data.last_sample[1] = 0;
765 else if (dsp->frequency < NATIVE_FREQUENCY)
766 dsp->resample = dsp_upsample;
767 else
768 dsp->resample = dsp_downsample;
771 /* Resample count stereo samples. Updates the src array, if resampling is
772 * done, to refer to the resampled data. Returns number of stereo samples
773 * for further processing.
775 static inline int resample(struct dsp_config *dsp, int count, int32_t *src[])
777 int32_t *dst[2] =
779 &resample_buf[RESAMPLE_BUF_LEFT_CHANNEL],
780 &resample_buf[RESAMPLE_BUF_RIGHT_CHANNEL],
783 count = dsp->resample(count, &dsp->data, (const int32_t **)src, dst);
785 src[0] = dst[0];
786 src[1] = dst[dsp->data.num_channels - 1];
788 return count;
791 static void dither_init(struct dsp_config *dsp)
793 memset(dither_data, 0, sizeof (dither_data));
794 dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH));
795 dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1;
798 void dsp_dither_enable(bool enable)
800 struct dsp_config *dsp = &AUDIO_DSP;
801 dither_enabled = enable;
802 sample_output_new_format(dsp);
805 /* Applies crossfeed to the stereo signal in src.
806 * Crossfeed is a process where listening over speakers is simulated. This
807 * is good for old hard panned stereo records, which might be quite fatiguing
808 * to listen to on headphones with no crossfeed.
810 #ifndef DSP_HAVE_ASM_CROSSFEED
811 static void apply_crossfeed(int count, int32_t *buf[])
813 int32_t *hist_l = &crossfeed_data.history[0];
814 int32_t *hist_r = &crossfeed_data.history[2];
815 int32_t *delay = &crossfeed_data.delay[0][0];
816 int32_t *coefs = &crossfeed_data.coefs[0];
817 int32_t gain = crossfeed_data.gain;
818 int32_t *di = crossfeed_data.index;
820 int32_t acc;
821 int32_t left, right;
822 int i;
824 for (i = 0; i < count; i++)
826 left = buf[0][i];
827 right = buf[1][i];
829 /* Filter delayed sample from left speaker */
830 acc = FRACMUL(*di, coefs[0]);
831 acc += FRACMUL(hist_l[0], coefs[1]);
832 acc += FRACMUL(hist_l[1], coefs[2]);
833 /* Save filter history for left speaker */
834 hist_l[1] = acc;
835 hist_l[0] = *di;
836 *di++ = left;
837 /* Filter delayed sample from right speaker */
838 acc = FRACMUL(*di, coefs[0]);
839 acc += FRACMUL(hist_r[0], coefs[1]);
840 acc += FRACMUL(hist_r[1], coefs[2]);
841 /* Save filter history for right speaker */
842 hist_r[1] = acc;
843 hist_r[0] = *di;
844 *di++ = right;
845 /* Now add the attenuated direct sound and write to outputs */
846 buf[0][i] = FRACMUL(left, gain) + hist_r[1];
847 buf[1][i] = FRACMUL(right, gain) + hist_l[1];
849 /* Wrap delay line index if bigger than delay line size */
850 if (di >= delay + 13*2)
851 di = delay;
853 /* Write back local copies of data we've modified */
854 crossfeed_data.index = di;
856 #endif /* DSP_HAVE_ASM_CROSSFEED */
859 * dsp_set_crossfeed(bool enable)
861 * !DSPPARAMSYNC
862 * needs syncing with changes to the following dsp parameters:
863 * * dsp->stereo_mode (A)
865 void dsp_set_crossfeed(bool enable)
867 crossfeed_enabled = enable;
868 AUDIO_DSP.apply_crossfeed = (enable && AUDIO_DSP.data.num_channels > 1)
869 ? apply_crossfeed : NULL;
872 void dsp_set_crossfeed_direct_gain(int gain)
874 crossfeed_data.gain = get_replaygain_int(gain * 10) << 7;
875 /* If gain is negative, the calculation overflowed and we need to clamp */
876 if (crossfeed_data.gain < 0)
877 crossfeed_data.gain = 0x7fffffff;
880 /* Both gains should be below 0 dB */
881 void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff)
883 int32_t *c = crossfeed_data.coefs;
884 long scaler = get_replaygain_int(lf_gain * 10) << 7;
886 cutoff = 0xffffffff/NATIVE_FREQUENCY*cutoff;
887 hf_gain -= lf_gain;
888 /* Divide cutoff by sqrt(10^(hf_gain/20)) to place cutoff at the -3 dB
889 * point instead of shelf midpoint. This is for compatibility with the old
890 * crossfeed shelf filter and should be removed if crossfeed settings are
891 * ever made incompatible for any other good reason.
893 cutoff = fp_div(cutoff, get_replaygain_int(hf_gain*5), 24);
894 filter_shelf_coefs(cutoff, hf_gain, false, c);
895 /* Scale coefs by LF gain and shift them to s0.31 format. We have no gains
896 * over 1 and can do this safely
898 c[0] = FRACMUL_SHL(c[0], scaler, 4);
899 c[1] = FRACMUL_SHL(c[1], scaler, 4);
900 c[2] <<= 4;
903 /* Apply a constant gain to the samples (e.g., for ReplayGain).
904 * Note that this must be called before the resampler.
906 #ifndef DSP_HAVE_ASM_APPLY_GAIN
907 static void dsp_apply_gain(int count, struct dsp_data *data, int32_t *buf[])
909 const int32_t gain = data->gain;
910 int ch;
912 for (ch = 0; ch < data->num_channels; ch++)
914 int32_t *d = buf[ch];
915 int i;
917 for (i = 0; i < count; i++)
918 d[i] = FRACMUL_SHL(d[i], gain, 8);
921 #endif /* DSP_HAVE_ASM_APPLY_GAIN */
923 /* Combine all gains to a global gain. */
924 static void set_gain(struct dsp_config *dsp)
926 /* gains are in S7.24 format */
927 dsp->data.gain = DEFAULT_GAIN;
929 /* Replay gain not relevant to voice */
930 if (dsp == &AUDIO_DSP && replaygain)
932 dsp->data.gain = replaygain;
935 if (dsp->eq_process && eq_precut)
937 dsp->data.gain = fp_mul(dsp->data.gain, eq_precut, 24);
940 #ifdef HAVE_SW_VOLUME_CONTROL
941 if (global_settings.volume < SW_VOLUME_MAX ||
942 global_settings.volume > SW_VOLUME_MIN)
944 int vol_gain = get_replaygain_int(global_settings.volume * 100);
945 dsp->data.gain = (long) (((int64_t) dsp->data.gain * vol_gain) >> 24);
947 #endif
949 if (dsp->data.gain == DEFAULT_GAIN)
951 dsp->data.gain = 0;
953 else
955 dsp->data.gain >>= 1; /* convert gain to S8.23 format */
958 dsp->apply_gain = dsp->data.gain != 0 ? dsp_apply_gain : NULL;
962 * Update the amount to cut the audio before applying the equalizer.
964 * @param precut to apply in decibels (multiplied by 10)
966 void dsp_set_eq_precut(int precut)
968 eq_precut = get_replaygain_int(precut * -10);
969 set_gain(&AUDIO_DSP);
973 * Synchronize the equalizer filter coefficients with the global settings.
975 * @param band the equalizer band to synchronize
977 void dsp_set_eq_coefs(int band)
979 const int *setting;
980 long gain;
981 unsigned long cutoff, q;
983 /* Adjust setting pointer to the band we actually want to change */
984 setting = &global_settings.eq_band0_cutoff + (band * 3);
986 /* Convert user settings to format required by coef generator functions */
987 cutoff = 0xffffffff / NATIVE_FREQUENCY * (*setting++);
988 q = *setting++;
989 gain = *setting++;
991 if (q == 0)
992 q = 1;
994 /* NOTE: The coef functions assume the EMAC unit is in fractional mode,
995 which it should be, since we're executed from the main thread. */
997 /* Assume a band is disabled if the gain is zero */
998 if (gain == 0)
1000 eq_data.enabled[band] = 0;
1002 else
1004 if (band == 0)
1005 eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1006 else if (band == 4)
1007 eq_hs_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1008 else
1009 eq_pk_coefs(cutoff, q, gain, eq_data.filters[band].coefs);
1011 eq_data.enabled[band] = 1;
1015 /* Apply EQ filters to those bands that have got it switched on. */
1016 static void eq_process(int count, int32_t *buf[])
1018 static const int shifts[] =
1020 EQ_SHELF_SHIFT, /* low shelf */
1021 EQ_PEAK_SHIFT, /* peaking */
1022 EQ_PEAK_SHIFT, /* peaking */
1023 EQ_PEAK_SHIFT, /* peaking */
1024 EQ_SHELF_SHIFT, /* high shelf */
1026 unsigned int channels = AUDIO_DSP.data.num_channels;
1027 int i;
1029 /* filter configuration currently is 1 low shelf filter, 3 band peaking
1030 filters and 1 high shelf filter, in that order. we need to know this
1031 so we can choose the correct shift factor.
1033 for (i = 0; i < 5; i++)
1035 if (!eq_data.enabled[i])
1036 continue;
1037 eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]);
1042 * Use to enable the equalizer.
1044 * @param enable true to enable the equalizer
1046 void dsp_set_eq(bool enable)
1048 AUDIO_DSP.eq_process = enable ? eq_process : NULL;
1049 set_gain(&AUDIO_DSP);
1052 static void dsp_set_stereo_width(int value)
1054 long width, straight, cross;
1056 width = value * 0x7fffff / 100;
1058 if (value <= 100)
1060 straight = (0x7fffff + width) / 2;
1061 cross = straight - width;
1063 else
1065 /* straight = (1 + width) / (2 * width) */
1066 straight = ((int64_t)(0x7fffff + width) << 22) / width;
1067 cross = straight - 0x7fffff;
1070 dsp_sw_gain = straight << 8;
1071 dsp_sw_cross = cross << 8;
1075 * Implements the different channel configurations and stereo width.
1078 /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for
1079 * completeness. */
1080 #if 0
1081 static void channels_process_sound_chan_stereo(int count, int32_t *buf[])
1083 /* The channels are each just themselves */
1084 (void)count; (void)buf;
1086 #endif
1088 #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO
1089 static void channels_process_sound_chan_mono(int count, int32_t *buf[])
1091 int32_t *sl = buf[0], *sr = buf[1];
1093 while (count-- > 0)
1095 int32_t lr = *sl/2 + *sr/2;
1096 *sl++ = lr;
1097 *sr++ = lr;
1100 #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */
1102 #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM
1103 static void channels_process_sound_chan_custom(int count, int32_t *buf[])
1105 const int32_t gain = dsp_sw_gain;
1106 const int32_t cross = dsp_sw_cross;
1107 int32_t *sl = buf[0], *sr = buf[1];
1109 while (count-- > 0)
1111 int32_t l = *sl;
1112 int32_t r = *sr;
1113 *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross);
1114 *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross);
1117 #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */
1119 static void channels_process_sound_chan_mono_left(int count, int32_t *buf[])
1121 /* Just copy over the other channel */
1122 memcpy(buf[1], buf[0], count * sizeof (*buf));
1125 static void channels_process_sound_chan_mono_right(int count, int32_t *buf[])
1127 /* Just copy over the other channel */
1128 memcpy(buf[0], buf[1], count * sizeof (*buf));
1131 #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE
1132 static void channels_process_sound_chan_karaoke(int count, int32_t *buf[])
1134 int32_t *sl = buf[0], *sr = buf[1];
1136 while (count-- > 0)
1138 int32_t ch = *sl/2 - *sr/2;
1139 *sl++ = ch;
1140 *sr++ = -ch;
1143 #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */
1145 static void dsp_set_channel_config(int value)
1147 static const channels_process_fn_type channels_process_functions[] =
1149 /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */
1150 [SOUND_CHAN_STEREO] = NULL,
1151 [SOUND_CHAN_MONO] = channels_process_sound_chan_mono,
1152 [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom,
1153 [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left,
1154 [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right,
1155 [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke,
1158 if ((unsigned)value >= ARRAYLEN(channels_process_functions) ||
1159 AUDIO_DSP.stereo_mode == STEREO_MONO)
1161 value = SOUND_CHAN_STEREO;
1164 /* This doesn't apply to voice */
1165 channels_mode = value;
1166 AUDIO_DSP.channels_process = channels_process_functions[value];
1169 #if CONFIG_CODEC == SWCODEC
1171 #ifdef HAVE_SW_TONE_CONTROLS
1172 static void set_tone_controls(void)
1174 filter_bishelf_coefs(0xffffffff/NATIVE_FREQUENCY*200,
1175 0xffffffff/NATIVE_FREQUENCY*3500,
1176 bass, treble, -prescale,
1177 AUDIO_DSP.tone_filter.coefs);
1178 /* Sync the voice dsp coefficients */
1179 memcpy(&VOICE_DSP.tone_filter.coefs, AUDIO_DSP.tone_filter.coefs,
1180 sizeof (VOICE_DSP.tone_filter.coefs));
1182 #endif
1184 /* Hook back from firmware/ part of audio, which can't/shouldn't call apps/
1185 * code directly.
1187 int dsp_callback(int msg, intptr_t param)
1189 switch (msg)
1191 #ifdef HAVE_SW_TONE_CONTROLS
1192 case DSP_CALLBACK_SET_PRESCALE:
1193 prescale = param;
1194 set_tone_controls();
1195 break;
1196 /* prescaler is always set after calling any of these, so we wait with
1197 * calculating coefs until the above case is hit.
1199 case DSP_CALLBACK_SET_BASS:
1200 bass = param;
1201 break;
1202 case DSP_CALLBACK_SET_TREBLE:
1203 treble = param;
1204 break;
1205 #ifdef HAVE_SW_VOLUME_CONTROL
1206 case DSP_CALLBACK_SET_SW_VOLUME:
1207 set_gain(&AUDIO_DSP);
1208 break;
1209 #endif
1210 #endif
1211 case DSP_CALLBACK_SET_CHANNEL_CONFIG:
1212 dsp_set_channel_config(param);
1213 break;
1214 case DSP_CALLBACK_SET_STEREO_WIDTH:
1215 dsp_set_stereo_width(param);
1216 break;
1217 default:
1218 break;
1220 return 0;
1222 #endif
1224 /* Process and convert src audio to dst based on the DSP configuration,
1225 * reading count number of audio samples. dst is assumed to be large
1226 * enough; use dsp_output_count() to get the required number. src is an
1227 * array of pointers; for mono and interleaved stereo, it contains one
1228 * pointer to the start of the audio data and the other is ignored; for
1229 * non-interleaved stereo, it contains two pointers, one for each audio
1230 * channel. Returns number of bytes written to dst.
1232 int dsp_process(struct dsp_config *dsp, char *dst, const char *src[], int count)
1234 static int32_t *tmp[2]; /* tdspeed_doit() needs it static */
1235 static long last_yield;
1236 long tick;
1237 int written = 0;
1239 #if defined(CPU_COLDFIRE)
1240 /* set emac unit for dsp processing, and save old macsr, we're running in
1241 codec thread context at this point, so can't clobber it */
1242 unsigned long old_macsr = coldfire_get_macsr();
1243 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
1244 #endif
1246 if (new_gain)
1247 dsp_set_replaygain(); /* Gain has changed */
1249 /* Perform at least one yield before starting */
1250 last_yield = current_tick;
1251 yield();
1253 /* Testing function pointers for NULL is preferred since the pointer
1254 will be preloaded to be used for the call if not. */
1255 while (count > 0)
1257 int samples = MIN(sample_buf_count/2, count);
1258 count -= samples;
1260 dsp->input_samples(samples, src, tmp);
1262 #ifdef HAVE_PITCHSCREEN
1263 if (dsp->tdspeed_active)
1264 samples = tdspeed_doit(tmp, samples);
1265 #endif
1267 int chunk_offset = 0;
1268 while (samples > 0)
1270 int32_t *t2[2];
1271 t2[0] = tmp[0]+chunk_offset;
1272 t2[1] = tmp[1]+chunk_offset;
1274 int chunk = MIN(sample_buf_count/2, samples);
1275 chunk_offset += chunk;
1276 samples -= chunk;
1278 if (dsp->apply_gain)
1279 dsp->apply_gain(chunk, &dsp->data, t2);
1281 if (dsp->resample && (chunk = resample(dsp, chunk, t2)) <= 0)
1282 break; /* I'm pretty sure we're downsampling here */
1284 if (dsp->apply_crossfeed)
1285 dsp->apply_crossfeed(chunk, t2);
1287 if (dsp->eq_process)
1288 dsp->eq_process(chunk, t2);
1290 #ifdef HAVE_SW_TONE_CONTROLS
1291 if ((bass | treble) != 0)
1292 eq_filter(t2, &dsp->tone_filter, chunk,
1293 dsp->data.num_channels, FILTER_BISHELF_SHIFT);
1294 #endif
1296 if (dsp->channels_process)
1297 dsp->channels_process(chunk, t2);
1299 if (dsp->compressor_process)
1300 dsp->compressor_process(chunk, t2);
1302 dsp->output_samples(chunk, &dsp->data, (const int32_t **)t2, (int16_t *)dst);
1304 written += chunk;
1305 dst += chunk * sizeof (int16_t) * 2;
1307 /* yield at least once each tick */
1308 tick = current_tick;
1309 if (TIME_AFTER(tick, last_yield))
1311 last_yield = tick;
1312 yield();
1317 #if defined(CPU_COLDFIRE)
1318 /* set old macsr again */
1319 coldfire_set_macsr(old_macsr);
1320 #endif
1321 return written;
1324 /* Given count number of input samples, calculate the maximum number of
1325 * samples of output data that would be generated (the calculation is not
1326 * entirely exact and rounds upwards to be on the safe side; during
1327 * resampling, the number of samples generated depends on the current state
1328 * of the resampler).
1330 /* dsp_input_size MUST be called afterwards */
1331 int dsp_output_count(struct dsp_config *dsp, int count)
1333 #ifdef HAVE_PITCHSCREEN
1334 if (dsp->tdspeed_active)
1335 count = tdspeed_est_output_size();
1336 #endif
1337 if (dsp->resample)
1339 count = (int)(((unsigned long)count * NATIVE_FREQUENCY
1340 + (dsp->frequency - 1)) / dsp->frequency);
1343 /* Now we have the resampled sample count which must not exceed
1344 * RESAMPLE_BUF_RIGHT_CHANNEL to avoid resample buffer overflow. One
1345 * must call dsp_input_count() to get the correct input sample
1346 * count.
1348 if (count > RESAMPLE_BUF_RIGHT_CHANNEL)
1349 count = RESAMPLE_BUF_RIGHT_CHANNEL;
1351 return count;
1354 /* Given count output samples, calculate number of input samples
1355 * that would be consumed in order to fill the output buffer.
1357 int dsp_input_count(struct dsp_config *dsp, int count)
1359 /* count is now the number of resampled input samples. Convert to
1360 original input samples. */
1361 if (dsp->resample)
1363 /* Use the real resampling delta =
1364 * dsp->frequency * 65536 / NATIVE_FREQUENCY, and
1365 * round towards zero to avoid buffer overflows. */
1366 count = (int)(((unsigned long)count *
1367 dsp->data.resample_data.delta) >> 16);
1370 #ifdef HAVE_PITCHSCREEN
1371 if (dsp->tdspeed_active)
1372 count = tdspeed_est_input_size(count);
1373 #endif
1375 return count;
1378 static void dsp_set_gain_var(long *var, long value)
1380 *var = value;
1381 new_gain = true;
1384 static void dsp_update_functions(struct dsp_config *dsp)
1386 sample_input_new_format(dsp);
1387 sample_output_new_format(dsp);
1388 if (dsp == &AUDIO_DSP)
1389 dsp_set_crossfeed(crossfeed_enabled);
1392 intptr_t dsp_configure(struct dsp_config *dsp, int setting, intptr_t value)
1394 switch (setting)
1396 case DSP_MYDSP:
1397 switch (value)
1399 case CODEC_IDX_AUDIO:
1400 return (intptr_t)&AUDIO_DSP;
1401 case CODEC_IDX_VOICE:
1402 return (intptr_t)&VOICE_DSP;
1403 default:
1404 return (intptr_t)NULL;
1407 case DSP_SET_FREQUENCY:
1408 memset(&dsp->data.resample_data, 0, sizeof (dsp->data.resample_data));
1409 /* Fall through!!! */
1410 case DSP_SWITCH_FREQUENCY:
1411 dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value;
1412 /* Account for playback speed adjustment when setting dsp->frequency
1413 if we're called from the main audio thread. Voice UI thread should
1414 not need this feature.
1416 #ifdef HAVE_PITCHSCREEN
1417 if (dsp == &AUDIO_DSP)
1418 dsp->frequency = pitch_ratio * dsp->codec_frequency / PITCH_SPEED_100;
1419 else
1420 #endif
1421 dsp->frequency = dsp->codec_frequency;
1423 resampler_new_delta(dsp);
1424 #ifdef HAVE_PITCHSCREEN
1425 tdspeed_setup(dsp);
1426 #endif
1427 break;
1429 case DSP_SET_SAMPLE_DEPTH:
1430 dsp->sample_depth = value;
1432 if (dsp->sample_depth <= NATIVE_DEPTH)
1434 dsp->frac_bits = WORD_FRACBITS;
1435 dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */
1436 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1437 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1439 else
1441 dsp->frac_bits = value;
1442 dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */
1443 dsp->data.clip_max = (1 << value) - 1;
1444 dsp->data.clip_min = -(1 << value);
1447 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1448 sample_input_new_format(dsp);
1449 dither_init(dsp);
1450 break;
1452 case DSP_SET_STEREO_MODE:
1453 dsp->stereo_mode = value;
1454 dsp->data.num_channels = value == STEREO_MONO ? 1 : 2;
1455 dsp_update_functions(dsp);
1456 #ifdef HAVE_PITCHSCREEN
1457 tdspeed_setup(dsp);
1458 #endif
1459 break;
1461 case DSP_RESET:
1462 dsp->stereo_mode = STEREO_NONINTERLEAVED;
1463 dsp->data.num_channels = 2;
1464 dsp->sample_depth = NATIVE_DEPTH;
1465 dsp->frac_bits = WORD_FRACBITS;
1466 dsp->sample_bytes = sizeof (int16_t);
1467 dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH;
1468 dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1);
1469 dsp->data.clip_min = -((1 << WORD_FRACBITS));
1470 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
1472 if (dsp == &AUDIO_DSP)
1474 track_gain = 0;
1475 album_gain = 0;
1476 track_peak = 0;
1477 album_peak = 0;
1478 new_gain = true;
1481 dsp_update_functions(dsp);
1482 resampler_new_delta(dsp);
1483 #ifdef HAVE_PITCHSCREEN
1484 tdspeed_setup(dsp);
1485 #endif
1486 if (dsp == &AUDIO_DSP)
1487 release_gain = UNITY;
1488 break;
1490 case DSP_FLUSH:
1491 memset(&dsp->data.resample_data, 0,
1492 sizeof (dsp->data.resample_data));
1493 resampler_new_delta(dsp);
1494 dither_init(dsp);
1495 #ifdef HAVE_PITCHSCREEN
1496 tdspeed_setup(dsp);
1497 #endif
1498 if (dsp == &AUDIO_DSP)
1499 release_gain = UNITY;
1500 break;
1502 case DSP_SET_TRACK_GAIN:
1503 if (dsp == &AUDIO_DSP)
1504 dsp_set_gain_var(&track_gain, value);
1505 break;
1507 case DSP_SET_ALBUM_GAIN:
1508 if (dsp == &AUDIO_DSP)
1509 dsp_set_gain_var(&album_gain, value);
1510 break;
1512 case DSP_SET_TRACK_PEAK:
1513 if (dsp == &AUDIO_DSP)
1514 dsp_set_gain_var(&track_peak, value);
1515 break;
1517 case DSP_SET_ALBUM_PEAK:
1518 if (dsp == &AUDIO_DSP)
1519 dsp_set_gain_var(&album_peak, value);
1520 break;
1522 default:
1523 return 0;
1526 return 1;
1529 int get_replaygain_mode(bool have_track_gain, bool have_album_gain)
1531 int type;
1533 bool track = ((global_settings.replaygain_type == REPLAYGAIN_TRACK)
1534 || ((global_settings.replaygain_type == REPLAYGAIN_SHUFFLE)
1535 && global_settings.playlist_shuffle));
1537 type = (!track && have_album_gain) ? REPLAYGAIN_ALBUM
1538 : have_track_gain ? REPLAYGAIN_TRACK : -1;
1540 return type;
1543 void dsp_set_replaygain(void)
1545 long gain = 0;
1547 new_gain = false;
1549 if ((global_settings.replaygain_type != REPLAYGAIN_OFF) ||
1550 global_settings.replaygain_noclip)
1552 bool track_mode = get_replaygain_mode(track_gain != 0,
1553 album_gain != 0) == REPLAYGAIN_TRACK;
1554 long peak = (track_mode || !album_peak) ? track_peak : album_peak;
1556 if (global_settings.replaygain_type != REPLAYGAIN_OFF)
1558 gain = (track_mode || !album_gain) ? track_gain : album_gain;
1560 if (global_settings.replaygain_preamp)
1562 long preamp = get_replaygain_int(
1563 global_settings.replaygain_preamp * 10);
1565 gain = (long) (((int64_t) gain * preamp) >> 24);
1569 if (gain == 0)
1571 /* So that noclip can work even with no gain information. */
1572 gain = DEFAULT_GAIN;
1575 if (global_settings.replaygain_noclip && (peak != 0)
1576 && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN))
1578 gain = (((int64_t) DEFAULT_GAIN << 24) / peak);
1581 if (gain == DEFAULT_GAIN)
1583 /* Nothing to do, disable processing. */
1584 gain = 0;
1588 /* Store in S7.24 format to simplify calculations. */
1589 replaygain = gain;
1590 set_gain(&AUDIO_DSP);
1593 /** SET COMPRESSOR
1594 * Called by the menu system to configure the compressor process */
1595 void dsp_set_compressor(int c_threshold, int c_gain, int c_ratio,
1596 int c_knee, int c_release)
1598 bool changed = false;
1599 bool active = (c_threshold < 0);
1600 bool new_auto_gain = (c_gain == 1);
1601 const int comp_ratio[] = {2, 4, 6, 10, 0};
1602 int new_ratio = comp_ratio[c_ratio];
1603 bool new_knee = (c_knee == 1);
1604 int new_release = c_release * NATIVE_FREQUENCY / 1000;
1606 if (c_menu.threshold != c_threshold)
1608 changed = true;
1609 c_menu.threshold = c_threshold;
1610 logf(" Compressor Threshold: %d dB\tEnabled: %s",
1611 c_menu.threshold, active ? "Yes" : "No");
1614 if (c_menu.auto_gain != new_auto_gain)
1616 changed = true;
1617 c_menu.auto_gain = new_auto_gain;
1618 logf(" Compressor Makeup Gain: %s",
1619 c_menu.auto_gain ? "Auto" : "Off");
1622 if (c_menu.ratio != new_ratio)
1624 changed = true;
1625 c_menu.ratio = new_ratio;
1626 if (c_menu.ratio)
1627 { logf(" Compressor Ratio: %d:1", c_menu.ratio); }
1628 else
1629 { logf(" Compressor Ratio: Limit"); }
1632 if (c_menu.soft_knee != new_knee)
1634 changed = true;
1635 c_menu.soft_knee = new_knee;
1636 logf(" Compressor Knee: %s", c_menu.soft_knee==1?"Soft":"Hard");
1639 if (c_menu.release != new_release)
1641 changed = true;
1642 c_menu.release = new_release;
1643 logf(" Compressor Release: %d", c_menu.release);
1646 if (changed && active)
1648 /* configure variables for compressor operation */
1649 int i;
1650 const int32_t db[] ={0x000000, /* positive db equivalents in S15.16 format */
1651 0x241FA4, 0x1E1A5E, 0x1A94C8, 0x181518, 0x1624EA, 0x148F82, 0x1338BD, 0x120FD2,
1652 0x1109EB, 0x101FA4, 0x0F4BB6, 0x0E8A3C, 0x0DD840, 0x0D3377, 0x0C9A0E, 0x0C0A8C,
1653 0x0B83BE, 0x0B04A5, 0x0A8C6C, 0x0A1A5E, 0x09ADE1, 0x094670, 0x08E398, 0x0884F6,
1654 0x082A30, 0x07D2FA, 0x077F0F, 0x072E31, 0x06E02A, 0x0694C8, 0x064BDF, 0x060546,
1655 0x05C0DA, 0x057E78, 0x053E03, 0x04FF5F, 0x04C273, 0x048726, 0x044D64, 0x041518,
1656 0x03DE30, 0x03A89B, 0x037448, 0x03412A, 0x030F32, 0x02DE52, 0x02AE80, 0x027FB0,
1657 0x0251D6, 0x0224EA, 0x01F8E2, 0x01CDB4, 0x01A359, 0x0179C9, 0x0150FC, 0x0128EB,
1658 0x010190, 0x00DAE4, 0x00B4E1, 0x008F82, 0x006AC1, 0x004699, 0x002305};
1660 struct curve_point
1662 int32_t db; /* S15.16 format */
1663 int32_t offset; /* S15.16 format */
1664 } db_curve[5];
1666 /** Set up the shape of the compression curve first as decibel values*/
1667 /* db_curve[0] = bottom of knee
1668 [1] = threshold
1669 [2] = top of knee
1670 [3] = 0 db input
1671 [4] = ~+12db input (2 bits clipping overhead) */
1673 db_curve[1].db = c_menu.threshold << 16;
1674 if (c_menu.soft_knee)
1676 /* bottom of knee is 3dB below the threshold for soft knee*/
1677 db_curve[0].db = db_curve[1].db - (3 << 16);
1678 /* top of knee is 3dB above the threshold for soft knee */
1679 db_curve[2].db = db_curve[1].db + (3 << 16);
1680 if (c_menu.ratio)
1681 /* offset = -3db * (ratio - 1) / ratio */
1682 db_curve[2].offset = (int32_t)((long long)(-3 << 16)
1683 * (c_menu.ratio - 1) / c_menu.ratio);
1684 else
1685 /* offset = -3db for hard limit */
1686 db_curve[2].offset = (-3 << 16);
1688 else
1690 /* bottom of knee is at the threshold for hard knee */
1691 db_curve[0].db = c_menu.threshold << 16;
1692 /* top of knee is at the threshold for hard knee */
1693 db_curve[2].db = c_menu.threshold << 16;
1694 db_curve[2].offset = 0;
1697 /* Calculate 0db and ~+12db offsets */
1698 db_curve[4].db = 0xC0A8C; /* db of 2 bits clipping */
1699 if (c_menu.ratio)
1701 /* offset = threshold * (ratio - 1) / ratio */
1702 db_curve[3].offset = (int32_t)((long long)(c_menu.threshold << 16)
1703 * (c_menu.ratio - 1) / c_menu.ratio);
1704 db_curve[4].offset = (int32_t)((long long)-db_curve[4].db
1705 * (c_menu.ratio - 1) / c_menu.ratio) + db_curve[3].offset;
1707 else
1709 /* offset = threshold for hard limit */
1710 db_curve[3].offset = (c_menu.threshold << 16);
1711 db_curve[4].offset = -db_curve[4].db + db_curve[3].offset;
1714 /** Now set up the comp_curve table with compression offsets in the form
1715 of gain factors in S7.24 format */
1716 /* comp_curve[0] is 0 (-infinity db) input */
1717 comp_curve[0] = UNITY;
1718 /* comp_curve[1 to 63] are intermediate compression values corresponding
1719 to the 6 MSB of the input values of a non-clipped signal */
1720 for (i = 1; i < 64; i++)
1722 /* db constants are stored as positive numbers;
1723 make them negative here */
1724 int32_t this_db = -db[i];
1726 /* no compression below the knee */
1727 if (this_db <= db_curve[0].db)
1728 comp_curve[i] = UNITY;
1730 /* if soft knee and below top of knee,
1731 interpolate along soft knee slope */
1732 else if (c_menu.soft_knee && (this_db <= db_curve[2].db))
1733 comp_curve[i] = fp_factor(fp_mul(
1734 ((this_db - db_curve[0].db) / 6),
1735 db_curve[2].offset, 16), 16) << 8;
1737 /* interpolate along ratio slope above the knee */
1738 else
1739 comp_curve[i] = fp_factor(fp_mul(
1740 fp_div((db_curve[1].db - this_db), db_curve[1].db, 16),
1741 db_curve[3].offset, 16), 16) << 8;
1743 /* comp_curve[64] is the compression level of a maximum level,
1744 non-clipped signal */
1745 comp_curve[64] = fp_factor(db_curve[3].offset, 16) << 8;
1747 /* comp_curve[65] is the compression level of a maximum level,
1748 clipped signal */
1749 comp_curve[65] = fp_factor(db_curve[4].offset, 16) << 8;
1751 #if defined(ROCKBOX_HAS_LOGF) && defined(LOGF_ENABLE)
1752 logf("\n *** Compression Offsets ***");
1753 /* some settings for display only, not used in calculations */
1754 db_curve[0].offset = 0;
1755 db_curve[1].offset = 0;
1756 db_curve[3].db = 0;
1758 for (i = 0; i <= 4; i++)
1760 logf("Curve[%d]: db: % 6.2f\toffset: % 6.2f", i,
1761 (float)db_curve[i].db / (1 << 16),
1762 (float)db_curve[i].offset / (1 << 16));
1765 logf("\nGain factors:");
1766 for (i = 1; i <= 65; i++)
1768 debugf("%02d: %.6f ", i, (float)comp_curve[i] / UNITY);
1769 if (i % 4 == 0) debugf("\n");
1771 debugf("\n");
1772 #endif
1774 /* if using auto peak, then makeup gain is max offset - .1dB headroom */
1775 comp_makeup_gain = c_menu.auto_gain ?
1776 fp_factor(-(db_curve[3].offset) - 0x199A, 16) << 8 : UNITY;
1777 logf("Makeup gain:\t%.6f", (float)comp_makeup_gain / UNITY);
1779 /* calculate per-sample gain change a rate of 10db over release time */
1780 comp_rel_slope = 0xAF0BB2 / c_menu.release;
1781 logf("Release slope:\t%.6f", (float)comp_rel_slope / UNITY);
1783 release_gain = UNITY;
1786 /* enable/disable the compressor */
1787 AUDIO_DSP.compressor_process = active ? compressor_process : NULL;
1790 /** GET COMPRESSION GAIN
1791 * Returns the required gain factor in S7.24 format in order to compress the
1792 * sample in accordance with the compression curve. Always 1 or less.
1794 static inline int32_t get_compression_gain(int32_t sample)
1796 const int frac_bits_offset = AUDIO_DSP.frac_bits - 15;
1798 /* sample must be positive */
1799 if (sample < 0)
1800 sample = -(sample + 1);
1802 /* shift sample into 15 frac bit range */
1803 if (frac_bits_offset > 0)
1804 sample >>= frac_bits_offset;
1805 if (frac_bits_offset < 0)
1806 sample <<= -frac_bits_offset;
1808 /* normal case: sample isn't clipped */
1809 if (sample < (1 << 15))
1811 /* index is 6 MSB, rem is 9 LSB */
1812 int index = sample >> 9;
1813 int32_t rem = (sample & 0x1FF) << 22;
1815 /* interpolate from the compression curve:
1816 higher gain - ((rem / (1 << 31)) * (higher gain - lower gain)) */
1817 return comp_curve[index] - (FRACMUL(rem,
1818 (comp_curve[index] - comp_curve[index + 1])));
1820 /* sample is somewhat clipped, up to 2 bits of overhead */
1821 if (sample < (1 << 17))
1823 /* straight interpolation:
1824 higher gain - ((clipped portion of sample * 4/3
1825 / (1 << 31)) * (higher gain - lower gain)) */
1826 return comp_curve[64] - (FRACMUL(((sample - (1 << 15)) / 3) << 16,
1827 (comp_curve[64] - comp_curve[65])));
1830 /* sample is too clipped, return invalid value */
1831 return -1;
1834 /** COMPRESSOR PROCESS
1835 * Changes the gain of the samples according to the compressor curve
1837 static void compressor_process(int count, int32_t *buf[])
1839 const int num_chan = AUDIO_DSP.data.num_channels;
1840 int32_t *in_buf[2] = {buf[0], buf[1]};
1842 while (count-- > 0)
1844 int ch;
1845 /* use lowest (most compressed) gain factor of the output buffer
1846 sample pair for both samples (mono is also handled correctly here) */
1847 int32_t sample_gain = UNITY;
1848 for (ch = 0; ch < num_chan; ch++)
1850 int32_t this_gain = get_compression_gain(*in_buf[ch]);
1851 if (this_gain < sample_gain)
1852 sample_gain = this_gain;
1855 /* perform release slope; skip if no compression and no release slope */
1856 if ((sample_gain != UNITY) || (release_gain != UNITY))
1858 /* if larger offset than previous slope, start new release slope */
1859 if ((sample_gain <= release_gain) && (sample_gain > 0))
1861 release_gain = sample_gain;
1863 else
1864 /* keep sloping towards unity gain (and ignore invalid value) */
1866 release_gain += comp_rel_slope;
1867 if (release_gain > UNITY)
1869 release_gain = UNITY;
1874 /* total gain factor is the product of release gain and makeup gain,
1875 but avoid computation if possible */
1876 int32_t total_gain = ((release_gain == UNITY) ? comp_makeup_gain :
1877 (comp_makeup_gain == UNITY) ? release_gain :
1878 FRACMUL_SHL(release_gain, comp_makeup_gain, 7));
1880 /* Implement the compressor: apply total gain factor (if any) to the
1881 output buffer sample pair/mono sample */
1882 if (total_gain != UNITY)
1884 for (ch = 0; ch < num_chan; ch++)
1886 *in_buf[ch] = FRACMUL_SHL(total_gain, *in_buf[ch], 7);
1889 in_buf[0]++;
1890 in_buf[1]++;