diff options
Diffstat (limited to 'apps/dsp.c')
-rw-r--r-- | apps/dsp.c | 1106 |
1 files changed, 673 insertions, 433 deletions
diff --git a/apps/dsp.c b/apps/dsp.c index 577910acec..0ffaaea8d8 100644 --- a/apps/dsp.c +++ b/apps/dsp.c | |||
@@ -31,10 +31,6 @@ | |||
31 | #include "misc.h" | 31 | #include "misc.h" |
32 | #include "debug.h" | 32 | #include "debug.h" |
33 | 33 | ||
34 | #ifndef SIMULATOR | ||
35 | #include <dsp_asm.h> | ||
36 | #endif | ||
37 | |||
38 | /* 16-bit samples are scaled based on these constants. The shift should be | 34 | /* 16-bit samples are scaled based on these constants. The shift should be |
39 | * no more than 15. | 35 | * no more than 15. |
40 | */ | 36 | */ |
@@ -46,87 +42,155 @@ | |||
46 | #define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ | 42 | #define RESAMPLE_BUF_COUNT (256 * 4) /* Enough for 11,025 Hz -> 44,100 Hz*/ |
47 | #define DEFAULT_GAIN 0x01000000 | 43 | #define DEFAULT_GAIN 0x01000000 |
48 | 44 | ||
49 | 45 | /* enums to index conversion properly with stereo mode and other settings */ | |
50 | enum | 46 | enum |
51 | { | 47 | { |
52 | CONVERT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED, | 48 | SAMPLE_INPUT_LE_NATIVE_I_STEREO = STEREO_INTERLEAVED, |
53 | CONVERT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED, | 49 | SAMPLE_INPUT_LE_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED, |
54 | CONVERT_LE_NATIVE_MONO = STEREO_MONO, | 50 | SAMPLE_INPUT_LE_NATIVE_MONO = STEREO_MONO, |
55 | CONVERT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES, | 51 | SAMPLE_INPUT_GT_NATIVE_I_STEREO = STEREO_INTERLEAVED + STEREO_NUM_MODES, |
56 | CONVERT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES, | 52 | SAMPLE_INPUT_GT_NATIVE_NI_STEREO = STEREO_NONINTERLEAVED + STEREO_NUM_MODES, |
57 | CONVERT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES, | 53 | SAMPLE_INPUT_GT_NATIVE_MONO = STEREO_MONO + STEREO_NUM_MODES, |
58 | CONVERT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES | 54 | SAMPLE_INPUT_GT_NATIVE_1ST_INDEX = STEREO_NUM_MODES |
59 | }; | 55 | }; |
60 | 56 | ||
61 | struct dsp_config | 57 | enum |
62 | { | 58 | { |
63 | long codec_frequency; /* Sample rate of data coming from the codec */ | 59 | SAMPLE_OUTPUT_MONO = 0, |
64 | long frequency; /* Effective sample rate after pitch shift (if any) */ | 60 | SAMPLE_OUTPUT_STEREO, |
65 | long clip_min; | 61 | SAMPLE_OUTPUT_DITHERED_MONO, |
66 | long clip_max; | 62 | SAMPLE_OUTPUT_DITHERED_STEREO |
67 | long track_gain; | ||
68 | long album_gain; | ||
69 | long track_peak; | ||
70 | long album_peak; | ||
71 | long replaygain; | ||
72 | int sample_depth; | ||
73 | int sample_bytes; | ||
74 | int stereo_mode; | ||
75 | int num_channels; | ||
76 | int frac_bits; | ||
77 | bool dither_enabled; | ||
78 | long dither_bias; | ||
79 | long dither_mask; | ||
80 | bool new_gain; | ||
81 | bool crossfeed_enabled; | ||
82 | bool eq_enabled; | ||
83 | long eq_precut; | ||
84 | long gain; /* Note that this is in S8.23 format. */ | ||
85 | int (*convert_to_internal)(const char* src[], int32_t* dst[], int count); | ||
86 | }; | 63 | }; |
87 | 64 | ||
65 | /**************************************************************************** | ||
66 | * NOTE: Any assembly routines that use these structures must be updated | ||
67 | * if current data members are moved or changed. | ||
68 | */ | ||
69 | /* 32-bit achitecture offset */ | ||
88 | struct resample_data | 70 | struct resample_data |
89 | { | 71 | { |
90 | long phase; | 72 | long delta; /* 00h */ |
91 | long delta; | 73 | long phase; /* 04h */ |
92 | int32_t last_sample[2]; | 74 | int32_t last_sample[2]; /* 08h */ |
75 | /* 10h */ | ||
76 | }; | ||
77 | |||
78 | /* This is for passing needed data to assembly dsp routines. If another | ||
79 | * dsp parameter needs to be passed, add to the end of the structure | ||
80 | * and remove from dsp_config. | ||
81 | * If another function type becomes assembly optimized and requires dsp | ||
82 | * config info, add a pointer paramter of type "struct dsp_data *". | ||
83 | * If removing something from other than the end, reserve the spot or | ||
84 | * else update every implementation for every target. | ||
85 | * Be sure to add the offset of the new member for easy viewing as well. :) | ||
86 | * It is the first member of dsp_config and all members can be accessesed | ||
87 | * through the main aggregate but this is intended to make a safe haven | ||
88 | * for these items whereas the c part can be rearranged at will. dsp_data | ||
89 | * could even moved within dsp_config without disurbing the order. | ||
90 | */ | ||
91 | struct dsp_data | ||
92 | { | ||
93 | int output_scale; /* 00h */ | ||
94 | int num_channels; /* 04h */ | ||
95 | struct resample_data resample_data; /* 08h */ | ||
96 | int clip_min; /* 18h */ | ||
97 | int clip_max; /* 2ch */ | ||
98 | /* 30h */ | ||
93 | }; | 99 | }; |
94 | 100 | ||
101 | /* No asm...yet */ | ||
95 | struct dither_data | 102 | struct dither_data |
96 | { | 103 | { |
97 | long error[3]; | 104 | long error[3]; /* 00h */ |
98 | long random; | 105 | long random; /* 0ch */ |
106 | /* 10h */ | ||
99 | }; | 107 | }; |
100 | 108 | ||
101 | struct crossfeed_data | 109 | struct crossfeed_data |
102 | { | 110 | { |
103 | int32_t gain; /* Direct path gain */ | 111 | int32_t gain; /* 00h - Direct path gain */ |
104 | int32_t coefs[3]; /* Coefficients for the shelving filter */ | 112 | int32_t coefs[3]; /* 04h - Coefficients for the shelving filter */ |
105 | int32_t history[4]; /* Format is x[n - 1], y[n - 1] for both channels */ | 113 | int32_t history[4]; /* 10h - Format is x[n - 1], y[n - 1] for both channels */ |
106 | int32_t delay[13][2]; | 114 | int32_t delay[13][2]; /* 20h */ |
107 | int index; /* Current index into the delay line */ | 115 | int index; /* 88h - Current index into the delay line */ |
116 | /* 8ch */ | ||
108 | }; | 117 | }; |
109 | 118 | ||
110 | /* Current setup is one lowshelf filters, three peaking filters and one | 119 | /* Current setup is one lowshelf filters, three peaking filters and one |
111 | highshelf filter. Varying the number of shelving filters make no sense, | 120 | highshelf filter. Varying the number of shelving filters make no sense, |
112 | but adding peaking filters is possible. */ | 121 | but adding peaking filters is possible. */ |
113 | struct eq_state { | 122 | struct eq_state |
114 | char enabled[5]; /* Flags for active filters */ | 123 | { |
115 | struct eqfilter filters[5]; | 124 | char enabled[5]; /* 00h - Flags for active filters */ |
125 | struct eqfilter filters[5]; /* 08h - packing is 4? */ | ||
126 | /* 10ch */ | ||
116 | }; | 127 | }; |
117 | 128 | ||
118 | static struct dsp_config dsp_conf[2] IBSS_ATTR; | 129 | /* Include header with defines which functions are implemented in assembly |
119 | static struct dither_data dither_data[2] IBSS_ATTR; | 130 | code for the target */ |
120 | static struct resample_data resample_data[2] IBSS_ATTR; | 131 | #ifndef SIMULATOR |
121 | struct crossfeed_data crossfeed_data IBSS_ATTR; | 132 | #include <dsp_asm.h> |
122 | static struct eq_state eq_data; | 133 | #endif |
134 | |||
135 | #ifndef DSP_HAVE_ASM_CROSSFEED | ||
136 | static void apply_crossfeed(int32_t *buf[], int count); | ||
137 | #endif | ||
138 | /* | ||
139 | ***************************************************************************/ | ||
123 | 140 | ||
124 | static int pitch_ratio = 1000; | 141 | struct dsp_config |
125 | static int channels_mode = 0; | 142 | { |
126 | static int32_t sw_gain, sw_cross; | 143 | struct dsp_data data; /* Config members for use in asm routines */ |
144 | long codec_frequency; /* Sample rate of data coming from the codec */ | ||
145 | long frequency; /* Effective sample rate after pitch shift (if any) */ | ||
146 | int sample_depth; | ||
147 | int sample_bytes; | ||
148 | int stereo_mode; | ||
149 | int frac_bits; | ||
150 | long gain; /* Note that this is in S8.23 format. */ | ||
151 | /* Functions that change depending upon settings - NULL if stage is | ||
152 | disabled */ | ||
153 | int (*input_samples)(int count, const char *src[], int32_t *dst[]); | ||
154 | int (*resample)(int count, struct dsp_data *data, | ||
155 | int32_t *src[], int32_t *dst[]); | ||
156 | void (*output_samples)(int count, struct dsp_data *data, | ||
157 | int32_t *src[], int16_t *dst); | ||
158 | /* These will be NULL for the voice codec and is more economical that | ||
159 | way */ | ||
160 | void (*apply_crossfeed)(int32_t *src[], int count); | ||
161 | void (*channels_process)(int count, int32_t *buf[]); | ||
162 | }; | ||
127 | 163 | ||
128 | extern int current_codec; | 164 | /* General DSP config */ |
129 | static struct dsp_config *dsp; | 165 | static struct dsp_config dsp_conf[2] IBSS_ATTR; /* 0=A, 1=V */ |
166 | /* Dithering */ | ||
167 | static struct dither_data dither_data[2] IBSS_ATTR; /* 0=left, 1=right */ | ||
168 | static long dither_mask IBSS_ATTR; | ||
169 | static long dither_bias IBSS_ATTR; | ||
170 | /* Crossfeed */ | ||
171 | struct crossfeed_data crossfeed_data IBSS_ATTR; /* A */ | ||
172 | /* Equalizer */ | ||
173 | static struct eq_state eq_data; /* A/V */ | ||
174 | |||
175 | /* Settings applicable to audio codec only */ | ||
176 | static int pitch_ratio = 1000; | ||
177 | static int channels_mode; | ||
178 | long dsp_sw_gain; | ||
179 | long dsp_sw_cross; | ||
180 | static bool dither_enabled; | ||
181 | static bool eq_enabled IBSS_ATTR; | ||
182 | static long eq_precut; | ||
183 | static long track_gain; | ||
184 | static bool new_gain; | ||
185 | static long album_gain; | ||
186 | static long track_peak; | ||
187 | static long album_peak; | ||
188 | static long replaygain; | ||
189 | static bool crossfeed_enabled; | ||
190 | |||
191 | #define audio_dsp (&dsp_conf[CODEC_IDX_AUDIO]) | ||
192 | #define voice_dsp (&dsp_conf[CODEC_IDX_VOICE]) | ||
193 | static struct dsp_config *dsp IDATA_ATTR = audio_dsp; | ||
130 | 194 | ||
131 | /* The internal format is 32-bit samples, non-interleaved, stereo. This | 195 | /* The internal format is 32-bit samples, non-interleaved, stereo. This |
132 | * format is similar to the raw output from several codecs, so the amount | 196 | * format is similar to the raw output from several codecs, so the amount |
@@ -136,6 +200,38 @@ static struct dsp_config *dsp; | |||
136 | static int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR; | 200 | static int32_t sample_buf[SAMPLE_BUF_COUNT] IBSS_ATTR; |
137 | static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR; | 201 | static int32_t resample_buf[RESAMPLE_BUF_COUNT] IBSS_ATTR; |
138 | 202 | ||
203 | /* set a new dsp and return old one */ | ||
204 | static inline struct dsp_config * switch_dsp(struct dsp_config *_dsp) | ||
205 | { | ||
206 | struct dsp_config * old_dsp = dsp; | ||
207 | dsp = _dsp; | ||
208 | return old_dsp; | ||
209 | } | ||
210 | |||
211 | #if 0 | ||
212 | /* Clip sample to arbitrary limits where range > 0 and min + range = max */ | ||
213 | static inline long clip_sample(int32_t sample, int32_t min, int32_t range) | ||
214 | { | ||
215 | int32_t c = sample - min; | ||
216 | if ((uint32_t)c > (uint32_t)range) | ||
217 | { | ||
218 | sample -= c; | ||
219 | if (c > 0) | ||
220 | sample += range; | ||
221 | } | ||
222 | |||
223 | return sample; | ||
224 | } | ||
225 | #endif | ||
226 | |||
227 | /* Clip sample to signed 16 bit range */ | ||
228 | static inline int32_t clip_sample_16(int32_t sample) | ||
229 | { | ||
230 | if ((int16_t)sample != sample) | ||
231 | sample = 0x7fff ^ (sample >> 31); | ||
232 | return sample; | ||
233 | } | ||
234 | |||
139 | int sound_get_pitch(void) | 235 | int sound_get_pitch(void) |
140 | { | 236 | { |
141 | return pitch_ratio; | 237 | return pitch_ratio; |
@@ -156,13 +252,13 @@ void sound_set_pitch(int permille) | |||
156 | */ | 252 | */ |
157 | 253 | ||
158 | /* convert count 16-bit mono to 32-bit mono */ | 254 | /* convert count 16-bit mono to 32-bit mono */ |
159 | static int convert_lte_native_mono( | 255 | static int sample_input_lte_native_mono( |
160 | const char *src[], int32_t *dst[], int count) | 256 | int count, const char *src[], int32_t *dst[]) |
161 | { | 257 | { |
162 | count = MIN(SAMPLE_BUF_COUNT/2, count); | 258 | count = MIN(SAMPLE_BUF_COUNT/2, count); |
163 | 259 | ||
164 | const short *s = (short*) src[0]; | 260 | const int16_t *s = (int16_t *) src[0]; |
165 | const short * const send = s + count; | 261 | const int16_t * const send = s + count; |
166 | int32_t *d = dst[0] = dst[1] = sample_buf; | 262 | int32_t *d = dst[0] = dst[1] = sample_buf; |
167 | const int scale = WORD_SHIFT; | 263 | const int scale = WORD_SHIFT; |
168 | 264 | ||
@@ -178,8 +274,8 @@ static int convert_lte_native_mono( | |||
178 | } | 274 | } |
179 | 275 | ||
180 | /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */ | 276 | /* convert count 16-bit interleaved stereo to 32-bit noninterleaved */ |
181 | static int convert_lte_native_interleaved_stereo( | 277 | static int sample_input_lte_native_i_stereo( |
182 | const char *src[], int32_t *dst[], int count) | 278 | int count, const char *src[], int32_t *dst[]) |
183 | { | 279 | { |
184 | count = MIN(SAMPLE_BUF_COUNT/2, count); | 280 | count = MIN(SAMPLE_BUF_COUNT/2, count); |
185 | 281 | ||
@@ -194,9 +290,9 @@ static int convert_lte_native_interleaved_stereo( | |||
194 | int32_t slr = *s++; | 290 | int32_t slr = *s++; |
195 | #ifdef ROCKBOX_LITTLE_ENDIAN | 291 | #ifdef ROCKBOX_LITTLE_ENDIAN |
196 | *dl++ = (slr >> 16) << scale; | 292 | *dl++ = (slr >> 16) << scale; |
197 | *dr++ = (int32_t)(short)slr << scale; | 293 | *dr++ = (int32_t)(int16_t)slr << scale; |
198 | #else /* ROCKBOX_BIG_ENDIAN */ | 294 | #else /* ROCKBOX_BIG_ENDIAN */ |
199 | *dl++ = (int32_t)(short)slr << scale; | 295 | *dl++ = (int32_t)(int16_t)slr << scale; |
200 | *dr++ = (slr >> 16) << scale; | 296 | *dr++ = (slr >> 16) << scale; |
201 | #endif | 297 | #endif |
202 | } | 298 | } |
@@ -208,12 +304,14 @@ static int convert_lte_native_interleaved_stereo( | |||
208 | } | 304 | } |
209 | 305 | ||
210 | /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */ | 306 | /* convert count 16-bit noninterleaved stereo to 32-bit noninterleaved */ |
211 | static int convert_lte_native_noninterleaved_stereo( | 307 | static int sample_input_lte_native_ni_stereo( |
212 | const char *src[], int32_t *dst[], int count) | 308 | int count, const char *src[], int32_t *dst[]) |
213 | { | 309 | { |
214 | const short *sl = (short *) src[0]; | 310 | count = MIN(SAMPLE_BUF_COUNT/2, count); |
215 | const short *sr = (short *) src[1]; | 311 | |
216 | const short * const slend = sl + count; | 312 | const int16_t *sl = (int16_t *) src[0]; |
313 | const int16_t *sr = (int16_t *) src[1]; | ||
314 | const int16_t * const slend = sl + count; | ||
217 | int32_t *dl = dst[0] = sample_buf; | 315 | int32_t *dl = dst[0] = sample_buf; |
218 | int32_t *dr = dst[1] = sample_buf + SAMPLE_BUF_COUNT/2; | 316 | int32_t *dr = dst[1] = sample_buf + SAMPLE_BUF_COUNT/2; |
219 | const int scale = WORD_SHIFT; | 317 | const int scale = WORD_SHIFT; |
@@ -232,8 +330,8 @@ static int convert_lte_native_noninterleaved_stereo( | |||
232 | } | 330 | } |
233 | 331 | ||
234 | /* convert count 32-bit mono to 32-bit mono */ | 332 | /* convert count 32-bit mono to 32-bit mono */ |
235 | static int convert_gt_native_mono( | 333 | static int sample_input_gt_native_mono( |
236 | const char *src[], int32_t *dst[], int count) | 334 | int count, const char *src[], int32_t *dst[]) |
237 | { | 335 | { |
238 | count = MIN(SAMPLE_BUF_COUNT/2, count); | 336 | count = MIN(SAMPLE_BUF_COUNT/2, count); |
239 | 337 | ||
@@ -244,8 +342,8 @@ static int convert_gt_native_mono( | |||
244 | } | 342 | } |
245 | 343 | ||
246 | /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */ | 344 | /* convert count 32-bit interleaved stereo to 32-bit noninterleaved stereo */ |
247 | static int convert_gt_native_interleaved_stereo( | 345 | static int sample_input_gt_native_i_stereo( |
248 | const char *src[], int32_t *dst[], int count) | 346 | int count, const char *src[], int32_t *dst[]) |
249 | { | 347 | { |
250 | count = MIN(SAMPLE_BUF_COUNT/2, count); | 348 | count = MIN(SAMPLE_BUF_COUNT/2, count); |
251 | 349 | ||
@@ -270,8 +368,8 @@ static int convert_gt_native_interleaved_stereo( | |||
270 | } | 368 | } |
271 | 369 | ||
272 | /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */ | 370 | /* convert 32 bit-noninterleaved stereo to 32-bit noninterleaved stereo */ |
273 | static int convert_gt_native_noninterleaved_stereo( | 371 | static int sample_input_gt_native_ni_stereo( |
274 | const char *src[], int32_t *dst[], int count) | 372 | int count, const char *src[], int32_t *dst[]) |
275 | { | 373 | { |
276 | count = MIN(SAMPLE_BUF_COUNT/2, count); | 374 | count = MIN(SAMPLE_BUF_COUNT/2, count); |
277 | 375 | ||
@@ -283,42 +381,190 @@ static int convert_gt_native_noninterleaved_stereo( | |||
283 | return count; | 381 | return count; |
284 | } | 382 | } |
285 | 383 | ||
286 | /* set the to-native sample conversion function based on dsp sample parameters */ | 384 | /** |
287 | static void new_sample_conversion(void) | 385 | * sample_input_new_format() |
386 | * | ||
387 | * set the to-native sample conversion function based on dsp sample parameters | ||
388 | * | ||
389 | * !DSPPARAMSYNC | ||
390 | * needs syncing with changes to the following dsp parameters: | ||
391 | * * dsp->stereo_mode (A/V) | ||
392 | * * dsp->sample_depth (A/V) | ||
393 | */ | ||
394 | static void sample_input_new_format(void) | ||
288 | { | 395 | { |
289 | static int (*convert_to_internal_functions[])( | 396 | static int (* const sample_input_functions[])( |
290 | const char* src[], int32_t *dst[], int count) = | 397 | int count, const char* src[], int32_t *dst[]) = |
291 | { | 398 | { |
292 | [CONVERT_LE_NATIVE_MONO] = convert_lte_native_mono, | 399 | [SAMPLE_INPUT_LE_NATIVE_MONO] = sample_input_lte_native_mono, |
293 | [CONVERT_LE_NATIVE_I_STEREO] = convert_lte_native_interleaved_stereo, | 400 | [SAMPLE_INPUT_LE_NATIVE_I_STEREO] = sample_input_lte_native_i_stereo, |
294 | [CONVERT_LE_NATIVE_NI_STEREO] = convert_lte_native_noninterleaved_stereo, | 401 | [SAMPLE_INPUT_LE_NATIVE_NI_STEREO] = sample_input_lte_native_ni_stereo, |
295 | [CONVERT_GT_NATIVE_MONO] = convert_gt_native_mono, | 402 | [SAMPLE_INPUT_GT_NATIVE_MONO] = sample_input_gt_native_mono, |
296 | [CONVERT_GT_NATIVE_I_STEREO] = convert_gt_native_interleaved_stereo, | 403 | [SAMPLE_INPUT_GT_NATIVE_I_STEREO] = sample_input_gt_native_i_stereo, |
297 | [CONVERT_GT_NATIVE_NI_STEREO] = convert_gt_native_noninterleaved_stereo, | 404 | [SAMPLE_INPUT_GT_NATIVE_NI_STEREO] = sample_input_gt_native_ni_stereo, |
298 | }; | 405 | }; |
299 | 406 | ||
300 | int convert = dsp->stereo_mode; | 407 | int convert = dsp->stereo_mode; |
301 | 408 | ||
302 | if (dsp->sample_depth > NATIVE_DEPTH) | 409 | if (dsp->sample_depth > NATIVE_DEPTH) |
303 | convert += CONVERT_GT_NATIVE_1ST_INDEX; | 410 | convert += SAMPLE_INPUT_GT_NATIVE_1ST_INDEX; |
411 | |||
412 | dsp->input_samples = sample_input_functions[convert]; | ||
413 | } | ||
414 | |||
415 | #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO | ||
416 | /* write mono internal format to output format */ | ||
417 | static void sample_output_mono(int count, struct dsp_data *data, | ||
418 | int32_t *src[], int16_t *dst) | ||
419 | { | ||
420 | const int32_t *s0 = src[0]; | ||
421 | const int scale = data->output_scale; | ||
422 | |||
423 | do | ||
424 | { | ||
425 | int32_t lr = clip_sample_16(*s0++ >> scale); | ||
426 | *dst++ = lr; | ||
427 | *dst++ = lr; | ||
428 | } | ||
429 | while (--count > 0); | ||
430 | } | ||
431 | #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_MONO */ | ||
432 | |||
433 | /* write stereo internal format to output format */ | ||
434 | #ifndef DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO | ||
435 | static void sample_output_stereo(int count, struct dsp_data *data, | ||
436 | int32_t *src[], int16_t *dst) | ||
437 | { | ||
438 | const int32_t *s0 = src[0]; | ||
439 | const int32_t *s1 = src[1]; | ||
440 | const int scale = data->output_scale; | ||
441 | |||
442 | do | ||
443 | { | ||
444 | *dst++ = clip_sample_16(*s0++ >> scale); | ||
445 | *dst++ = clip_sample_16(*s1++ >> scale); | ||
446 | } | ||
447 | while (--count > 0); | ||
448 | } | ||
449 | #endif /* DSP_HAVE_ASM_SAMPLE_OUTPUT_STEREO */ | ||
450 | |||
451 | /** | ||
452 | * The "dither" code to convert the 24-bit samples produced by libmad was | ||
453 | * taken from the coolplayer project - coolplayer.sourceforge.net | ||
454 | * | ||
455 | * This function handles mono and stereo outputs. | ||
456 | */ | ||
457 | static void sample_output_dithered(int count, struct dsp_data *data, | ||
458 | int32_t *src[], int16_t *dst) | ||
459 | { | ||
460 | const int32_t mask = dither_mask; | ||
461 | const int32_t bias = dither_bias; | ||
462 | const int scale = data->output_scale; | ||
463 | const int32_t min = data->clip_min; | ||
464 | const int32_t max = data->clip_max; | ||
465 | const int32_t range = max - min; | ||
466 | const int dinc = dsp->data.num_channels; | ||
467 | |||
468 | int ch; | ||
469 | for (ch = 0; ch < dinc; ch++) | ||
470 | { | ||
471 | struct dither_data * const dither = &dither_data[ch]; | ||
472 | int32_t *s = src[ch]; | ||
473 | int16_t *d = &dst[ch]; | ||
474 | int i; | ||
475 | |||
476 | for (i = 0; i < count; i++, s++, d += dinc) | ||
477 | { | ||
478 | int32_t output, sample; | ||
479 | int32_t random; | ||
480 | |||
481 | /* Noise shape and bias */ | ||
482 | sample = *s; | ||
483 | sample += dither->error[0] - dither->error[1] + dither->error[2]; | ||
484 | dither->error[2] = dither->error[1]; | ||
485 | dither->error[1] = dither->error[0]/2; | ||
486 | |||
487 | output = sample + bias; | ||
488 | |||
489 | /* Dither */ | ||
490 | random = dither->random*0x0019660dL + 0x3c6ef35fL; | ||
491 | output += (random & mask) - (dither->random & mask); | ||
492 | dither->random = random; | ||
493 | |||
494 | /* Clip */ | ||
495 | int32_t c = output - min; | ||
496 | if ((uint32_t)c > (uint32_t)range) | ||
497 | { | ||
498 | output -= c; | ||
499 | if (c > 0) | ||
500 | { | ||
501 | output += range; | ||
502 | if (sample > max) | ||
503 | sample = max; | ||
504 | } | ||
505 | else if (sample < min) | ||
506 | { | ||
507 | sample = min; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | output &= ~mask; | ||
512 | |||
513 | /* Error feedback */ | ||
514 | dither->error[0] = sample - output; | ||
515 | |||
516 | /* Quantize */ | ||
517 | *d = output >> scale; | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | /** | ||
523 | * sample_output_new_format() | ||
524 | * | ||
525 | * set the from-native to ouput sample conversion routine | ||
526 | * | ||
527 | * !DSPPARAMSYNC | ||
528 | * needs syncing with changes to the following dsp parameters: | ||
529 | * * dsp->stereo_mode (A/V) | ||
530 | * * dither_enabled (A) | ||
531 | */ | ||
532 | static void sample_output_new_format(void) | ||
533 | { | ||
534 | static void (* const sample_output_functions[])( | ||
535 | int count, struct dsp_data *data, | ||
536 | int32_t *src[], int16_t *dst) = | ||
537 | { | ||
538 | sample_output_mono, | ||
539 | sample_output_stereo, | ||
540 | sample_output_dithered, | ||
541 | sample_output_dithered | ||
542 | }; | ||
543 | |||
544 | int out = dsp->data.num_channels - 1; | ||
545 | |||
546 | if (dsp == audio_dsp && dither_enabled) | ||
547 | out += 2; | ||
304 | 548 | ||
305 | dsp->convert_to_internal = convert_to_internal_functions[convert]; | 549 | dsp->output_samples = sample_output_functions[out]; |
306 | } | 550 | } |
307 | 551 | ||
308 | static void resampler_set_delta(int frequency) | 552 | static void resampler_set_delta(int frequency) |
309 | { | 553 | { |
310 | resample_data[current_codec].delta = (unsigned long) | 554 | dsp->data.resample_data.delta = (unsigned long) |
311 | frequency * 65536LL / NATIVE_FREQUENCY; | 555 | frequency * 65536LL / NATIVE_FREQUENCY; |
312 | } | 556 | } |
313 | 557 | ||
314 | /* Linear interpolation resampling that introduces a one sample delay because | 558 | /** |
559 | * Linear interpolation resampling that introduces a one sample delay because | ||
315 | * of our inability to look into the future at the end of a frame. | 560 | * of our inability to look into the future at the end of a frame. |
316 | */ | 561 | */ |
317 | #ifndef DSP_HAVE_ASM_RESAMPLING | 562 | #ifndef DSP_HAVE_ASM_RESAMPLING |
318 | static int dsp_downsample(int channels, int count, struct resample_data *r, | 563 | static int dsp_downsample(int count, struct dsp_data *data, |
319 | int32_t **src, int32_t **dst) | 564 | int32_t *src[], int32_t *dst[]) |
320 | { | 565 | { |
321 | long delta = r->delta; | 566 | int ch = data->num_channels - 1; |
567 | long delta = data->resample_data.delta; | ||
322 | long phase, pos; | 568 | long phase, pos; |
323 | int32_t *d; | 569 | int32_t *d; |
324 | 570 | ||
@@ -328,12 +574,12 @@ static int dsp_downsample(int channels, int count, struct resample_data *r, | |||
328 | /* Just initialize things and not worry too much about the relatively | 574 | /* Just initialize things and not worry too much about the relatively |
329 | * uncommon case of not being able to spit out a sample for the frame. | 575 | * uncommon case of not being able to spit out a sample for the frame. |
330 | */ | 576 | */ |
331 | int32_t *s = src[--channels]; | 577 | int32_t *s = src[ch]; |
332 | int32_t last = r->last_sample[channels]; | 578 | int32_t last = data->resample_data.last_sample[ch]; |
333 | 579 | ||
334 | r->last_sample[channels] = s[count - 1]; | 580 | data->resample_data.last_sample[ch] = s[count - 1]; |
335 | d = dst[channels]; | 581 | d = dst[ch]; |
336 | phase = r->phase; | 582 | phase = data->resample_data.phase; |
337 | pos = phase >> 16; | 583 | pos = phase >> 16; |
338 | 584 | ||
339 | /* Do we need last sample of previous frame for interpolation? */ | 585 | /* Do we need last sample of previous frame for interpolation? */ |
@@ -348,17 +594,18 @@ static int dsp_downsample(int channels, int count, struct resample_data *r, | |||
348 | last = s[pos - 1]; | 594 | last = s[pos - 1]; |
349 | } | 595 | } |
350 | } | 596 | } |
351 | while (channels > 0); | 597 | while (--ch >= 0); |
352 | 598 | ||
353 | /* Wrap phase accumulator back to start of next frame. */ | 599 | /* Wrap phase accumulator back to start of next frame. */ |
354 | r->phase = phase - (count << 16); | 600 | data->resample_data.phase = phase - (count << 16); |
355 | return d - dst[0]; | 601 | return d - dst[0]; |
356 | } | 602 | } |
357 | 603 | ||
358 | static int dsp_upsample(int channels, int count, struct resample_data *r, | 604 | static int dsp_upsample(int count, struct dsp_data *data, |
359 | int32_t **src, int32_t **dst) | 605 | int32_t *src[], int32_t *dst[]) |
360 | { | 606 | { |
361 | long delta = r->delta; | 607 | int ch = data->num_channels - 1; |
608 | long delta = data->resample_data.delta; | ||
362 | long phase, pos; | 609 | long phase, pos; |
363 | int32_t *d; | 610 | int32_t *d; |
364 | 611 | ||
@@ -367,12 +614,12 @@ static int dsp_upsample(int channels, int count, struct resample_data *r, | |||
367 | { | 614 | { |
368 | /* Should always be able to output a sample for a ratio up to | 615 | /* Should always be able to output a sample for a ratio up to |
369 | RESAMPLE_BUF_COUNT / SAMPLE_BUF_COUNT. */ | 616 | RESAMPLE_BUF_COUNT / SAMPLE_BUF_COUNT. */ |
370 | int32_t *s = src[--channels]; | 617 | int32_t *s = src[ch]; |
371 | int32_t last = r->last_sample[channels]; | 618 | int32_t last = data->resample_data.last_sample[ch]; |
372 | 619 | ||
373 | r->last_sample[channels] = s[count - 1]; | 620 | data->resample_data.last_sample[ch] = s[count - 1]; |
374 | d = dst[channels]; | 621 | d = dst[ch]; |
375 | phase = r->phase; | 622 | phase = data->resample_data.phase; |
376 | pos = phase >> 16; | 623 | pos = phase >> 16; |
377 | 624 | ||
378 | while (pos == 0) | 625 | while (pos == 0) |
@@ -390,10 +637,10 @@ static int dsp_upsample(int channels, int count, struct resample_data *r, | |||
390 | pos = phase >> 16; | 637 | pos = phase >> 16; |
391 | } | 638 | } |
392 | } | 639 | } |
393 | while (channels > 0); | 640 | while (--ch >= 0); |
394 | 641 | ||
395 | /* Wrap phase accumulator back to start of next frame. */ | 642 | /* Wrap phase accumulator back to start of next frame. */ |
396 | r->phase = phase & 0xffff; | 643 | data->resample_data.phase = phase & 0xffff; |
397 | return d - dst[0]; | 644 | return d - dst[0]; |
398 | } | 645 | } |
399 | #endif /* DSP_HAVE_ASM_RESAMPLING */ | 646 | #endif /* DSP_HAVE_ASM_RESAMPLING */ |
@@ -402,111 +649,57 @@ static int dsp_upsample(int channels, int count, struct resample_data *r, | |||
402 | * done, to refer to the resampled data. Returns number of stereo samples | 649 | * done, to refer to the resampled data. Returns number of stereo samples |
403 | * for further processing. | 650 | * for further processing. |
404 | */ | 651 | */ |
405 | static inline int resample(int32_t *src[], int count) | 652 | static inline int resample(int count, int32_t *src[]) |
406 | { | 653 | { |
407 | long new_count = count; | 654 | if (dsp->resample) |
408 | |||
409 | if (dsp->frequency != NATIVE_FREQUENCY) | ||
410 | { | 655 | { |
411 | int32_t *dst[2] = | 656 | int32_t *dst[2] = |
412 | { | 657 | { |
413 | resample_buf, | 658 | resample_buf, |
414 | resample_buf + RESAMPLE_BUF_COUNT/2, | 659 | resample_buf + RESAMPLE_BUF_COUNT/2, |
415 | }; | 660 | }; |
416 | int channels = dsp->num_channels; | ||
417 | |||
418 | if (dsp->frequency < NATIVE_FREQUENCY) | ||
419 | new_count = dsp_upsample(channels, count, | ||
420 | &resample_data[current_codec], | ||
421 | src, dst); | ||
422 | else | ||
423 | new_count = dsp_downsample(channels, count, | ||
424 | &resample_data[current_codec], | ||
425 | src, dst); | ||
426 | 661 | ||
662 | count = dsp->resample(count, &dsp->data, src, dst); | ||
427 | src[0] = dst[0]; | 663 | src[0] = dst[0]; |
428 | src[1] = dst[channels - 1]; | 664 | src[1] = dst[dsp->data.num_channels - 1]; |
429 | } | 665 | } |
430 | 666 | ||
431 | return new_count; | 667 | return count; |
432 | } | 668 | } |
433 | 669 | ||
434 | static inline long clip_sample(int32_t sample, int32_t min, int32_t max) | 670 | static void dither_init(void) |
435 | { | 671 | { |
436 | if (sample > max) | 672 | /* Voice codec should not reset the audio codec's dither data */ |
437 | { | 673 | if (dsp != audio_dsp) |
438 | sample = max; | 674 | return; |
439 | } | ||
440 | else if (sample < min) | ||
441 | { | ||
442 | sample = min; | ||
443 | } | ||
444 | 675 | ||
445 | return sample; | 676 | memset(dither_data, 0, sizeof (dither_data)); |
677 | dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH)); | ||
678 | dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1; | ||
446 | } | 679 | } |
447 | 680 | ||
448 | /* The "dither" code to convert the 24-bit samples produced by libmad was | ||
449 | * taken from the coolplayer project - coolplayer.sourceforge.net | ||
450 | */ | ||
451 | |||
452 | void dsp_dither_enable(bool enable) | 681 | void dsp_dither_enable(bool enable) |
453 | { | 682 | { |
454 | dsp->dither_enabled = enable; | 683 | /* Be sure audio dsp is current to set correct function */ |
455 | } | 684 | struct dsp_config *old_dsp = switch_dsp(audio_dsp); |
456 | 685 | dither_enabled = enable; | |
457 | static void dither_init(void) | 686 | sample_output_new_format(); |
458 | { | 687 | switch_dsp(old_dsp); |
459 | memset(dither_data, 0, sizeof(dither_data)); | ||
460 | dsp->dither_bias = (1L << (dsp->frac_bits - NATIVE_DEPTH)); | ||
461 | dsp->dither_mask = (1L << (dsp->frac_bits + 1 - NATIVE_DEPTH)) - 1; | ||
462 | } | ||
463 | |||
464 | static void dither_samples(int32_t* src, int num, struct dither_data* dither) | ||
465 | { | ||
466 | int32_t output, sample; | ||
467 | int32_t random; | ||
468 | int32_t min, max; | ||
469 | long mask = dsp->dither_mask; | ||
470 | long bias = dsp->dither_bias; | ||
471 | int i; | ||
472 | |||
473 | for (i = 0; i < num; ++i) { | ||
474 | /* Noise shape and bias */ | ||
475 | sample = src[i]; | ||
476 | sample += dither->error[0] - dither->error[1] + dither->error[2]; | ||
477 | dither->error[2] = dither->error[1]; | ||
478 | dither->error[1] = dither->error[0]/2; | ||
479 | |||
480 | output = sample + bias; | ||
481 | |||
482 | /* Dither */ | ||
483 | random = dither->random*0x0019660dL + 0x3c6ef35fL; | ||
484 | output += (random & mask) - (dither->random & mask); | ||
485 | dither->random = random; | ||
486 | |||
487 | /* Clip and quantize */ | ||
488 | min = dsp->clip_min; | ||
489 | max = dsp->clip_max; | ||
490 | if (output > max) { | ||
491 | output = max; | ||
492 | if (sample > max) | ||
493 | sample = max; | ||
494 | } else if (output < min) { | ||
495 | output = min; | ||
496 | if (sample < min) | ||
497 | sample = min; | ||
498 | } | ||
499 | output &= ~mask; | ||
500 | |||
501 | /* Error feedback */ | ||
502 | dither->error[0] = sample - output; | ||
503 | src[i] = output; | ||
504 | } | ||
505 | } | 688 | } |
506 | 689 | ||
690 | /** | ||
691 | * dsp_set_crossfeed(bool enable) | ||
692 | * | ||
693 | * !DSPPARAMSYNC | ||
694 | * needs syncing with changes to the following dsp parameters: | ||
695 | * * dsp->stereo_mode (A) | ||
696 | */ | ||
507 | void dsp_set_crossfeed(bool enable) | 697 | void dsp_set_crossfeed(bool enable) |
508 | { | 698 | { |
509 | dsp->crossfeed_enabled = enable; | 699 | crossfeed_enabled = enable; |
700 | audio_dsp->apply_crossfeed = | ||
701 | (enable && audio_dsp->data.num_channels > 1) | ||
702 | ? apply_crossfeed : NULL; | ||
510 | } | 703 | } |
511 | 704 | ||
512 | void dsp_set_crossfeed_direct_gain(int gain) | 705 | void dsp_set_crossfeed_direct_gain(int gain) |
@@ -533,7 +726,7 @@ void dsp_set_crossfeed_cross_params(long lf_gain, long hf_gain, long cutoff) | |||
533 | * to listen to on headphones with no crossfeed. | 726 | * to listen to on headphones with no crossfeed. |
534 | */ | 727 | */ |
535 | #ifndef DSP_HAVE_ASM_CROSSFEED | 728 | #ifndef DSP_HAVE_ASM_CROSSFEED |
536 | static void apply_crossfeed(int32_t* src[], int count) | 729 | static void apply_crossfeed(int32_t *buf[], int count) |
537 | { | 730 | { |
538 | int32_t *hist_l = &crossfeed_data.history[0]; | 731 | int32_t *hist_l = &crossfeed_data.history[0]; |
539 | int32_t *hist_r = &crossfeed_data.history[2]; | 732 | int32_t *hist_r = &crossfeed_data.history[2]; |
@@ -546,9 +739,10 @@ static void apply_crossfeed(int32_t* src[], int count) | |||
546 | int32_t left, right; | 739 | int32_t left, right; |
547 | int i; | 740 | int i; |
548 | 741 | ||
549 | for (i = 0; i < count; i++) { | 742 | for (i = 0; i < count; i++) |
550 | left = src[0][i]; | 743 | { |
551 | right = src[1][i]; | 744 | left = buf[0][i]; |
745 | right = buf[1][i]; | ||
552 | 746 | ||
553 | /* Filter delayed sample from left speaker */ | 747 | /* Filter delayed sample from left speaker */ |
554 | ACC_INIT(acc, delay[di*2], coefs[0]); | 748 | ACC_INIT(acc, delay[di*2], coefs[0]); |
@@ -567,8 +761,8 @@ static void apply_crossfeed(int32_t* src[], int count) | |||
567 | delay[di*2] = left; | 761 | delay[di*2] = left; |
568 | delay[di*2 + 1] = right; | 762 | delay[di*2 + 1] = right; |
569 | /* Now add the attenuated direct sound and write to outputs */ | 763 | /* Now add the attenuated direct sound and write to outputs */ |
570 | src[0][i] = FRACMUL(left, gain) + hist_r[1]; | 764 | buf[0][i] = FRACMUL(left, gain) + hist_r[1]; |
571 | src[1][i] = FRACMUL(right, gain) + hist_l[1]; | 765 | buf[1][i] = FRACMUL(right, gain) + hist_l[1]; |
572 | 766 | ||
573 | /* Wrap delay line index if bigger than delay line size */ | 767 | /* Wrap delay line index if bigger than delay line size */ |
574 | if (++di > 12) | 768 | if (++di > 12) |
@@ -580,18 +774,19 @@ static void apply_crossfeed(int32_t* src[], int count) | |||
580 | #endif | 774 | #endif |
581 | 775 | ||
582 | /* Combine all gains to a global gain. */ | 776 | /* Combine all gains to a global gain. */ |
583 | static void set_gain(void) | 777 | static void set_gain(struct dsp_config *dsp) |
584 | { | 778 | { |
585 | dsp->gain = DEFAULT_GAIN; | 779 | dsp->gain = DEFAULT_GAIN; |
586 | 780 | ||
587 | if (dsp->replaygain) | 781 | /* Replay gain not relevant to voice */ |
782 | if (dsp == audio_dsp && replaygain) | ||
588 | { | 783 | { |
589 | dsp->gain = dsp->replaygain; | 784 | dsp->gain = replaygain; |
590 | } | 785 | } |
591 | 786 | ||
592 | if (dsp->eq_enabled && dsp->eq_precut) | 787 | if (eq_enabled && eq_precut) |
593 | { | 788 | { |
594 | dsp->gain = (long) (((int64_t) dsp->gain * dsp->eq_precut) >> 24); | 789 | dsp->gain = (long) (((int64_t) dsp->gain * eq_precut) >> 24); |
595 | } | 790 | } |
596 | 791 | ||
597 | if (dsp->gain == DEFAULT_GAIN) | 792 | if (dsp->gain == DEFAULT_GAIN) |
@@ -611,7 +806,7 @@ static void set_gain(void) | |||
611 | */ | 806 | */ |
612 | void dsp_set_eq(bool enable) | 807 | void dsp_set_eq(bool enable) |
613 | { | 808 | { |
614 | dsp->eq_enabled = enable; | 809 | eq_enabled = enable; |
615 | } | 810 | } |
616 | 811 | ||
617 | /** | 812 | /** |
@@ -621,8 +816,9 @@ void dsp_set_eq(bool enable) | |||
621 | */ | 816 | */ |
622 | void dsp_set_eq_precut(int precut) | 817 | void dsp_set_eq_precut(int precut) |
623 | { | 818 | { |
624 | dsp->eq_precut = get_replaygain_int(precut * -10); | 819 | eq_precut = get_replaygain_int(precut * -10); |
625 | set_gain(); | 820 | set_gain(audio_dsp); |
821 | set_gain(voice_dsp); /* For EQ precut */ | ||
626 | } | 822 | } |
627 | 823 | ||
628 | /** | 824 | /** |
@@ -651,9 +847,12 @@ void dsp_set_eq_coefs(int band) | |||
651 | which it should be, since we're executed from the main thread. */ | 847 | which it should be, since we're executed from the main thread. */ |
652 | 848 | ||
653 | /* Assume a band is disabled if the gain is zero */ | 849 | /* Assume a band is disabled if the gain is zero */ |
654 | if (gain == 0) { | 850 | if (gain == 0) |
851 | { | ||
655 | eq_data.enabled[band] = 0; | 852 | eq_data.enabled[band] = 0; |
656 | } else { | 853 | } |
854 | else | ||
855 | { | ||
657 | if (band == 0) | 856 | if (band == 0) |
658 | eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs); | 857 | eq_ls_coefs(cutoff, q, gain, eq_data.filters[band].coefs); |
659 | else if (band == 4) | 858 | else if (band == 4) |
@@ -666,24 +865,28 @@ void dsp_set_eq_coefs(int band) | |||
666 | } | 865 | } |
667 | 866 | ||
668 | /* Apply EQ filters to those bands that have got it switched on. */ | 867 | /* Apply EQ filters to those bands that have got it switched on. */ |
669 | static void eq_process(int32_t **x, unsigned num) | 868 | static void eq_process(int count, int32_t *buf[]) |
670 | { | 869 | { |
870 | static const int shifts[] = | ||
871 | { | ||
872 | EQ_SHELF_SHIFT, /* low shelf */ | ||
873 | EQ_PEAK_SHIFT, /* peaking */ | ||
874 | EQ_PEAK_SHIFT, /* peaking */ | ||
875 | EQ_PEAK_SHIFT, /* peaking */ | ||
876 | EQ_SHELF_SHIFT, /* high shelf */ | ||
877 | }; | ||
878 | unsigned int channels = dsp->data.num_channels; | ||
671 | int i; | 879 | int i; |
672 | unsigned int channels = dsp->num_channels; | ||
673 | unsigned shift; | ||
674 | 880 | ||
675 | /* filter configuration currently is 1 low shelf filter, 3 band peaking | 881 | /* filter configuration currently is 1 low shelf filter, 3 band peaking |
676 | filters and 1 high shelf filter, in that order. we need to know this | 882 | filters and 1 high shelf filter, in that order. we need to know this |
677 | so we can choose the correct shift factor. | 883 | so we can choose the correct shift factor. |
678 | */ | 884 | */ |
679 | for (i = 0; i < 5; i++) { | 885 | for (i = 0; i < 5; i++) |
680 | if (eq_data.enabled[i]) { | 886 | { |
681 | if (i == 0 || i == 4) /* shelving filters */ | 887 | if (!eq_data.enabled[i]) |
682 | shift = EQ_SHELF_SHIFT; | 888 | continue; |
683 | else | 889 | eq_filter(buf, &eq_data.filters[i], count, channels, shifts[i]); |
684 | shift = EQ_PEAK_SHIFT; | ||
685 | eq_filter(x, &eq_data.filters[i], num, channels, shift); | ||
686 | } | ||
687 | } | 890 | } |
688 | } | 891 | } |
689 | 892 | ||
@@ -691,45 +894,44 @@ static void eq_process(int32_t **x, unsigned num) | |||
691 | * the src array if gain was applied. | 894 | * the src array if gain was applied. |
692 | * Note that this must be called before the resampler. | 895 | * Note that this must be called before the resampler. |
693 | */ | 896 | */ |
694 | static void apply_gain(int32_t* _src[], int _count) | 897 | static void apply_gain(int count, int32_t *buf[]) |
695 | { | 898 | { |
696 | if (dsp->gain) | 899 | int32_t *sl, *sr; |
900 | int32_t s, *d; | ||
901 | long gain; | ||
902 | int i; | ||
903 | |||
904 | if (new_gain) | ||
697 | { | 905 | { |
698 | int32_t** src = _src; | 906 | /* Gain has changed */ |
699 | int count = _count; | 907 | dsp_set_replaygain(); |
700 | int32_t* s0 = src[0]; | 908 | if (dsp->gain == 0) |
701 | int32_t* s1 = src[1]; | 909 | return; /* No gain to apply now */ |
702 | long gain = dsp->gain; | 910 | } |
703 | int32_t s; | 911 | |
704 | int i; | 912 | sl = buf[0], sr = buf[1]; |
705 | int32_t *d; | 913 | gain = dsp->gain; |
706 | 914 | ||
707 | if (s0 != s1) | 915 | if (sl != sr) |
708 | { | 916 | { |
709 | d = &sample_buf[SAMPLE_BUF_COUNT / 2]; | 917 | d = &sample_buf[SAMPLE_BUF_COUNT / 2]; |
710 | src[1] = d; | 918 | buf[1] = d; |
711 | s = *s1++; | 919 | s = *sr++; |
712 | 920 | ||
713 | for (i = 0; i < count; i++) | ||
714 | FRACMUL_8_LOOP(s, gain, s1, d); | ||
715 | } | ||
716 | else | ||
717 | { | ||
718 | src[1] = &sample_buf[0]; | ||
719 | } | ||
720 | |||
721 | d = &sample_buf[0]; | ||
722 | src[0] = d; | ||
723 | s = *s0++; | ||
724 | |||
725 | for (i = 0; i < count; i++) | 921 | for (i = 0; i < count; i++) |
726 | FRACMUL_8_LOOP(s, gain, s0, d); | 922 | FRACMUL_8_LOOP(s, gain, sr, d); |
923 | } | ||
924 | else | ||
925 | { | ||
926 | buf[1] = &sample_buf[0]; | ||
727 | } | 927 | } |
728 | } | ||
729 | 928 | ||
730 | void channels_set(int value) | 929 | d = &sample_buf[0]; |
731 | { | 930 | buf[0] = d; |
732 | channels_mode = value; | 931 | s = *sl++; |
932 | |||
933 | for (i = 0; i < count; i++) | ||
934 | FRACMUL_8_LOOP(s, gain, sl, d); | ||
733 | } | 935 | } |
734 | 936 | ||
735 | void stereo_width_set(int value) | 937 | void stereo_width_set(int value) |
@@ -737,89 +939,119 @@ void stereo_width_set(int value) | |||
737 | long width, straight, cross; | 939 | long width, straight, cross; |
738 | 940 | ||
739 | width = value * 0x7fffff / 100; | 941 | width = value * 0x7fffff / 100; |
740 | if (value <= 100) { | 942 | |
943 | if (value <= 100) | ||
944 | { | ||
741 | straight = (0x7fffff + width) / 2; | 945 | straight = (0x7fffff + width) / 2; |
742 | cross = straight - width; | 946 | cross = straight - width; |
743 | } else { | 947 | } |
948 | else | ||
949 | { | ||
744 | /* straight = (1 + width) / (2 * width) */ | 950 | /* straight = (1 + width) / (2 * width) */ |
745 | straight = ((int64_t)(0x7fffff + width) << 22) / width; | 951 | straight = ((int64_t)(0x7fffff + width) << 22) / width; |
746 | cross = straight - 0x7fffff; | 952 | cross = straight - 0x7fffff; |
747 | } | 953 | } |
748 | sw_gain = straight << 8; | 954 | |
749 | sw_cross = cross << 8; | 955 | dsp_sw_gain = straight << 8; |
956 | dsp_sw_cross = cross << 8; | ||
750 | } | 957 | } |
751 | 958 | ||
752 | /* Implements the different channel configurations and stereo width. | 959 | /** |
753 | * We might want to combine this with the write_samples stage for efficiency, | 960 | * Implements the different channel configurations and stereo width. |
754 | * but for now we'll just let it stay as a stage of its own. | ||
755 | */ | 961 | */ |
756 | static void channels_process(int32_t **src, int num) | 962 | |
963 | /* SOUND_CHAN_STEREO mode is a noop so has no function - just outline one for | ||
964 | * completeness. */ | ||
965 | #if 0 | ||
966 | static void channels_process_sound_chan_stereo(int count, int32_t *buf[]) | ||
757 | { | 967 | { |
758 | int i; | 968 | /* The channels are each just themselves */ |
759 | int32_t *sl = src[0], *sr = src[1]; | 969 | (void)count; (void)buf; |
970 | } | ||
971 | #endif | ||
760 | 972 | ||
761 | if (channels_mode == SOUND_CHAN_STEREO) | 973 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_MONO |
762 | return; | 974 | static void channels_process_sound_chan_mono(int count, int32_t *buf[]) |
763 | switch (channels_mode) { | 975 | { |
764 | case SOUND_CHAN_MONO: | 976 | int32_t *sl = buf[0], *sr = buf[1]; |
765 | for (i = 0; i < num; i++) | ||
766 | sl[i] = sr[i] = sl[i]/2 + sr[i]/2; | ||
767 | break; | ||
768 | case SOUND_CHAN_CUSTOM: | ||
769 | for (i = 0; i < num; i++) { | ||
770 | int32_t left_sample = sl[i]; | ||
771 | 977 | ||
772 | sl[i] = FRACMUL(sl[i], sw_gain) + FRACMUL(sr[i], sw_cross); | 978 | do |
773 | sr[i] = FRACMUL(sr[i], sw_gain) + FRACMUL(left_sample, sw_cross); | 979 | { |
774 | } | 980 | int32_t lr = *sl/2 + *sr/2; |
775 | break; | 981 | *sl++ = lr; |
776 | case SOUND_CHAN_MONO_LEFT: | 982 | *sr++ = lr; |
777 | for (i = 0; i < num; i++) | ||
778 | sr[i] = sl[i]; | ||
779 | break; | ||
780 | case SOUND_CHAN_MONO_RIGHT: | ||
781 | for (i = 0; i < num; i++) | ||
782 | sl[i] = sr[i]; | ||
783 | break; | ||
784 | case SOUND_CHAN_KARAOKE: | ||
785 | for (i = 0; i < num; i++) { | ||
786 | int32_t left_sample = sl[i]/2; | ||
787 | |||
788 | sl[i] = left_sample - sr[i]/2; | ||
789 | sr[i] = sr[i]/2 - left_sample; | ||
790 | } | ||
791 | break; | ||
792 | } | 983 | } |
984 | while (--count > 0); | ||
793 | } | 985 | } |
986 | #endif /* DSP_HAVE_ASM_SOUND_CHAN_MONO */ | ||
794 | 987 | ||
795 | static void write_samples(short* dst, int32_t* src[], int count) | 988 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_CUSTOM |
989 | static void channels_process_sound_chan_custom(int count, int32_t *buf[]) | ||
796 | { | 990 | { |
797 | int32_t* s0 = src[0]; | 991 | const int32_t gain = dsp_sw_gain; |
798 | int32_t* s1 = src[1]; | 992 | const int32_t cross = dsp_sw_cross; |
799 | int scale = dsp->frac_bits + 1 - NATIVE_DEPTH; | 993 | int32_t *sl = buf[0], *sr = buf[1]; |
800 | 994 | ||
801 | if (dsp->dither_enabled) | 995 | do |
802 | { | 996 | { |
803 | dither_samples(src[0], count, &dither_data[0]); | 997 | int32_t l = *sl; |
804 | dither_samples(src[1], count, &dither_data[1]); | 998 | int32_t r = *sr; |
999 | *sl++ = FRACMUL(l, gain) + FRACMUL(r, cross); | ||
1000 | *sr++ = FRACMUL(r, gain) + FRACMUL(l, cross); | ||
1001 | } | ||
1002 | while (--count > 0); | ||
1003 | } | ||
1004 | #endif /* DSP_HAVE_ASM_SOUND_CHAN_CUSTOM */ | ||
805 | 1005 | ||
806 | while (count-- > 0) | 1006 | static void channels_process_sound_chan_mono_left(int count, int32_t *buf[]) |
807 | { | 1007 | { |
808 | *dst++ = (short) (*s0++ >> scale); | 1008 | /* Just copy over the other channel */ |
809 | *dst++ = (short) (*s1++ >> scale); | 1009 | memcpy(buf[1], buf[0], count * sizeof (*buf)); |
810 | } | 1010 | } |
1011 | |||
1012 | static void channels_process_sound_chan_mono_right(int count, int32_t *buf[]) | ||
1013 | { | ||
1014 | /* Just copy over the other channel */ | ||
1015 | memcpy(buf[0], buf[1], count * sizeof (*buf)); | ||
1016 | } | ||
1017 | |||
1018 | #ifndef DSP_HAVE_ASM_SOUND_CHAN_KARAOKE | ||
1019 | static void channels_process_sound_chan_karaoke(int count, int32_t *buf[]) | ||
1020 | { | ||
1021 | int32_t *sl = buf[0], *sr = buf[1]; | ||
1022 | |||
1023 | do | ||
1024 | { | ||
1025 | int32_t l = *sl/2; | ||
1026 | int32_t r = *sr/2; | ||
1027 | *sl++ = l - r; | ||
1028 | *sr++ = r - l; | ||
811 | } | 1029 | } |
812 | else | 1030 | while (--count > 0); |
1031 | } | ||
1032 | #endif /* DSP_HAVE_ASM_SOUND_CHAN_KARAOKE */ | ||
1033 | |||
1034 | void channels_set(int value) | ||
1035 | { | ||
1036 | static void (* const channels_process_functions[])( | ||
1037 | int count, int32_t *buf[]) = | ||
813 | { | 1038 | { |
814 | long min = dsp->clip_min; | 1039 | /* SOUND_CHAN_STEREO = All-purpose index for no channel processing */ |
815 | long max = dsp->clip_max; | 1040 | [SOUND_CHAN_STEREO] = NULL, |
1041 | [SOUND_CHAN_MONO] = channels_process_sound_chan_mono, | ||
1042 | [SOUND_CHAN_CUSTOM] = channels_process_sound_chan_custom, | ||
1043 | [SOUND_CHAN_MONO_LEFT] = channels_process_sound_chan_mono_left, | ||
1044 | [SOUND_CHAN_MONO_RIGHT] = channels_process_sound_chan_mono_right, | ||
1045 | [SOUND_CHAN_KARAOKE] = channels_process_sound_chan_karaoke, | ||
1046 | }; | ||
816 | 1047 | ||
817 | while (count-- > 0) | 1048 | if ((unsigned)value >= ARRAYLEN(channels_process_functions) || |
818 | { | 1049 | audio_dsp->stereo_mode == STEREO_MONO) |
819 | *dst++ = (short) (clip_sample(*s0++, min, max) >> scale); | 1050 | value = SOUND_CHAN_STEREO; |
820 | *dst++ = (short) (clip_sample(*s1++, min, max) >> scale); | 1051 | |
821 | } | 1052 | /* This doesn't apply to voice */ |
822 | } | 1053 | channels_mode = value; |
1054 | audio_dsp->channels_process = channels_process_functions[value]; | ||
823 | } | 1055 | } |
824 | 1056 | ||
825 | /* Process and convert src audio to dst based on the DSP configuration, | 1057 | /* Process and convert src audio to dst based on the DSP configuration, |
@@ -832,7 +1064,7 @@ static void write_samples(short* dst, int32_t* src[], int count) | |||
832 | */ | 1064 | */ |
833 | int dsp_process(char *dst, const char *src[], int count) | 1065 | int dsp_process(char *dst, const char *src[], int count) |
834 | { | 1066 | { |
835 | int32_t* tmp[2]; | 1067 | int32_t *tmp[2]; |
836 | int written = 0; | 1068 | int written = 0; |
837 | int samples; | 1069 | int samples; |
838 | 1070 | ||
@@ -843,27 +1075,23 @@ int dsp_process(char *dst, const char *src[], int count) | |||
843 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); | 1075 | coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); |
844 | #endif | 1076 | #endif |
845 | 1077 | ||
846 | dsp = &dsp_conf[current_codec]; | ||
847 | |||
848 | dsp_set_replaygain(false); | ||
849 | |||
850 | while (count > 0) | 1078 | while (count > 0) |
851 | { | 1079 | { |
852 | samples = dsp->convert_to_internal(src, tmp, count); | 1080 | samples = dsp->input_samples(count, src, tmp); |
853 | count -= samples; | 1081 | count -= samples; |
854 | apply_gain(tmp, samples); | 1082 | if (dsp->gain != 0) |
855 | samples = resample(tmp, samples); | 1083 | apply_gain(samples, tmp); |
856 | if (samples <= 0) | 1084 | if ((samples = resample(samples, tmp)) <= 0) |
857 | break; /* I'm pretty sure we're downsampling here */ | 1085 | break; /* I'm pretty sure we're downsampling here */ |
858 | if (dsp->crossfeed_enabled && dsp->stereo_mode != STEREO_MONO) | 1086 | if (dsp->apply_crossfeed) |
859 | apply_crossfeed(tmp, samples); | 1087 | dsp->apply_crossfeed(tmp, samples); |
860 | if (dsp->eq_enabled) | 1088 | if (eq_enabled) |
861 | eq_process(tmp, samples); | 1089 | eq_process(samples, tmp); |
862 | if (dsp->stereo_mode != STEREO_MONO) | 1090 | if (dsp->channels_process) |
863 | channels_process(tmp, samples); | 1091 | dsp->channels_process(samples, tmp); |
864 | write_samples((short*) dst, tmp, samples); | 1092 | dsp->output_samples(samples, &dsp->data, tmp, (int16_t *)dst); |
865 | written += samples; | 1093 | written += samples; |
866 | dst += samples * sizeof(short) * 2; | 1094 | dst += samples * sizeof (int16_t) * 2; |
867 | yield(); | 1095 | yield(); |
868 | } | 1096 | } |
869 | 1097 | ||
@@ -883,21 +1111,19 @@ int dsp_process(char *dst, const char *src[], int count) | |||
883 | /* dsp_input_size MUST be called afterwards */ | 1111 | /* dsp_input_size MUST be called afterwards */ |
884 | int dsp_output_count(int count) | 1112 | int dsp_output_count(int count) |
885 | { | 1113 | { |
886 | dsp = &dsp_conf[current_codec]; | 1114 | if (dsp->resample) |
887 | |||
888 | if (dsp->frequency != NATIVE_FREQUENCY) | ||
889 | { | 1115 | { |
890 | count = (int)(((unsigned long)count * NATIVE_FREQUENCY | 1116 | count = (int)(((unsigned long)count * NATIVE_FREQUENCY |
891 | + (dsp->frequency - 1)) / dsp->frequency); | 1117 | + (dsp->frequency - 1)) / dsp->frequency); |
892 | } | ||
893 | 1118 | ||
894 | /* Now we have the resampled sample count which must not exceed | 1119 | /* Now we have the resampled sample count which must not exceed |
895 | * RESAMPLE_BUF_COUNT/2 to avoid resample buffer overflow. One | 1120 | * RESAMPLE_BUF_COUNT/2 to avoid resample buffer overflow. One |
896 | * must call dsp_input_count() to get the correct input sample | 1121 | * must call dsp_input_count() to get the correct input sample |
897 | * count. | 1122 | * count. |
898 | */ | 1123 | */ |
899 | if (count > RESAMPLE_BUF_COUNT/2) | 1124 | if (count > RESAMPLE_BUF_COUNT/2) |
900 | count = RESAMPLE_BUF_COUNT/2; | 1125 | count = RESAMPLE_BUF_COUNT/2; |
1126 | } | ||
901 | 1127 | ||
902 | return count; | 1128 | return count; |
903 | } | 1129 | } |
@@ -907,17 +1133,15 @@ int dsp_output_count(int count) | |||
907 | */ | 1133 | */ |
908 | int dsp_input_count(int count) | 1134 | int dsp_input_count(int count) |
909 | { | 1135 | { |
910 | dsp = &dsp_conf[current_codec]; | ||
911 | |||
912 | /* count is now the number of resampled input samples. Convert to | 1136 | /* count is now the number of resampled input samples. Convert to |
913 | original input samples. */ | 1137 | original input samples. */ |
914 | if (dsp->frequency != NATIVE_FREQUENCY) | 1138 | if (dsp->resample) |
915 | { | 1139 | { |
916 | /* Use the real resampling delta = | 1140 | /* Use the real resampling delta = |
917 | * dsp->frequency * 65536 / NATIVE_FREQUENCY, and | 1141 | * dsp->frequency * 65536 / NATIVE_FREQUENCY, and |
918 | * round towards zero to avoid buffer overflows. */ | 1142 | * round towards zero to avoid buffer overflows. */ |
919 | count = (int)(((unsigned long)count * | 1143 | count = (int)(((unsigned long)count * |
920 | resample_data[current_codec].delta) >> 16); | 1144 | dsp->data.resample_data.delta) >> 16); |
921 | } | 1145 | } |
922 | 1146 | ||
923 | return count; | 1147 | return count; |
@@ -925,20 +1149,39 @@ int dsp_input_count(int count) | |||
925 | 1149 | ||
926 | int dsp_stereo_mode(void) | 1150 | int dsp_stereo_mode(void) |
927 | { | 1151 | { |
928 | dsp = &dsp_conf[current_codec]; | ||
929 | |||
930 | return dsp->stereo_mode; | 1152 | return dsp->stereo_mode; |
931 | } | 1153 | } |
932 | 1154 | ||
933 | bool dsp_configure(int setting, intptr_t value) | 1155 | bool dsp_configure(int setting, intptr_t value) |
934 | { | 1156 | { |
935 | dsp = &dsp_conf[current_codec]; | 1157 | void set_gain_var(long *var, long value) |
1158 | { | ||
1159 | /* Voice shouldn't mess with these */ | ||
1160 | if (dsp != audio_dsp) | ||
1161 | return; | ||
1162 | |||
1163 | *var = value; | ||
1164 | new_gain = true; | ||
1165 | } | ||
1166 | |||
1167 | void update_functions(void) | ||
1168 | { | ||
1169 | sample_input_new_format(); | ||
1170 | sample_output_new_format(); | ||
1171 | if (dsp == audio_dsp) | ||
1172 | dsp_set_crossfeed(crossfeed_enabled); | ||
1173 | } | ||
936 | 1174 | ||
937 | switch (setting) | 1175 | switch (setting) |
938 | { | 1176 | { |
1177 | case DSP_SWITCH_CODEC: | ||
1178 | if ((uintptr_t)value <= 1) | ||
1179 | switch_dsp(&dsp_conf[value]); | ||
1180 | break; | ||
1181 | |||
939 | case DSP_SET_FREQUENCY: | 1182 | case DSP_SET_FREQUENCY: |
940 | memset(&resample_data[current_codec], 0, | 1183 | memset(&dsp->data.resample_data, 0, |
941 | sizeof(struct resample_data)); | 1184 | sizeof (dsp->data.resample_data)); |
942 | /* Fall through!!! */ | 1185 | /* Fall through!!! */ |
943 | case DSP_SWITCH_FREQUENCY: | 1186 | case DSP_SWITCH_FREQUENCY: |
944 | dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value; | 1187 | dsp->codec_frequency = (value == 0) ? NATIVE_FREQUENCY : value; |
@@ -946,19 +1189,20 @@ bool dsp_configure(int setting, intptr_t value) | |||
946 | if we're called from the main audio thread. Voice UI thread should | 1189 | if we're called from the main audio thread. Voice UI thread should |
947 | not need this feature. | 1190 | not need this feature. |
948 | */ | 1191 | */ |
949 | if (current_codec == CODEC_IDX_AUDIO) | 1192 | if (dsp == audio_dsp) |
950 | dsp->frequency = pitch_ratio * dsp->codec_frequency / 1000; | 1193 | dsp->frequency = pitch_ratio * dsp->codec_frequency / 1000; |
951 | else | 1194 | else |
952 | dsp->frequency = dsp->codec_frequency; | 1195 | dsp->frequency = dsp->codec_frequency; |
953 | resampler_set_delta(dsp->frequency); | ||
954 | break; | ||
955 | 1196 | ||
956 | case DSP_SET_CLIP_MIN: | 1197 | resampler_set_delta(dsp->frequency); |
957 | dsp->clip_min = value; | 1198 | |
958 | break; | 1199 | if (dsp->frequency == NATIVE_FREQUENCY) |
1200 | dsp->resample = NULL; | ||
1201 | else if (dsp->frequency < NATIVE_FREQUENCY) | ||
1202 | dsp->resample = dsp_upsample; | ||
1203 | else | ||
1204 | dsp->resample = dsp_downsample; | ||
959 | 1205 | ||
960 | case DSP_SET_CLIP_MAX: | ||
961 | dsp->clip_max = value; | ||
962 | break; | 1206 | break; |
963 | 1207 | ||
964 | case DSP_SET_SAMPLE_DEPTH: | 1208 | case DSP_SET_SAMPLE_DEPTH: |
@@ -967,69 +1211,73 @@ bool dsp_configure(int setting, intptr_t value) | |||
967 | if (dsp->sample_depth <= NATIVE_DEPTH) | 1211 | if (dsp->sample_depth <= NATIVE_DEPTH) |
968 | { | 1212 | { |
969 | dsp->frac_bits = WORD_FRACBITS; | 1213 | dsp->frac_bits = WORD_FRACBITS; |
970 | dsp->sample_bytes = sizeof(short); | 1214 | dsp->sample_bytes = sizeof (int16_t); /* samples are 16 bits */ |
971 | dsp->clip_max = ((1 << WORD_FRACBITS) - 1); | 1215 | dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1); |
972 | dsp->clip_min = -((1 << WORD_FRACBITS)); | 1216 | dsp->data.clip_min = -((1 << WORD_FRACBITS)); |
973 | } | 1217 | } |
974 | else | 1218 | else |
975 | { | 1219 | { |
976 | dsp->frac_bits = value; | 1220 | dsp->frac_bits = value; |
977 | dsp->sample_bytes = 4; /* samples are 32 bits */ | 1221 | dsp->sample_bytes = sizeof (int32_t); /* samples are 32 bits */ |
978 | dsp->clip_max = (1 << value) - 1; | 1222 | dsp->data.clip_max = (1 << value) - 1; |
979 | dsp->clip_min = -(1 << value); | 1223 | dsp->data.clip_min = -(1 << value); |
980 | } | 1224 | } |
981 | 1225 | ||
982 | new_sample_conversion(); | 1226 | dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH; |
1227 | sample_input_new_format(); | ||
983 | dither_init(); | 1228 | dither_init(); |
984 | break; | 1229 | break; |
985 | 1230 | ||
986 | case DSP_SET_STEREO_MODE: | 1231 | case DSP_SET_STEREO_MODE: |
987 | dsp->stereo_mode = value; | 1232 | dsp->stereo_mode = value; |
988 | dsp->num_channels = value == STEREO_MONO ? 1 : 2; | 1233 | dsp->data.num_channels = value == STEREO_MONO ? 1 : 2; |
989 | new_sample_conversion(); | 1234 | update_functions(); |
990 | break; | 1235 | break; |
991 | 1236 | ||
992 | case DSP_RESET: | 1237 | case DSP_RESET: |
993 | dsp->stereo_mode = STEREO_NONINTERLEAVED; | 1238 | dsp->stereo_mode = STEREO_NONINTERLEAVED; |
994 | dsp->num_channels = 2; | 1239 | dsp->data.num_channels = 2; |
995 | dsp->clip_max = ((1 << WORD_FRACBITS) - 1); | ||
996 | dsp->clip_min = -((1 << WORD_FRACBITS)); | ||
997 | dsp->track_gain = 0; | ||
998 | dsp->album_gain = 0; | ||
999 | dsp->track_peak = 0; | ||
1000 | dsp->album_peak = 0; | ||
1001 | dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY; | ||
1002 | dsp->sample_depth = NATIVE_DEPTH; | 1240 | dsp->sample_depth = NATIVE_DEPTH; |
1003 | dsp->frac_bits = WORD_FRACBITS; | 1241 | dsp->frac_bits = WORD_FRACBITS; |
1004 | dsp->new_gain = true; | 1242 | dsp->sample_bytes = sizeof (int16_t); |
1005 | new_sample_conversion(); | 1243 | dsp->data.output_scale = dsp->frac_bits + 1 - NATIVE_DEPTH; |
1244 | dsp->data.clip_max = ((1 << WORD_FRACBITS) - 1); | ||
1245 | dsp->data.clip_min = -((1 << WORD_FRACBITS)); | ||
1246 | dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY; | ||
1247 | |||
1248 | if (dsp == audio_dsp) | ||
1249 | { | ||
1250 | track_gain = 0; | ||
1251 | album_gain = 0; | ||
1252 | track_peak = 0; | ||
1253 | album_peak = 0; | ||
1254 | new_gain = true; | ||
1255 | } | ||
1256 | |||
1257 | update_functions(); | ||
1006 | break; | 1258 | break; |
1007 | 1259 | ||
1008 | case DSP_FLUSH: | 1260 | case DSP_FLUSH: |
1009 | memset(&resample_data[current_codec], 0, | 1261 | memset(&dsp->data.resample_data, 0, |
1010 | sizeof (struct resample_data)); | 1262 | sizeof (dsp->data.resample_data)); |
1011 | resampler_set_delta(dsp->frequency); | 1263 | resampler_set_delta(dsp->frequency); |
1012 | dither_init(); | 1264 | dither_init(); |
1013 | break; | 1265 | break; |
1014 | 1266 | ||
1015 | case DSP_SET_TRACK_GAIN: | 1267 | case DSP_SET_TRACK_GAIN: |
1016 | dsp->track_gain = (long) value; | 1268 | set_gain_var(&track_gain, value); |
1017 | dsp->new_gain = true; | ||
1018 | break; | 1269 | break; |
1019 | 1270 | ||
1020 | case DSP_SET_ALBUM_GAIN: | 1271 | case DSP_SET_ALBUM_GAIN: |
1021 | dsp->album_gain = (long) value; | 1272 | set_gain_var(&album_gain, value); |
1022 | dsp->new_gain = true; | ||
1023 | break; | 1273 | break; |
1024 | 1274 | ||
1025 | case DSP_SET_TRACK_PEAK: | 1275 | case DSP_SET_TRACK_PEAK: |
1026 | dsp->track_peak = (long) value; | 1276 | set_gain_var(&track_peak, value); |
1027 | dsp->new_gain = true; | ||
1028 | break; | 1277 | break; |
1029 | 1278 | ||
1030 | case DSP_SET_ALBUM_PEAK: | 1279 | case DSP_SET_ALBUM_PEAK: |
1031 | dsp->album_peak = (long) value; | 1280 | set_gain_var(&album_peak, value); |
1032 | dsp->new_gain = true; | ||
1033 | break; | 1281 | break; |
1034 | 1282 | ||
1035 | default: | 1283 | default: |
@@ -1039,59 +1287,51 @@ bool dsp_configure(int setting, intptr_t value) | |||
1039 | return 1; | 1287 | return 1; |
1040 | } | 1288 | } |
1041 | 1289 | ||
1042 | void dsp_set_replaygain(bool always) | 1290 | void dsp_set_replaygain(void) |
1043 | { | 1291 | { |
1044 | dsp = &dsp_conf[current_codec]; | 1292 | long gain = 0; |
1045 | |||
1046 | if (always || dsp->new_gain) | ||
1047 | { | ||
1048 | long gain = 0; | ||
1049 | 1293 | ||
1050 | dsp->new_gain = false; | 1294 | new_gain = false; |
1051 | |||
1052 | if (global_settings.replaygain || global_settings.replaygain_noclip) | ||
1053 | { | ||
1054 | bool track_mode = get_replaygain_mode(dsp->track_gain != 0, | ||
1055 | dsp->album_gain != 0) == REPLAYGAIN_TRACK; | ||
1056 | long peak = (track_mode || !dsp->album_peak) | ||
1057 | ? dsp->track_peak : dsp->album_peak; | ||
1058 | |||
1059 | if (global_settings.replaygain) | ||
1060 | { | ||
1061 | gain = (track_mode || !dsp->album_gain) | ||
1062 | ? dsp->track_gain : dsp->album_gain; | ||
1063 | 1295 | ||
1064 | if (global_settings.replaygain_preamp) | 1296 | if (global_settings.replaygain || global_settings.replaygain_noclip) |
1065 | { | 1297 | { |
1066 | long preamp = get_replaygain_int( | 1298 | bool track_mode = get_replaygain_mode(track_gain != 0, |
1067 | global_settings.replaygain_preamp * 10); | 1299 | album_gain != 0) == REPLAYGAIN_TRACK; |
1300 | long peak = (track_mode || !album_peak) ? track_peak : album_peak; | ||
1068 | 1301 | ||
1069 | gain = (long) (((int64_t) gain * preamp) >> 24); | 1302 | if (global_settings.replaygain) |
1070 | } | 1303 | { |
1071 | } | 1304 | gain = (track_mode || !album_gain) ? track_gain : album_gain; |
1072 | 1305 | ||
1073 | if (gain == 0) | 1306 | if (global_settings.replaygain_preamp) |
1074 | { | 1307 | { |
1075 | /* So that noclip can work even with no gain information. */ | 1308 | long preamp = get_replaygain_int( |
1076 | gain = DEFAULT_GAIN; | 1309 | global_settings.replaygain_preamp * 10); |
1077 | } | ||
1078 | 1310 | ||
1079 | if (global_settings.replaygain_noclip && (peak != 0) | 1311 | gain = (long) (((int64_t) gain * preamp) >> 24); |
1080 | && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN)) | ||
1081 | { | ||
1082 | gain = (((int64_t) DEFAULT_GAIN << 24) / peak); | ||
1083 | } | 1312 | } |
1313 | } | ||
1084 | 1314 | ||
1085 | if (gain == DEFAULT_GAIN) | 1315 | if (gain == 0) |
1086 | { | 1316 | { |
1087 | /* Nothing to do, disable processing. */ | 1317 | /* So that noclip can work even with no gain information. */ |
1088 | gain = 0; | 1318 | gain = DEFAULT_GAIN; |
1319 | } | ||
1089 | 1320 | ||
1090 | } | 1321 | if (global_settings.replaygain_noclip && (peak != 0) |
1322 | && ((((int64_t) gain * peak) >> 24) >= DEFAULT_GAIN)) | ||
1323 | { | ||
1324 | gain = (((int64_t) DEFAULT_GAIN << 24) / peak); | ||
1091 | } | 1325 | } |
1092 | 1326 | ||
1093 | /* Store in S8.23 format to simplify calculations. */ | 1327 | if (gain == DEFAULT_GAIN) |
1094 | dsp->replaygain = gain; | 1328 | { |
1095 | set_gain(); | 1329 | /* Nothing to do, disable processing. */ |
1330 | gain = 0; | ||
1331 | } | ||
1096 | } | 1332 | } |
1333 | |||
1334 | /* Store in S8.23 format to simplify calculations. */ | ||
1335 | replaygain = gain; | ||
1336 | set_gain(audio_dsp); | ||
1097 | } | 1337 | } |