summaryrefslogtreecommitdiff
path: root/apps/dsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/dsp.c')
-rw-r--r--apps/dsp.c145
1 files changed, 84 insertions, 61 deletions
diff --git a/apps/dsp.c b/apps/dsp.c
index 35f9cb66bd..3d02f5a630 100644
--- a/apps/dsp.c
+++ b/apps/dsp.c
@@ -128,7 +128,8 @@
128 128
129struct dsp_config 129struct dsp_config
130{ 130{
131 long frequency; 131 long codec_frequency; /* Sample rate of data coming from the codec */
132 long frequency; /* Effective sample rate after pitch shift (if any) */
132 long clip_min; 133 long clip_min;
133 long clip_max; 134 long clip_max;
134 long track_gain; 135 long track_gain;
@@ -147,9 +148,8 @@ struct dsp_config
147 148
148struct resample_data 149struct resample_data
149{ 150{
150 long last_sample; 151 long phase, delta;
151 long phase; 152 long last_sample[2];
152 long delta;
153}; 153};
154 154
155struct dither_data 155struct dither_data
@@ -168,9 +168,11 @@ struct crossfeed_data
168 168
169static struct dsp_config dsp_conf[2] IBSS_ATTR; 169static struct dsp_config dsp_conf[2] IBSS_ATTR;
170static struct dither_data dither_data[2] IBSS_ATTR; 170static struct dither_data dither_data[2] IBSS_ATTR;
171static struct resample_data resample_data[2][2] IBSS_ATTR; 171static struct resample_data resample_data[2] IBSS_ATTR;
172struct crossfeed_data crossfeed_data IBSS_ATTR; 172struct crossfeed_data crossfeed_data IBSS_ATTR;
173 173
174static int pitch_ratio = 1000;
175
174extern int current_codec; 176extern int current_codec;
175struct dsp_config *dsp; 177struct dsp_config *dsp;
176 178
@@ -182,6 +184,18 @@ struct dsp_config *dsp;
182static long sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR; 184static long sample_buf[SAMPLE_BUF_SIZE] IBSS_ATTR;
183static long resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR; 185static long resample_buf[RESAMPLE_BUF_SIZE] IBSS_ATTR;
184 186
187int sound_get_pitch(void)
188{
189 return pitch_ratio;
190}
191
192void sound_set_pitch(int permille)
193{
194 pitch_ratio = permille;
195
196 dsp_configure(DSP_SWITCH_FREQUENCY, (int *)dsp->codec_frequency);
197}
198
185/* Convert at most count samples to the internal format, if needed. Returns 199/* Convert at most count samples to the internal format, if needed. Returns
186 * number of samples ready for further processing. Updates src to point 200 * number of samples ready for further processing. Updates src to point
187 * past the samples "consumed" and dst is set to point to the samples to 201 * past the samples "consumed" and dst is set to point to the samples to
@@ -270,64 +284,81 @@ static int convert_to_internal(char* src[], int count, long* dst[])
270 return count; 284 return count;
271} 285}
272 286
287static void resampler_set_delta(int frequency)
288{
289 resample_data[current_codec].delta = (unsigned long)
290 frequency * 65536LL / NATIVE_FREQUENCY;
291}
292
273/* Linear resampling that introduces a one sample delay, because of our 293/* Linear resampling that introduces a one sample delay, because of our
274 * inability to look into the future at the end of a frame. 294 * inability to look into the future at the end of a frame.
275 */ 295 */
276 296
277static long downsample(long *dst, long *src, int count, 297/* TODO: we really should have a separate set of resample functions for both
298 mono and stereo to avoid all this internal branching and looping. */
299static long downsample(long **dst, long **src, int count,
278 struct resample_data *r) 300 struct resample_data *r)
279{ 301{
280 long phase = r->phase; 302 long phase = r->phase;
281 long delta = r->delta; 303 long delta = r->delta;
282 long last_sample = r->last_sample; 304 long last_sample;
305 long *d[2] = { dst[0], dst[1] };
283 int pos = phase >> 16; 306 int pos = phase >> 16;
284 int i = 1; 307 int i = 1, j;
285 308 int num_channels = src[0] == src[1] ? 1 : 2;
286 /* Do we need last sample of previous frame for interpolation? */ 309
287 if (pos > 0) 310 for (j = 0; j < num_channels; j++) {
288 { 311 last_sample = r->last_sample[j];
289 last_sample = src[pos - 1]; 312 /* Do we need last sample of previous frame for interpolation? */
313 if (pos > 0)
314 {
315 last_sample = src[j][pos - 1];
316 }
317 *d[j]++ = last_sample + FRACMUL((phase & 0xffff) << 15,
318 src[j][pos] - last_sample);
290 } 319 }
291
292 *dst++ = last_sample + FRACMUL((phase & 0xffff) << 15,
293 src[pos] - last_sample);
294 phase += delta; 320 phase += delta;
295 321
296 while ((pos = phase >> 16) < count) 322 while ((pos = phase >> 16) < count)
297 { 323 {
298 *dst++ = src[pos - 1] + FRACMUL((phase & 0xffff) << 15, 324 for (j = 0; j < num_channels; j++)
299 src[pos] - src[pos - 1]); 325 *d[j]++ = src[j][pos - 1] + FRACMUL((phase & 0xffff) << 15,
300 phase += delta; 326 src[j][pos] - src[j][pos - 1]);
301 i++; 327 phase += delta;
328 i++;
302 } 329 }
303 330
304 /* Wrap phase accumulator back to start of next frame. */ 331 /* Wrap phase accumulator back to start of next frame. */
305 r->phase = phase - (count << 16); 332 r->phase = phase - (count << 16);
306 r->delta = delta; 333 r->delta = delta;
307 r->last_sample = src[count - 1]; 334 r->last_sample[0] = src[0][count - 1];
335 r->last_sample[1] = src[1][count - 1];
308 return i; 336 return i;
309} 337}
310 338
311static long upsample(long *dst, long *src, int count, struct resample_data *r) 339static long upsample(long **dst, long **src, int count, struct resample_data *r)
312{ 340{
313 long phase = r->phase; 341 long phase = r->phase;
314 long delta = r->delta; 342 long delta = r->delta;
315 long last_sample = r->last_sample; 343 long *d[2] = { dst[0], dst[1] };
316 int i = 0; 344 int i = 0, j;
317 int pos; 345 int pos;
318 346 int num_channels = src[0] == src[1] ? 1 : 2;
347
319 while ((pos = phase >> 16) == 0) 348 while ((pos = phase >> 16) == 0)
320 { 349 {
321 *dst++ = last_sample + FRACMUL((phase & 0xffff) << 15, 350 for (j = 0; j < num_channels; j++)
322 src[pos] - last_sample); 351 *d[j]++ = r->last_sample[j] + FRACMUL((phase & 0xffff) << 15,
352 src[j][pos] - r->last_sample[j]);
323 phase += delta; 353 phase += delta;
324 i++; 354 i++;
325 } 355 }
326 356
327 while ((pos = phase >> 16) < count) 357 while ((pos = phase >> 16) < count)
328 { 358 {
329 *dst++ = src[pos - 1] + FRACMUL((phase & 0xffff) << 15, 359 for (j = 0; j < num_channels; j++)
330 src[pos] - src[pos - 1]); 360 *d[j]++ = src[j][pos - 1] + FRACMUL((phase & 0xffff) << 15,
361 src[j][pos] - src[j][pos - 1]);
331 phase += delta; 362 phase += delta;
332 i++; 363 i++;
333 } 364 }
@@ -335,7 +366,8 @@ static long upsample(long *dst, long *src, int count, struct resample_data *r)
335 /* Wrap phase accumulator back to start of next frame. */ 366 /* Wrap phase accumulator back to start of next frame. */
336 r->phase = phase - (count << 16); 367 r->phase = phase - (count << 16);
337 r->delta = delta; 368 r->delta = delta;
338 r->last_sample = src[count - 1]; 369 r->last_sample[0] = src[0][count - 1];
370 r->last_sample[1] = src[1][count - 1];
339 return i; 371 return i;
340} 372}
341 373
@@ -349,36 +381,21 @@ static inline int resample(long* src[], int count)
349 381
350 if (dsp->frequency != NATIVE_FREQUENCY) 382 if (dsp->frequency != NATIVE_FREQUENCY)
351 { 383 {
352 long* d0 = &resample_buf[0]; 384 long* dst[2] = {&resample_buf[0], &resample_buf[RESAMPLE_BUF_SIZE / 2]};
353 /* Only process the second channel if needed. */
354 long* d1 = (src[0] == src[1]) ? d0
355 : &resample_buf[RESAMPLE_BUF_SIZE / 2];
356 385
357 if (dsp->frequency < NATIVE_FREQUENCY) 386 if (dsp->frequency < NATIVE_FREQUENCY)
358 { 387 {
359 new_count = upsample(d0, src[0], count, 388 new_count = upsample(dst, src, count,
360 &resample_data[current_codec][0]); 389 &resample_data[current_codec]);
361
362 if (d0 != d1)
363 {
364 upsample(d1, src[1], count,
365 &resample_data[current_codec][1]);
366 }
367 } 390 }
368 else 391 else
369 { 392 {
370 new_count = downsample(d0, src[0], count, 393 new_count = downsample(dst, src, count,
371 &resample_data[current_codec][0]); 394 &resample_data[current_codec]);
372
373 if (d0 != d1)
374 {
375 downsample(d1, src[1], count,
376 &resample_data[current_codec][1]);
377 }
378 } 395 }
379 396
380 src[0] = d0; 397 src[0] = dst[0];
381 src[1] = d1; 398 src[1] = dst[1];
382 } 399 }
383 else 400 else
384 { 401 {
@@ -767,7 +784,7 @@ long dsp_input_size(long size)
767 * (unsigned long) dsp->frequency * 65536 / NATIVE_FREQUENCY, and 784 * (unsigned long) dsp->frequency * 65536 / NATIVE_FREQUENCY, and
768 * round towards zero to avoid buffer overflows. */ 785 * round towards zero to avoid buffer overflows. */
769 size = ((unsigned long)size * 786 size = ((unsigned long)size *
770 resample_data[current_codec][0].delta) >> 16; 787 resample_data[current_codec].delta) >> 16;
771 } 788 }
772 789
773 /* Convert back to bytes. */ 790 /* Convert back to bytes. */
@@ -793,14 +810,20 @@ bool dsp_configure(int setting, void *value)
793 switch (setting) 810 switch (setting)
794 { 811 {
795 case DSP_SET_FREQUENCY: 812 case DSP_SET_FREQUENCY:
796 memset(&resample_data[current_codec][0], 0, 813 memset(&resample_data[current_codec], 0,
797 sizeof(struct resample_data) * 2); 814 sizeof(struct resample_data));
798 /* Fall through!!! */ 815 /* Fall through!!! */
799 case DSP_SWITCH_FREQUENCY: 816 case DSP_SWITCH_FREQUENCY:
800 dsp->frequency = ((int) value == 0) ? NATIVE_FREQUENCY : (int) value; 817 dsp->codec_frequency = ((int) value == 0) ? NATIVE_FREQUENCY : (int) value;
801 resample_data[current_codec][0].delta = 818 /* Account for playback speed adjustment when settingg dsp->frequency
802 resample_data[current_codec][1].delta = 819 if we're called from the main audio thread. Voice UI thread should
803 (unsigned long) dsp->frequency * 65536 / NATIVE_FREQUENCY; 820 not need this feature.
821 */
822 if (current_codec == CODEC_IDX_AUDIO)
823 dsp->frequency = pitch_ratio * dsp->codec_frequency / 1000;
824 else
825 dsp->frequency = dsp->codec_frequency;
826 resampler_set_delta(dsp->frequency);
804 break; 827 break;
805 828
806 case DSP_SET_CLIP_MIN: 829 case DSP_SET_CLIP_MIN:
@@ -844,7 +867,7 @@ bool dsp_configure(int setting, void *value)
844 dsp->album_gain = 0; 867 dsp->album_gain = 0;
845 dsp->track_peak = 0; 868 dsp->track_peak = 0;
846 dsp->album_peak = 0; 869 dsp->album_peak = 0;
847 dsp->frequency = NATIVE_FREQUENCY; 870 dsp->codec_frequency = dsp->frequency = NATIVE_FREQUENCY;
848 dsp->sample_depth = NATIVE_DEPTH; 871 dsp->sample_depth = NATIVE_DEPTH;
849 dsp->frac_bits = WORD_FRACBITS; 872 dsp->frac_bits = WORD_FRACBITS;
850 dsp->new_gain = true; 873 dsp->new_gain = true;