summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorThom Johansen <thomj@rockbox.org>2005-11-28 22:26:20 +0000
committerThom Johansen <thomj@rockbox.org>2005-11-28 22:26:20 +0000
commit27c658c8a655ebe4f8160c24486867aca2900754 (patch)
tree9b91b1275e1c0ed493af477f5656f5edfb42b9aa /apps
parent1d6eeea1e196b6d7beefab70a6ee664340ab7bef (diff)
downloadrockbox-27c658c8a655ebe4f8160c24486867aca2900754.tar.gz
rockbox-27c658c8a655ebe4f8160c24486867aca2900754.zip
Enabled playback speed adjustment support for H1x0. Modified the resampler to do both channels in one pass.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@8099 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps')
-rw-r--r--apps/dsp.c145
-rw-r--r--apps/dsp.h3
-rw-r--r--apps/playback.c3
-rw-r--r--apps/playback.h3
-rw-r--r--apps/screens.c13
-rw-r--r--apps/screens.h4
6 files changed, 101 insertions, 70 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;
diff --git a/apps/dsp.h b/apps/dsp.h
index f250d89708..f86a4d9989 100644
--- a/apps/dsp.h
+++ b/apps/dsp.h
@@ -54,5 +54,6 @@ int dsp_stereo_mode(void);
54bool dsp_configure(int setting, void *value); 54bool dsp_configure(int setting, void *value);
55void dsp_set_replaygain(bool always); 55void dsp_set_replaygain(bool always);
56void dsp_set_crossfeed(bool enable); 56void dsp_set_crossfeed(bool enable);
57 57void sound_set_pitch(int r);
58int sound_get_pitch(void);
58#endif 59#endif
diff --git a/apps/playback.c b/apps/playback.c
index 41659cbd6b..563fb741ed 100644
--- a/apps/playback.c
+++ b/apps/playback.c
@@ -133,9 +133,6 @@ static struct mutex mutex_codecthread;
133 133
134static struct mp3entry id3_voice; 134static struct mp3entry id3_voice;
135 135
136#define CODEC_IDX_AUDIO 0
137#define CODEC_IDX_VOICE 1
138
139static char *voicebuf; 136static char *voicebuf;
140static int voice_remaining; 137static int voice_remaining;
141static bool voice_is_playing; 138static bool voice_is_playing;
diff --git a/apps/playback.h b/apps/playback.h
index 8128cc2490..befaae8086 100644
--- a/apps/playback.h
+++ b/apps/playback.h
@@ -27,6 +27,9 @@
27#include "id3.h" 27#include "id3.h"
28#include "mp3data.h" 28#include "mp3data.h"
29 29
30#define CODEC_IDX_AUDIO 0
31#define CODEC_IDX_VOICE 1
32
30/* Not yet implemented. */ 33/* Not yet implemented. */
31#define CODEC_SET_AUDIOBUF_WATERMARK 4 34#define CODEC_SET_AUDIOBUF_WATERMARK 4
32 35
diff --git a/apps/screens.c b/apps/screens.c
index 1693c31957..8bf18dc6c6 100644
--- a/apps/screens.c
+++ b/apps/screens.c
@@ -342,11 +342,16 @@ int charging_screen(void)
342#endif /* HAVE_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING */ 342#endif /* HAVE_CHARGING && !HAVE_POWEROFF_WHILE_CHARGING */
343 343
344 344
345#if CONFIG_KEYPAD == RECORDER_PAD 345#if CONFIG_KEYPAD == RECORDER_PAD || CONFIG_KEYPAD == IRIVER_H100_PAD
346/* returns: 346/* returns:
347 0 if no key was pressed 347 0 if no key was pressed
348 1 if a key was pressed (or if ON was held down long enough to repeat) 348 1 if a key was pressed (or if ON was held down long enough to repeat)
349 2 if USB was connected */ 349 2 if USB was connected */
350#if CONFIG_KEYPAD == RECORDER_PAD
351#define PITCH_PAUSE BUTTON_PLAY
352#elif CONFIG_KEYPAD == IRIVER_H100_PAD
353#define PITCH_PAUSE BUTTON_SELECT
354#endif
350int pitch_screen(void) 355int pitch_screen(void)
351{ 356{
352 int button; 357 int button;
@@ -411,17 +416,17 @@ int pitch_screen(void)
411 sound_set_pitch(pitch); 416 sound_set_pitch(pitch);
412 break; 417 break;
413 418
414 case BUTTON_ON | BUTTON_PLAY: 419 case BUTTON_ON | PITCH_PAUSE:
415 audio_pause(); 420 audio_pause();
416 used = true; 421 used = true;
417 break; 422 break;
418 423
419 case BUTTON_PLAY | BUTTON_REL: 424 case PITCH_PAUSE | BUTTON_REL:
420 audio_resume(); 425 audio_resume();
421 used = true; 426 used = true;
422 break; 427 break;
423 428
424 case BUTTON_ON | BUTTON_PLAY | BUTTON_REL: 429 case BUTTON_ON | PITCH_PAUSE | BUTTON_REL:
425 audio_resume(); 430 audio_resume();
426 exit = true; 431 exit = true;
427 break; 432 break;
diff --git a/apps/screens.h b/apps/screens.h
index f879da264c..ea5e9440c8 100644
--- a/apps/screens.h
+++ b/apps/screens.h
@@ -33,8 +33,10 @@ void charging_splash(void);
33int mmc_remove_request(void); 33int mmc_remove_request(void);
34#endif 34#endif
35 35
36#if CONFIG_KEYPAD == RECORDER_PAD 36#if CONFIG_KEYPAD == RECORDER_PAD || defined(IRIVER_H100_SERIES)
37int pitch_screen(void); 37int pitch_screen(void);
38#endif
39#if CONFIG_KEYPAD == RECORDER_PAD
38extern bool quick_screen_f3(int button_enter); 40extern bool quick_screen_f3(int button_enter);
39#endif 41#endif
40extern bool quick_screen_quick(int button_enter); 42extern bool quick_screen_quick(int button_enter);