diff options
author | Miika Pekkarinen <miipekk@ihme.org> | 2005-06-26 19:41:29 +0000 |
---|---|---|
committer | Miika Pekkarinen <miipekk@ihme.org> | 2005-06-26 19:41:29 +0000 |
commit | d8cb703b1e86c9f910211a976d8bed0c7a99379a (patch) | |
tree | 6db3b698d83e639974bd6603225ff11891652113 /apps/playback.c | |
parent | 316eb6538e2fc88efa93248deb761679071409f1 (diff) | |
download | rockbox-d8cb703b1e86c9f910211a976d8bed0c7a99379a.tar.gz rockbox-d8cb703b1e86c9f910211a976d8bed0c7a99379a.zip |
Initial DSP implementation. DSP supports resampling audio stream from
codecs (currently works corrently only with mp3's, somebody should fix
that).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@6877 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/playback.c')
-rw-r--r-- | apps/playback.c | 131 |
1 files changed, 123 insertions, 8 deletions
diff --git a/apps/playback.c b/apps/playback.c index 500f44e45b..996e825e13 100644 --- a/apps/playback.c +++ b/apps/playback.c | |||
@@ -49,6 +49,7 @@ | |||
49 | #include "playback.h" | 49 | #include "playback.h" |
50 | #include "pcm_playback.h" | 50 | #include "pcm_playback.h" |
51 | #include "buffer.h" | 51 | #include "buffer.h" |
52 | #include "dsp.h" | ||
52 | #ifdef HAVE_LCD_BITMAP | 53 | #ifdef HAVE_LCD_BITMAP |
53 | #include "icons.h" | 54 | #include "icons.h" |
54 | #include "peakmeter.h" | 55 | #include "peakmeter.h" |
@@ -171,7 +172,7 @@ int mp3_get_file_pos(void); | |||
171 | 172 | ||
172 | /* Simulator stubs. */ | 173 | /* Simulator stubs. */ |
173 | #ifdef SIMULATOR | 174 | #ifdef SIMULATOR |
174 | bool audiobuffer_insert(char *buf, size_t length) | 175 | bool pcm_insert_buffer(char *buf, size_t length) |
175 | { | 176 | { |
176 | (void)buf; | 177 | (void)buf; |
177 | (void)length; | 178 | (void)length; |
@@ -179,6 +180,20 @@ bool audiobuffer_insert(char *buf, size_t length) | |||
179 | return true; | 180 | return true; |
180 | } | 181 | } |
181 | 182 | ||
183 | void pcm_flush_buffer(size_t length) | ||
184 | { | ||
185 | (void)length; | ||
186 | } | ||
187 | |||
188 | |||
189 | void* pcm_request_buffer(size_t length, size_t *realsize) | ||
190 | { | ||
191 | (void)length; | ||
192 | (void)realsize; | ||
193 | |||
194 | return NULL; | ||
195 | } | ||
196 | |||
182 | void audiobuffer_add_event(void (*event_handler)(void)) | 197 | void audiobuffer_add_event(void (*event_handler)(void)) |
183 | { | 198 | { |
184 | (void)event_handler; | 199 | (void)event_handler; |
@@ -229,6 +244,92 @@ int ata_sleep(void) | |||
229 | } | 244 | } |
230 | #endif | 245 | #endif |
231 | 246 | ||
247 | bool codec_audiobuffer_insert_callback(char *buf, size_t length) | ||
248 | { | ||
249 | char *dest; | ||
250 | size_t realsize; | ||
251 | int factor; | ||
252 | int next_channel = 0; | ||
253 | int processed_length; | ||
254 | |||
255 | /* If non-interleaved stereo mode. */ | ||
256 | if (dsp_config.stereo_mode == STEREO_NONINTERLEAVED) { | ||
257 | next_channel = length / 2; | ||
258 | } | ||
259 | |||
260 | if (dsp_config.sample_depth > 16) { | ||
261 | length /= 2; | ||
262 | factor = 1; | ||
263 | } else { | ||
264 | factor = 0; | ||
265 | } | ||
266 | |||
267 | while (length > 0) { | ||
268 | /* Request a few extra bytes for resampling. */ | ||
269 | /* FIXME: Required extra bytes SHOULD be calculated. */ | ||
270 | while ((dest = pcm_request_buffer(length+16384, &realsize)) == NULL) | ||
271 | yield(); | ||
272 | |||
273 | if (realsize < 16384) { | ||
274 | pcm_flush_buffer(0); | ||
275 | continue ; | ||
276 | } | ||
277 | |||
278 | realsize -= 16384; | ||
279 | |||
280 | if (next_channel) { | ||
281 | processed_length = dsp_process(dest, buf, realsize / 4) * 2; | ||
282 | dsp_process(dest, buf + next_channel, realsize / 4); | ||
283 | } else { | ||
284 | processed_length = dsp_process(dest, buf, realsize / 2); | ||
285 | } | ||
286 | pcm_flush_buffer(processed_length); | ||
287 | length -= realsize; | ||
288 | buf += realsize << factor; | ||
289 | } | ||
290 | |||
291 | return true; | ||
292 | } | ||
293 | |||
294 | bool codec_audiobuffer_insert_split_callback(void *ch1, void *ch2, | ||
295 | size_t length) | ||
296 | { | ||
297 | char *dest; | ||
298 | size_t realsize; | ||
299 | int factor; | ||
300 | int processed_length; | ||
301 | |||
302 | /* non-interleaved stereo mode. */ | ||
303 | if (dsp_config.sample_depth > 16) { | ||
304 | factor = 0; | ||
305 | } else { | ||
306 | length /= 2; | ||
307 | factor = 1; | ||
308 | } | ||
309 | |||
310 | while (length > 0) { | ||
311 | /* Request a few extra bytes for resampling. */ | ||
312 | while ((dest = pcm_request_buffer(length+4096, &realsize)) == NULL) | ||
313 | yield(); | ||
314 | |||
315 | if (realsize < 4096) { | ||
316 | pcm_flush_buffer(0); | ||
317 | continue ; | ||
318 | } | ||
319 | |||
320 | realsize -= 4096; | ||
321 | |||
322 | processed_length = dsp_process(dest, ch1, realsize / 4) * 2; | ||
323 | dsp_process(dest, ch2, realsize / 4); | ||
324 | pcm_flush_buffer(processed_length); | ||
325 | length -= realsize; | ||
326 | ch1 += realsize >> factor; | ||
327 | ch2 += realsize >> factor; | ||
328 | } | ||
329 | |||
330 | return true; | ||
331 | } | ||
332 | |||
232 | void* get_codec_memory_callback(size_t *size) | 333 | void* get_codec_memory_callback(size_t *size) |
233 | { | 334 | { |
234 | *size = MALLOC_BUFSIZE; | 335 | *size = MALLOC_BUFSIZE; |
@@ -260,7 +361,7 @@ size_t codec_filebuf_callback(void *ptr, size_t size) | |||
260 | 361 | ||
261 | if (ci.stop_codec || !playing) | 362 | if (ci.stop_codec || !playing) |
262 | return 0; | 363 | return 0; |
263 | 364 | ||
264 | copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem); | 365 | copy_n = MIN((off_t)size, (off_t)cur_ti->available + cur_ti->filerem); |
265 | 366 | ||
266 | while (copy_n > cur_ti->available) { | 367 | while (copy_n > cur_ti->available) { |
@@ -283,7 +384,7 @@ size_t codec_filebuf_callback(void *ptr, size_t size) | |||
283 | buf_ridx -= codecbuflen; | 384 | buf_ridx -= codecbuflen; |
284 | ci.curpos += copy_n; | 385 | ci.curpos += copy_n; |
285 | cur_ti->available -= copy_n; | 386 | cur_ti->available -= copy_n; |
286 | codecbufused -= copy_n; | 387 | codecbufused -= copy_n; |
287 | 388 | ||
288 | return copy_n; | 389 | return copy_n; |
289 | } | 390 | } |
@@ -427,8 +528,18 @@ void codec_configure_callback(int setting, void *value) | |||
427 | conf_bufferlimit = (unsigned int)value; | 528 | conf_bufferlimit = (unsigned int)value; |
428 | break; | 529 | break; |
429 | 530 | ||
531 | case CODEC_DSP_ENABLE: | ||
532 | if ((bool)value) | ||
533 | ci.audiobuffer_insert = codec_audiobuffer_insert_callback; | ||
534 | else | ||
535 | ci.audiobuffer_insert = pcm_insert_buffer; | ||
536 | break ; | ||
537 | |||
538 | #ifndef SIMULATOR | ||
430 | default: | 539 | default: |
431 | logf("Illegal key: %d", setting); | 540 | if (!dsp_configure(setting, value)) |
541 | logf("Illegal key: %d", setting); | ||
542 | #endif | ||
432 | } | 543 | } |
433 | } | 544 | } |
434 | 545 | ||
@@ -647,6 +758,8 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
647 | conf_bufferlimit = 0; | 758 | conf_bufferlimit = 0; |
648 | conf_watermark = AUDIO_DEFAULT_WATERMARK; | 759 | conf_watermark = AUDIO_DEFAULT_WATERMARK; |
649 | conf_filechunk = AUDIO_DEFAULT_FILECHUNK; | 760 | conf_filechunk = AUDIO_DEFAULT_FILECHUNK; |
761 | dsp_configure(DSP_RESET, 0); | ||
762 | ci.configure(CODEC_DSP_ENABLE, false); | ||
650 | } | 763 | } |
651 | 764 | ||
652 | tracks[track_widx].codecbuf = &codecbuf[buf_widx]; | 765 | tracks[track_widx].codecbuf = &codecbuf[buf_widx]; |
@@ -697,7 +810,7 @@ bool audio_load_track(int offset, bool start_play, int peek_offset) | |||
697 | copy_n = MIN(size - i, copy_n); | 810 | copy_n = MIN(size - i, copy_n); |
698 | copy_n = MIN((int)fill_bytesleft, copy_n); | 811 | copy_n = MIN((int)fill_bytesleft, copy_n); |
699 | rc = read(fd, &codecbuf[buf_widx], copy_n); | 812 | rc = read(fd, &codecbuf[buf_widx], copy_n); |
700 | if (rc < 0) { | 813 | if (rc <= 0) { |
701 | logf("File error!"); | 814 | logf("File error!"); |
702 | close(fd); | 815 | close(fd); |
703 | return false; | 816 | return false; |
@@ -1152,7 +1265,7 @@ struct mp3entry* audio_next_track(void) | |||
1152 | 1265 | ||
1153 | bool audio_has_changed_track(void) | 1266 | bool audio_has_changed_track(void) |
1154 | { | 1267 | { |
1155 | if (track_changed && track_count > 0) { | 1268 | if (track_changed && track_count > 0 && playing) { |
1156 | if (!cur_ti->taginfo_ready) | 1269 | if (!cur_ti->taginfo_ready) |
1157 | return false; | 1270 | return false; |
1158 | track_changed = false; | 1271 | track_changed = false; |
@@ -1384,6 +1497,7 @@ int mp3_get_file_pos(void) | |||
1384 | void audio_set_buffer_margin(int seconds) | 1497 | void audio_set_buffer_margin(int seconds) |
1385 | { | 1498 | { |
1386 | (void)seconds; | 1499 | (void)seconds; |
1500 | logf("bufmargin: %d", seconds); | ||
1387 | } | 1501 | } |
1388 | #endif | 1502 | #endif |
1389 | 1503 | ||
@@ -1395,7 +1509,7 @@ void mpeg_id3_options(bool _v1first) | |||
1395 | void audio_init(void) | 1509 | void audio_init(void) |
1396 | { | 1510 | { |
1397 | logf("audio api init"); | 1511 | logf("audio api init"); |
1398 | codecbuflen = audiobufend - audiobuf - PCMBUF_SIZE | 1512 | codecbuflen = audiobufend - audiobuf - PCMBUF_SIZE - PCMBUF_GUARD |
1399 | - MALLOC_BUFSIZE - GUARD_BUFSIZE; | 1513 | - MALLOC_BUFSIZE - GUARD_BUFSIZE; |
1400 | //codecbuflen = 2*512*1024; | 1514 | //codecbuflen = 2*512*1024; |
1401 | codecbufused = 0; | 1515 | codecbufused = 0; |
@@ -1412,7 +1526,8 @@ void audio_init(void) | |||
1412 | 1526 | ||
1413 | /* Initialize codec api. */ | 1527 | /* Initialize codec api. */ |
1414 | ci.read_filebuf = codec_filebuf_callback; | 1528 | ci.read_filebuf = codec_filebuf_callback; |
1415 | ci.audiobuffer_insert = audiobuffer_insert; | 1529 | ci.audiobuffer_insert = pcm_insert_buffer; |
1530 | ci.audiobuffer_insert_split = codec_audiobuffer_insert_split_callback; | ||
1416 | ci.get_codec_memory = get_codec_memory_callback; | 1531 | ci.get_codec_memory = get_codec_memory_callback; |
1417 | ci.request_buffer = codec_request_buffer_callback; | 1532 | ci.request_buffer = codec_request_buffer_callback; |
1418 | ci.advance_buffer = codec_advance_buffer_callback; | 1533 | ci.advance_buffer = codec_advance_buffer_callback; |