summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/audio_thread.c
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-02-01 02:25:15 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-02-01 02:25:15 +0000
commitf90cbcb652af3bf794ec61d7f7ec3de00c8b7cb2 (patch)
tree62c13ffdeb5112181897103a6a015cfc1fab98ae /apps/plugins/mpegplayer/audio_thread.c
parent7e402d8202af409a0ea8f3f2676a2e6f501af05b (diff)
downloadrockbox-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.c93
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 @@
27struct pts_queue_slot; 27struct pts_queue_slot;
28struct audio_thread_data 28struct 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;