/**************************************************************************** DESCRIPTION This function connects a synchronous audio stream to the pcm subsystem */ void CsrSbcEncoderPluginConnect( Sink audio_sink , Task codec_task , uint16 volume , uint32 rate , bool stereo , AUDIO_MODE_T mode , const void * params ) { /* DSP Application loading and Transform starting is handled by a call to A2dpAudioCodecEnable in the application, so should not be done here. */ typedef struct { unsigned source_type:4; unsigned reserved:4; uint8 content_protection; uint32 voice_rate; unsigned bitpool:8; unsigned format:8; uint16 packet_size; Sink media_sink_b; } sbc_codec_data_type; sbc_codec_data_type *sbc_codecData = (sbc_codec_data_type *) params; if (!sbc_codecData) Panic(); SBC = (SBC_t*)PanicUnlessMalloc (sizeof (SBC_t) ) ; SBC->media_sink[0] = audio_sink ; SBC->codec_task = codec_task ; SBC->media_sink[1] = sbc_codecData->media_sink_b; SBC->packet_size = sbc_codecData->packet_size; StreamDisconnect(StreamKalimbaSource(2), 0); /* Initialise the RTP SBC encoder */ SBC->t[0] = TransformRtpSbcEncode(StreamKalimbaSource(2), audio_sink); /* Configure the RTP transform to generate the selected packet size */ TransformConfigure(SBC->t[0], VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, sbc_codecData->packet_size); /* Transform should not manage timings. */ TransformConfigure(SBC->t[0], VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE); /* Start the transform */ (void) TransformStart(SBC->t[0]); PRINT(("Audio Plugin: TransformStart sink:0x%x\n",(uint16)audio_sink)); if (SBC->media_sink[1]) { /* There is a 2nd audio stream so initialise this transform */ StreamDisconnect(StreamKalimbaSource(3), 0); /* Initialise the RTP SBC encoder */ SBC->t[1] = TransformRtpSbcEncode(StreamKalimbaSource(3), SBC->media_sink[1]); /* Configure the RTP transform to generate the selected packet size */ TransformConfigure(SBC->t[1], VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, sbc_codecData->packet_size); /* Transform should not manage timings. */ TransformConfigure(SBC->t[1], VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE); /* Start the transform */ (void) TransformStart(SBC->t[1]); PRINT(("Audio Plugin: TransformStart sink:0x%x\n",(uint16)SBC->media_sink[1])); } /* Configure SBC encoding format */ if (!KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_PARAMS, sbc_codecData->format, 0, 0, 0)) /* If message fails to get through, abort */ Panic(); /* Pass bit pool value to DSP */ if (!KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_BITPOOL, sbc_codecData->bitpool, 0, 0, 0)) /* If message fails to get through, abort */ Panic(); /* disard any data sent by the SNK */ StreamConnectDispose(StreamSourceFromSink(audio_sink)); if (SBC->media_sink[1]) { /* disard any data sent by the 2nd SNK */ StreamConnectDispose(StreamSourceFromSink(SBC->media_sink[1])); } /* select the source type */ if(sbc_codecData->source_type == SourceUsb) { PRINT(("Audio Plugin: SourceUsb\n")); /* Select the source type */ PanicFalse(KalimbaSendMessage(KALIMBA_ENCODER_SELECT, 0x0001, 0, 0, 0)); } else { PRINT(("Audio Plugin: SourceAnalog\n")); /* For analogue input source */ StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0)); StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1)); (void)PcmClearAllRouting(); if (CodecGetCodecType(codec_task) == codec_wm8731) { PRINT(("Audio Plugin: codec_wm8731\n")); /* configure slot 0 and 1 to be left and right channel and synchronise the offsets for stereo playback */ (void)PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) rate, (uint32) rate, VM_PCM_EXTERNAL_I2S); (void)PcmRateAndRoute(1, 0, (uint32) rate, (uint32) rate, VM_PCM_EXTERNAL_I2S); } else { PRINT(("Audio Plugin: codec_internal\n")); /* configure slot 0 and 1 to be left and right channel and synchronise the offsets for stereo playback */ (void)PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) rate, (uint32) rate, VM_PCM_INTERNAL_A); (void)PcmRateAndRoute(1, 0, (uint32) rate, (uint32) rate, VM_PCM_INTERNAL_B); } /* plug Left ADC into port 0 */ (void)StreamConnect(StreamPcmSource(0),StreamKalimbaSink(0)); /* plug Right ADC into port 1 */ (void)StreamConnect(StreamPcmSource(1),StreamKalimbaSink(1)); /* Select the source type */ PanicFalse(KalimbaSendMessage(KALIMBA_ENCODER_SELECT, 0x0002, 0, 0, 0)); if(!KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0)) { PRINT(("SBC: Message KALIMBA_MSG_GO failed!\n")); Panic(); } } /* Select the source type */ /*PanicFalse(KalimbaSendMessage(KALIMBA_SOURCE_SELECT, SOURCE_USB, 0, 0, 0)); */ /*CsrSbcEncoderUsbPluginSetVolume(volume) ;*/ /*(void) StreamConnect(PanicNull(StreamUsbEndPointSource(end_point_iso_in)), StreamKalimbaSink(0)); */ /* Start decode */ /* if(!KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0)) { PRINT(("SBC: Message KALIMBA_MSG_GO failed!\n")); Panic(); } */ }
void A2dpStartKalimbaStreaming(const A2DP *a2dp, uint16 media_sink) { FILE_INDEX index = FILE_NONE; #ifdef BUILD_FOR_23FW Transform t; #else Transform t, l_t, r_t; Source l_src = StreamAudioSource(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A); Source r_src = StreamAudioSource(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_1, AUDIO_CHANNEL_B); Sink l_snk = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A); Sink r_snk = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_1, AUDIO_CHANNEL_B); #endif /* load SBC codec */ index = FileFind(FILE_ROOT, sbc_encoder, sizeof(sbc_encoder)-1); if (!KalimbaLoad(index)) /* codec load failure, Panic as the test isn't going to work now */ Panic(); /* Init and configure RTP */ t = TransformRtpSbcEncode(StreamKalimbaSource(0), (Sink)media_sink); TransformConfigure(t, VM_TRANSFORM_RTP_SBC_ENCODE_PACKET_SIZE, 668); TransformConfigure(t, VM_TRANSFORM_RTP_SBC_ENCODE_MANAGE_TIMING, FALSE); (void)TransformStart(t); /* Configure SBC encoding format */ (void)PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_PARAMS, 0x00bd, 0, 0, 0)); (void)PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_BITPOOL, 0x0030, 0, 0, 0)); #ifdef BUILD_FOR_23FW StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0)); StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1)); /* set up ADCs */ (void)PcmClearAllRouting(); (void)PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, 44100, 44100, VM_PCM_INTERNAL_A)); (void)PanicFalse(PcmRateAndRoute(1, 0, 44100, 44100, VM_PCM_INTERNAL_B)); (void)PanicFalse(StreamConnect(StreamPcmSource(0),StreamKalimbaSink(0))); (void)PanicFalse(StreamConnect(StreamPcmSource(1),StreamKalimbaSink(1))); #else SourceClose(l_src); SourceClose(r_src); SinkClose(l_snk); SinkClose(r_snk); (void) SourceConfigure(l_src, STREAM_CODEC_INPUT_RATE, 44100); (void) SourceConfigure(r_src, STREAM_CODEC_INPUT_RATE, 44100); (void) SourceSynchronise(l_src, r_src); /* set up ADCs */ l_t = StreamConnect(l_src, StreamKalimbaSink(0)); r_t = StreamConnect(r_src, StreamKalimbaSink(1)); (void)TransformStart(l_t); (void)TransformStart(r_t); #endif /* Start decode */ (void) PanicFalse(KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0)); }
/**************************************************************************** DESCRIPTION Connect the encoded audio input and pcm audio output streams */ static void MusicConnectAudio (A2dpPluginTaskdata *task, bool stereo ) { plugin_codec_data_type *codecData = (plugin_codec_data_type *) DECODER->params; uint32 voice_rate = 0; val_clock_mismatch = codecData->clock_mismatch; if ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant == FASTSTREAM_SINK) { /* FastStream does not use RTP. L2CAP frames enter/leave via port 2 */ /* Initialise PCM. Output stereo at 44k1Hz or 48kHz, input from left ADC at 16kHz. */ /* If no voice rate is set just make the ADC rate equal to 16kHz */ if (!codecData->voice_rate) voice_rate = 16000; else voice_rate = codecData->voice_rate; PRINT(("FASTSTREAM: rate=0x%lx voice_rate=0x%lx\n format=0x%x bitpool=0x%x",DECODER->rate,codecData->voice_rate,codecData->format,codecData->bitpool)); PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, (uint32)DECODER->rate, (uint32) voice_rate, VM_PCM_INTERNAL_A)); /* is it mono playback? */ if ( !stereo ) { PRINT(("DECODER: Mono\n")); /* Connect Kalimba to PCM */ if (DECODER->rate) { StreamDisconnect(StreamSourceFromSink(DECODER->media_sink), 0); PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0))); PanicFalse(StreamConnect(StreamSourceFromSink(DECODER->media_sink),StreamKalimbaSink(2))); } } else { PRINT(("DECODER: Stereo\n")); PanicFalse(PcmRateAndRoute(1, 0, (uint32)DECODER->rate, (uint32) voice_rate, VM_PCM_INTERNAL_B)); /* Connect Kalimba to PCM */ if (DECODER->rate) { StreamDisconnect(StreamSourceFromSink(DECODER->media_sink), 0); PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0))); PanicFalse(StreamConnect(StreamKalimbaSource(1),StreamPcmSink(1))); PanicFalse(StreamConnect(StreamSourceFromSink(DECODER->media_sink),StreamKalimbaSink(2))); } } if (codecData->voice_rate) { StreamDisconnect(0, DECODER->media_sink); /* configure parameters */ PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_PARAMS, codecData->format, 0, 0, 0)); PanicFalse(KalimbaSendMessage(KALIMBA_MSG_SBCENC_SET_BITPOOL, codecData->bitpool, 0, 0, 0)); PanicFalse(StreamConnect(StreamPcmSource(0), StreamKalimbaSink(0))); PanicFalse(StreamConnect(StreamKalimbaSource(2),DECODER->media_sink)); } } else /* Not FastStream CODEC */ { uint8 content_protection = codecData->content_protection; uint16 scms_enabled = 0; Transform rtp_transform = 0; switch ((A2DP_DECODER_PLUGIN_TYPE_T)task->a2dp_plugin_variant) { case SBC_DECODER: rtp_transform = TransformRtpSbcDecode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(0)); break; case MP3_DECODER: rtp_transform = TransformRtpMp3Decode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(0)); break; case AAC_DECODER: rtp_transform = TransformRtpAacDecode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(0)); break; default: break; } /* Configure the content protection */ if (content_protection) scms_enabled = 1; TransformConfigure(rtp_transform, VM_TRANSFORM_RTP_SCMS_ENABLE, scms_enabled); /*start the transform decode*/ (void)TransformStart( rtp_transform ) ; /* is it mono playback? */ if ( !stereo ) { PcmRateAndRoute(0, PCM_NO_SYNC, DECODER->rate, (uint32) 8000, VM_PCM_INTERNAL_A) ; PRINT(("DECODER: Mono\n")); /* plug port 0 into both DACs */ (void) PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0))); } else { PRINT(("DECODER: Stereo\n")); PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, DECODER->rate, (uint32) 8000, VM_PCM_INTERNAL_A)); PanicFalse(PcmRateAndRoute(1, 0, DECODER->rate, (uint32) 8000, VM_PCM_INTERNAL_B)); /* plug port 0 into Left DAC */ PanicFalse(StreamConnect(StreamKalimbaSource(0),StreamPcmSink(0))); /* plug port 1 into Right DAC */ PanicFalse(StreamConnect(StreamKalimbaSource(1),StreamPcmSink(1))); } } CsrA2dpDecoderPluginSetVolume(task,DECODER->volume) ; /* The DSP must know the sample rate for tone mixing */ KalimbaSendMessage(MESSAGE_SET_SAMPLE_RATE, DECODER->rate, val_pskey_max_mismatch, val_clock_mismatch, 0); PRINT(("DECODER: Send Go message to DSP now\n")); if(!KalimbaSendMessage(KALIMBA_MSG_GO,0,0,0,0)) { PRINT(("DECODER: Message KALIMBA_MSG_GO failed!\n")); Panic(); } }