summaryrefslogtreecommitdiff
path: root/apps/plugins/mpegplayer/audio_thread.c
diff options
context:
space:
mode:
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;