diff options
author | Michael Sevakis <jethead71@rockbox.org> | 2008-02-01 02:25:15 +0000 |
---|---|---|
committer | Michael Sevakis <jethead71@rockbox.org> | 2008-02-01 02:25:15 +0000 |
commit | f90cbcb652af3bf794ec61d7f7ec3de00c8b7cb2 (patch) | |
tree | 62c13ffdeb5112181897103a6a015cfc1fab98ae /apps/plugins/mpegplayer/audio_thread.c | |
parent | 7e402d8202af409a0ea8f3f2676a2e6f501af05b (diff) | |
download | rockbox-f90cbcb652af3bf794ec61d7f7ec3de00c8b7cb2.tar.gz rockbox-f90cbcb652af3bf794ec61d7f7ec3de00c8b7cb2.zip |
mpegplayer: Use the core DSP to process audio. Removes the sample rate restriction on audio and any mpeg audio samplerate may be used. Use the global sound settings for audio output with the option to force any one of the processing stages off. All are forced off by default. I didn't personally care to fully duplicate the Sound Settings menu which would have been needed since using the core one would affect settings globally and exactly the same configuration probably isn't desired since the CPU load for video playback is much greater. Rebalance the threading to compensate with some expense to buffering speed.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16194 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/plugins/mpegplayer/audio_thread.c')
-rw-r--r-- | apps/plugins/mpegplayer/audio_thread.c | 93 |
1 files changed, 49 insertions, 44 deletions
diff --git a/apps/plugins/mpegplayer/audio_thread.c b/apps/plugins/mpegplayer/audio_thread.c index 78d28e40c5..2bb766ad88 100644 --- a/apps/plugins/mpegplayer/audio_thread.c +++ b/apps/plugins/mpegplayer/audio_thread.c | |||
@@ -27,10 +27,13 @@ | |||
27 | struct pts_queue_slot; | 27 | struct pts_queue_slot; |
28 | struct audio_thread_data | 28 | struct audio_thread_data |
29 | { | 29 | { |
30 | struct queue_event ev; /* Our event queue to receive commands */ | 30 | struct queue_event ev; /* Our event queue to receive commands */ |
31 | int state; /* Thread state */ | 31 | int state; /* Thread state */ |
32 | int status; /* Media status (STREAM_PLAYING, etc.) */ | 32 | int status; /* Media status (STREAM_PLAYING, etc.) */ |
33 | int mad_errors; /* A count of the errors in each frame */ | 33 | int mad_errors; /* A count of the errors in each frame */ |
34 | unsigned samplerate; /* Current stream sample rate */ | ||
35 | int nchannels; /* Number of audio channels */ | ||
36 | struct dsp_config *dsp; /* The DSP we're using */ | ||
34 | }; | 37 | }; |
35 | 38 | ||
36 | /* The audio stack is stolen from the core codec thread (but not in uisim) */ | 39 | /* The audio stack is stolen from the core codec thread (but not in uisim) */ |
@@ -402,6 +405,8 @@ static void audio_thread_msg(struct audio_thread_data *td) | |||
402 | 405 | ||
403 | td->status = STREAM_STOPPED; | 406 | td->status = STREAM_STOPPED; |
404 | td->state = TSTATE_INIT; | 407 | td->state = TSTATE_INIT; |
408 | td->samplerate = 0; | ||
409 | td->nchannels = 0; | ||
405 | 410 | ||
406 | init_mad(); | 411 | init_mad(); |
407 | td->mad_errors = 0; | 412 | td->mad_errors = 0; |
@@ -460,12 +465,19 @@ static void audio_thread(void) | |||
460 | { | 465 | { |
461 | struct audio_thread_data td; | 466 | struct audio_thread_data td; |
462 | 467 | ||
468 | rb->memset(&td, 0, sizeof (td)); | ||
463 | td.status = STREAM_STOPPED; | 469 | td.status = STREAM_STOPPED; |
464 | td.state = TSTATE_EOS; | 470 | td.state = TSTATE_EOS; |
465 | 471 | ||
466 | /* We need this here to init the EMAC for Coldfire targets */ | 472 | /* We need this here to init the EMAC for Coldfire targets */ |
467 | init_mad(); | 473 | init_mad(); |
468 | 474 | ||
475 | td.dsp = (struct dsp_config *)rb->dsp_configure(NULL, DSP_MYDSP, | ||
476 | CODEC_IDX_AUDIO); | ||
477 | rb->sound_set_pitch(1000); | ||
478 | rb->dsp_configure(td.dsp, DSP_RESET, 0); | ||
479 | rb->dsp_configure(td.dsp, DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); | ||
480 | |||
469 | goto message_wait; | 481 | goto message_wait; |
470 | 482 | ||
471 | /* This is the decoding loop. */ | 483 | /* This is the decoding loop. */ |
@@ -594,64 +606,56 @@ static void audio_thread(void) | |||
594 | mad_synth_frame(&synth, &frame); | 606 | mad_synth_frame(&synth, &frame); |
595 | 607 | ||
596 | /** Output **/ | 608 | /** Output **/ |
609 | if (frame.header.samplerate != td.samplerate) | ||
610 | { | ||
611 | td.samplerate = frame.header.samplerate; | ||
612 | rb->dsp_configure(td.dsp, DSP_SWITCH_FREQUENCY, | ||
613 | td.samplerate); | ||
614 | } | ||
597 | 615 | ||
598 | /* TODO: Output through core dsp. We'll still use our own PCM buffer | 616 | if (MAD_NCHANNELS(&frame.header) != td.nchannels) |
599 | since the core pcm buffer has no timestamping or clock facilities */ | 617 | { |
618 | td.nchannels = MAD_NCHANNELS(&frame.header); | ||
619 | rb->dsp_configure(td.dsp, DSP_SET_STEREO_MODE, | ||
620 | td.nchannels == 1 ? | ||
621 | STEREO_MONO : STEREO_NONINTERLEAVED); | ||
622 | } | ||
623 | |||
624 | td.state = TSTATE_RENDER_WAIT; | ||
600 | 625 | ||
601 | /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */ | 626 | /* Add a frame of audio to the pcm buffer. Maximum is 1152 samples. */ |
602 | render_wait: | 627 | render_wait: |
603 | if (synth.pcm.length > 0) | 628 | if (synth.pcm.length > 0) |
604 | { | 629 | { |
605 | struct pcm_frame_header *pcm_insert = pcm_output_get_buffer(); | 630 | struct pcm_frame_header *dst_hdr = pcm_output_get_buffer(); |
606 | int16_t *audio_data = (int16_t *)pcm_insert->data; | 631 | const char *src[2] = |
607 | unsigned length = synth.pcm.length; | 632 | { (char *)synth.pcm.samples[0], (char *)synth.pcm.samples[1] }; |
608 | ssize_t size = sizeof(*pcm_insert) + length*4; | 633 | int out_count = (synth.pcm.length * CLOCK_RATE |
609 | 634 | + (td.samplerate - 1)) / td.samplerate; | |
610 | td.state = TSTATE_RENDER_WAIT; | 635 | ssize_t size = sizeof(*dst_hdr) + out_count*4; |
611 | 636 | ||
612 | /* Wait for required amount of free buffer space */ | 637 | /* Wait for required amount of free buffer space */ |
613 | while (pcm_output_free() < size) | 638 | while (pcm_output_free() < size) |
614 | { | 639 | { |
615 | /* Wait one frame */ | 640 | /* Wait one frame */ |
616 | int timeout = synth.pcm.length*HZ / synth.pcm.samplerate; | 641 | int timeout = out_count*HZ / td.samplerate; |
617 | str_get_msg_w_tmo(&audio_str, &td.ev, MAX(timeout, 1)); | 642 | str_get_msg_w_tmo(&audio_str, &td.ev, MAX(timeout, 1)); |
618 | if (td.ev.id != SYS_TIMEOUT) | 643 | if (td.ev.id != SYS_TIMEOUT) |
619 | goto message_process; | 644 | goto message_process; |
620 | } | 645 | } |
621 | 646 | ||
622 | pcm_insert->time = audio_queue.curr->time; | 647 | out_count = rb->dsp_process(td.dsp, dst_hdr->data, src, |
623 | pcm_insert->size = size; | 648 | synth.pcm.length); |
624 | 649 | ||
625 | /* As long as we're on this timestamp, the time is just incremented | 650 | if (out_count <= 0) |
626 | by the number of samples */ | 651 | break; |
627 | audio_queue.curr->time += length; | ||
628 | |||
629 | if (MAD_NCHANNELS(&frame.header) == 2) | ||
630 | { | ||
631 | int32_t *left = &synth.pcm.samples[0][0]; | ||
632 | int32_t *right = &synth.pcm.samples[1][0]; | ||
633 | 652 | ||
634 | do | 653 | dst_hdr->size = sizeof(*dst_hdr) + out_count*4; |
635 | { | 654 | dst_hdr->time = audio_queue.curr->time; |
636 | /* libmad outputs s3.28 */ | ||
637 | *audio_data++ = clip_sample(*left++ >> 13); | ||
638 | *audio_data++ = clip_sample(*right++ >> 13); | ||
639 | } | ||
640 | while (--length > 0); | ||
641 | } | ||
642 | else /* mono */ | ||
643 | { | ||
644 | int32_t *mono = &synth.pcm.samples[0][0]; | ||
645 | 655 | ||
646 | do | 656 | /* As long as we're on this timestamp, the time is just |
647 | { | 657 | incremented by the number of samples */ |
648 | int32_t s = clip_sample(*mono++ >> 13); | 658 | audio_queue.curr->time += out_count; |
649 | *audio_data++ = s; | ||
650 | *audio_data++ = s; | ||
651 | } | ||
652 | while (--length > 0); | ||
653 | } | ||
654 | /**/ | ||
655 | 659 | ||
656 | /* Make this data available to DMA */ | 660 | /* Make this data available to DMA */ |
657 | pcm_output_add_data(); | 661 | pcm_output_add_data(); |
@@ -712,9 +716,10 @@ bool audio_thread_init(void) | |||
712 | rb->queue_init(audio_str.hdr.q, false); | 716 | rb->queue_init(audio_str.hdr.q, false); |
713 | rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send); | 717 | rb->queue_enable_queue_send(audio_str.hdr.q, &audio_str_queue_send); |
714 | 718 | ||
719 | /* One-up on the priority since the core DSP over-yields internally */ | ||
715 | audio_str.thread = rb->create_thread( | 720 | audio_str.thread = rb->create_thread( |
716 | audio_thread, audio_stack, audio_stack_size, 0, | 721 | audio_thread, audio_stack, audio_stack_size, 0, |
717 | "mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK) IF_COP(, CPU)); | 722 | "mpgaudio" IF_PRIO(,PRIORITY_PLAYBACK-1) IF_COP(, CPU)); |
718 | 723 | ||
719 | if (audio_str.thread == NULL) | 724 | if (audio_str.thread == NULL) |
720 | return false; | 725 | return false; |