/****************************************************************************
DESCRIPTION
    connect the subwoofer if a subwoofer link has been established
*/
void CsrA2dpDecoderPluginConnectSubwoofer(A2dpPluginConnectParams *codecData)
{     
    DECODER_t * DECODER = CsrA2dpDecoderGetDecoderData();
    
    PRINT(("DECODER:Try to connect sub\n"));
 
    /* ensure the decoder is loaded */
    if(codecData)
    {
        /* if the sub woofer is available at connection time? */
        if(codecData->sub_woofer_type != AUDIO_SUB_WOOFER_NONE)
        {
            /* determine the sub link type */
            switch(codecData->sub_woofer_type)
            {
                /* SUB using esco as its bt link, connect to dsp port 2 */
                case AUDIO_SUB_WOOFER_ESCO:
                    /* ensure the correct ype of link is requested */
                    if(DECODER->sink_type != AUDIO_SINK_AV)
                    {
                        PRINT(("DECODER: connect esco sub\n"));
                        /* connect SUB output from dsp, source port 2, to esco sink  */
                        StreamConnect(StreamKalimbaSource(DSP_ESCO_SUB_PORT),codecData->sub_sink);
                        /* update port connection status */                    
                        codecData->sub_connection_port = DSP_ESCO_SUB_PORT;
                        /* set volume levels to desired level */
                        SubConnectedNowUnmuteVolume(DECODER);
                    }
                    else
                        PRINT(("DECODER: connect esco sub - ***wrong type***\n"));                        
                break;
    
                /* SUB using l2cap as its bt link, connect to dsp port 3 */
                case AUDIO_SUB_WOOFER_L2CAP:
                    /* ensure the correct ype of link is requested */
                    if(DECODER->sink_type == AUDIO_SINK_AV)
                    {
                        PRINT(("DECODER: connect l2cap sub\n"));
                        /* connect SUB output from dsp, source port 3, to l2cap sink  */
                        StreamConnect(StreamKalimbaSource(DSP_L2CAP_SUB_PORT),codecData->sub_sink);
                        /* update port connection status */                                        
                        codecData->sub_connection_port = DSP_L2CAP_SUB_PORT;
                        /* set volume levels to desired level */
                        SubConnectedNowUnmuteVolume(DECODER);
                    }
                    else
                        PRINT(("DECODER: connect l2cap sub - ***wrong type***\n"));                        
                break;              
    
                default:
                break;
            }
        }
    }
}
Ejemplo n.º 2
0
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
    configure the sub woofer and connect its audio if present
*/
void CsrA2dpDecoderPluginSetSubWoofer(AUDIO_SUB_TYPE_T sub_type, Sink sub_sink)
{
    DECODER_t * DECODER = CsrA2dpDecoderGetDecoderData();
    
    /* ensure the decoder is loaded */
    if(DECODER)
    {
        A2dpPluginConnectParams *codecData = (A2dpPluginConnectParams *) DECODER->params;

        /* update the decoder params with the new sub woofer status */
        codecData->sub_woofer_type = sub_type;
        codecData->sub_sink = sub_sink;

        /* determine sub woofer type and connect (or disconnect if gone away) the sink
           to the appropriate dsp port */
        switch(sub_type)
        {
            /* SUB no longer available, disconnect port if still connected */
            case AUDIO_SUB_WOOFER_NONE:
                PRINT(("DECODER: Disconnect woofer\n" ));
                /* if source is still connected then disconnect it */
                if(codecData->sub_connection_port != DSP_SUB_PORT_NOT_CONNECTED)
                {
                    /* determine if the subwoofer has connected after the decoder was loaded,
                       configured and unmuted */
                    if(codecData->sub_is_available == FALSE)
                    {
                        /* mute the outputs whilst the subwoofer port is connected and
                           decoder restarted */
                        csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_ENABLE);
                    }

                    PRINT(("DECODER: Disconnect kalimba port %x\n", codecData->sub_connection_port));
                    StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), 0);                 
                    /* update connected ports state */
                    codecData->sub_connection_port = DSP_SUB_PORT_NOT_CONNECTED;
                    /* set volume levels to desired level */
                    SubConnectedNowUnmuteVolume(DECODER);
                    
                    /* determine if the subwoofer has connected after the decoder was loaded,
                       configured and unmuted */
                    if(codecData->sub_is_available == FALSE)
                    {
                        /* unmute the outputs again */
                        csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_DISABLE);
                    }
                }
            break;

            /* SUB using esco as its bt link, connect to dsp port 2 */
            case AUDIO_SUB_WOOFER_ESCO:
                PRINT(("DECODER: connect esco dsp port 2, sub_sink = %x\n", (uint16)sub_sink ));
                /* ensure the correct ype of link is requested */
                if(DECODER->sink_type != AUDIO_SINK_AV)
                {               
                    /* connect SUB output from dsp, source port 2, to esco sink  */
                    if(codecData->sub_connection_port != DSP_ESCO_SUB_PORT)
                    {
                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* mute the outputs whilst the subwoofer port is connected and
                               decoder restarted */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_ENABLE);
                        }
                        
                        /* if not already connected */
                        if(codecData->sub_connection_port == DSP_L2CAP_SUB_PORT)
                        {
                            /* wrong port connected, disconnect it first */
                            StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), 0);
                            PRINT(("DECODER: Disconnect kalimba port %x\n", codecData->sub_connection_port));
                        }
                        /* ensure sink is valid */
                        if(SinkIsValid(sub_sink))
                        {
                            /* connect esco (2) port */
                            if(StreamConnect(StreamKalimbaSource(DSP_ESCO_SUB_PORT),sub_sink))
                            {
                                /* update connected ports state */
                                codecData->sub_connection_port = DSP_ESCO_SUB_PORT;
                                PRINT(("DECODER: Connect kalimba port %x\n", codecData->sub_connection_port));
                                /* set volume levels to desired level */
                                SubConnectedNowUnmuteVolume(DECODER);
                            }
                            else
                                PRINT(("DECODER: connect esco dsp port 2 FAILED\n" ));
                        }
                        else
                        {
                            PRINT(("DECODER: connect esco dsp port 2, sub_sink = %x NOT VALID\n", (uint16)sub_sink ));
                        }

                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* unmute the outputs again */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_DISABLE);
                        }

                    }
                }
                else
                    PRINT(("DECODER: ESCO - ****wrong link type****\n"));                    
            break;

            /* SUB using l2cap as its bt link, connect to dsp port 3 */
            case AUDIO_SUB_WOOFER_L2CAP:
                PRINT(("DECODER: connect l2cap dsp port 3, sub_sink = %x\n", (uint16)sub_sink ));
                /* ensure the correct ype of link is requested */
                if(DECODER->sink_type == AUDIO_SINK_AV)
                {
                    /* connect SUB output from dsp, source port 2, to esco sink  */
                    if(codecData->sub_connection_port != DSP_L2CAP_SUB_PORT)
                    {
                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* mute the outputs whilst the subwoofer port is connected and
                               decoder restarted */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_ENABLE);
                        }

                        /* if not already connected */
                        if(codecData->sub_connection_port == DSP_ESCO_SUB_PORT)
                        {
                            /* wrong port connected, disconnect it first */
                            StreamDisconnect(StreamKalimbaSource(codecData->sub_connection_port), 0);
                            PRINT(("DECODER: Disconnect kalimba port %x\n", codecData->sub_connection_port));
                        }
    
                        /* ensure sink is valid */
                        if(SinkIsValid(sub_sink))
                        {
                            /* connect l2cap (3) port */
                            if(StreamConnect(StreamKalimbaSource(DSP_L2CAP_SUB_PORT),sub_sink))
                            {
                                /* update connected ports state */
                                codecData->sub_connection_port = DSP_L2CAP_SUB_PORT;
                                PRINT(("DECODER: Connect kalimba port %x\n", codecData->sub_connection_port));
                                /* set volume levels to desired level */
                                SubConnectedNowUnmuteVolume(DECODER);
                            }
                            else
                                PRINT(("DECODER: connect l2cap dsp port 3 FAILED\n" ));
                        }
                        else
                        {
                            PRINT(("DECODER: connect l2cap dsp port 3, sub_sink = %x NOT VALID\n", (uint16)sub_sink ));
                        }
                        
                        /* determine if the subwoofer has connected after the decoder was loaded,
                           configured and unmuted */
                        if(codecData->sub_is_available == FALSE)
                        {
                            /* unmute the outputs again */
                            csrA2dpDecoderPluginOutputMute(multi_channel_group_all, AUDIO_MUTE_DISABLE);
                        }
                    }
                }
                else
                    PRINT(("DECODER: L2CAP - ****wrong link type****\n"));                                        
            break;
        }
    }
    else
        PRINT(("DECODER: CsrA2dpDecoderPluginSetSubWoofer ERROR NO DECODER\n" ));
}
Ejemplo n.º 4
0
/****************************************************************************
NAME
    connectAudioStreams

DESCRIPTION
    Helper function to connect the audio streams
*/
static void connectAudioStreams(void)
{
    /* Connect the appropriate input stream to Kalimba */
    if (plugin_data->input == SUBWOOFER_INPUT_ADC)
    {
        PRINT(("[SW_PLUGIN] : Plugging ADC to Kalimba [%u]\n", plugin_data->adc_sample_rate));
        
        /* Configure the ADC */
        PanicFalse( SourceConfigure(plugin_data->audio_source, STREAM_CODEC_INPUT_RATE, plugin_data->adc_sample_rate) );
        
        /* Plug the ADC sink into the Kalimba */
        PanicFalse( StreamConnect(plugin_data->audio_source, StreamKalimbaSink(DSP_INPUT_PORT_ADC)) );
    }
    else if (plugin_data->input == SUBWOOFER_INPUT_ESCO)
    {
        /* Enable meta-data on the audio input */
        if ( SourceConfigure(plugin_data->audio_source, VM_SOURCE_SCO_METADATA_ENABLE, 1))
        {
            /* Plug the eSCO sink into the Kalimba */
            if ( !StreamConnect(plugin_data->audio_source, StreamKalimbaSink(DSP_INPUT_PORT_ESCO)) )
            {
                PRINT(("[SW_PLUGIN] : Plugging ESCO to Kalimba [FAILED]\n"));
                sendErrorToClient();
                /* Nothing more can be done here */
                return;
            }
            else
            {
                PRINT(("[SW_PLUGIN] : ESCO connected to Kalimba\n"));
            }
        }
        else
        {
            PRINT(("[SW_PLUGIN] : Plugging ESCO to Kalimba [FAILED]\n"));
            sendErrorToClient();
            /* Nothing more can be done here */
            return;
        }
    }
    else if (plugin_data->input == SUBWOOFER_INPUT_L2CAP)
    {
        /* Plug the L2CAP sink into the Kalimba */
        if ( !StreamConnect(plugin_data->audio_source, StreamKalimbaSink(DSP_INPUT_PORT_L2CAP)) )
        {
            PRINT(("[SW_PLUGIN] : Plugging L2CAP to Kalimba [FAILED]\n"));
            sendErrorToClient();
            /* Nothing more can be done here */
            return;
        }
        else
        {
            PRINT(("[SW_PLUGIN] : L2CAP connected to Kalimba\n"));
        }
    }
    else
    {
        PRINT(("[SW_PLUGIN] : Plugin parameter INPUT[%x] is invalid\n", plugin_data->input));
        Panic();
    }
    
    /* Connect Kalimba to the appropriate output stream */
    if (plugin_data->output == SUBWOOFER_OUTPUT_DAC)
    {
        
        
        /* Get the Codec DAC sink & Configure output rate */
        plugin_data->codec_sink = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A_AND_B);
        if ( !SinkConfigure(plugin_data->codec_sink, STREAM_CODEC_OUTPUT_RATE, plugin_data->sample_rate) )
        {
            PRINT(("[SW_PLUGIN] : Could not configure DAC [%u]\n", plugin_data->sample_rate));
            sendErrorToClient();
            /* Nothing more can be done here */
            return;
        }
        
        /* Plug the audio route from Kalimba to the DAC */
        if ( !StreamConnect(StreamKalimbaSource(DSP_OUTPUT_PORT_DAC), plugin_data->codec_sink) )
        {
            PRINT(("[SW_PLUGIN] : Could not connect DAC to Kalimba[%u]\n", plugin_data->sample_rate));
            sendErrorToClient();
            /* Nothing more can be done here */
            return;
        }
        
        PRINT(("[SW_PLUGIN] : Kalimba connected to DAC\n"));
    }
    else if (plugin_data->output == SUBWOOFER_OUTPUT_I2S)
    {
        PRINT(("[SW_PLUGIN] : Plugging Kalimba to I2S [%u]\n", plugin_data->sample_rate));
        
        /* Is a specified output frequency required? use resampling */
        if(CsrI2SMusicResamplingFrequency())
        {
            CsrI2SAudioOutputConnect(CsrI2SMusicResamplingFrequency(), FALSE, StreamKalimbaSource(DSP_OUTPUT_PORT_I2S), NULL);
        }
        else
        {
            CsrI2SAudioOutputConnect(plugin_data->sample_rate, FALSE, StreamKalimbaSource(DSP_OUTPUT_PORT_I2S), NULL);
        }
    }
    else
    {
        PRINT(("[SW_PLUGIN] : Plugin parameter OUTPUT[%x] is invalid\n", plugin_data->output));
        Panic();
    }
    
    /* set dsp operating flags */
    SetCurrentDspStatus(DSP_RUNNING);
    SetAudioInUse(TRUE);
}
Ejemplo n.º 5
0
/****************************************************************************
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();
	}
	*/
}
static void CsrVoicePresencesPluginPlayDigit(void) 
{
    Source lSource ;
    voice_prompt prompt;
    
    /* Get the prompt data*/
    lSource = csrVoicePresencesGetPrompt(&prompt, koovox_phrase_data);
    if(!lSource) Panic();
    
    SetAudioBusy((TaskData*) &csr_voice_presences_plugin);

    /* Stash the source */
    koovox_phrase_data->source = lSource;
    koovox_phrase_data->decompression = prompt.decompression;
    koovox_phrase_data->stereo = prompt.stereo;
    koovox_phrase_data->playback_rate =  (prompt.playback_rate ? prompt.playback_rate : 8000);
    koovox_phrase_data->mixing = FALSE;    /* overridden later if this prompt is mixed */
    
    SetVpPlaying(TRUE);

	PRINT(("==decompression:%d===\n", prompt.decompression));

    /* Connect the stream to the DAC */
    switch(prompt.decompression)
    {
        case voice_prompts_codec_ima_adpcm:
        case voice_prompts_codec_none:     
        case voice_prompts_codec_tone:  
        {
            Sink lSink = NULL;
            Task taskdata = NULL;
            
            /* if DSP is already running, the voice prompt can be mixed with the dsp
               audio via the kalimba mixing port (3), either the CVC plugin or
               the music plugin will have already determined the output source and connected the 
               appropriate ports to the hardware, the volume will already have been set, it is not
               necessary to do it again */
            if(GetCurrentDspStatus())
            {            
                /* Configure tone or prompt playback */    
                if(prompt.decompression == voice_prompts_codec_tone)
                {
                    PRINT(("PRESENT: play tone\n"));
                    KalimbaSendMessage(MESSAGE_SET_TONE_RATE_MESSAGE_ID, koovox_phrase_data->playback_rate , 0/*Mono Bit 0 =0, TONE BIT 1 = 0*/, 0, 0); 
                }                    
                else
                {
                    PRINT(("PRESENT: play adpcm\n"));
                    KalimbaSendMessage(MESSAGE_SET_TONE_RATE_MESSAGE_ID, koovox_phrase_data->playback_rate , /*PROMPT_MONO*/PROMPT_ISPROMPT, 0, 0);                                  
                }
                /* stream voice prompt data to the DSP tone mixing port */                
                koovox_phrase_data->mixing = TRUE;
                lSink = StreamKalimbaSink(PRESENT_DSP_PORT);
                PRINT(("PRESENT: play dsp mix lSink = %x lSource = %x\n",(uint16)lSink,(uint16)lSource));
                SinkConfigure(lSink, STREAM_CODEC_OUTPUT_RATE, koovox_phrase_data->playback_rate);
                
                /* Get messages when source has finished */
                taskdata = MessageSinkTask( lSink , (TaskData*) &csr_voice_presences_plugin);

                /* connect the kalimba port to the audio_prompt */
                if(prompt.decompression == voice_prompts_codec_ima_adpcm)
                {   
                    PanicFalse(TransformStart(TransformAdpcmDecode(lSource, lSink)));
                }
                else
                {                      
                    PanicFalse(StreamConnect(lSource, lSink)); 
                }   
                
            }
			else
			{
				CsrVoicePresencesPluginStopPhrase();
			}
        }
        break;
        
        case voice_prompts_codec_pcm:        
        {    
            Sink lSink = NULL;
            Task taskdata = NULL;
            
            /* determine whether the prompt is being played as a mixed with audio via the dsp, if the dsp is being
               used for audio mixing there is no need to set the volume as this will already have been performed 
               plugin used to load the dsp for audio processing */            
            if(GetCurrentDspStatus())
            {
                /* store that this PCM prompt is mixing */
                koovox_phrase_data->mixing = TRUE;
                
                /* stream voice prompt data to the DSP tone mixing port */                
                lSink = StreamKalimbaSink(PRESENT_DSP_PORT);
                PRINT(("PRESENT: play dsp mix lSink = %x lSource = %x\n",(uint16)lSink,(uint16)lSource));
                SinkConfigure(lSink, STREAM_CODEC_OUTPUT_RATE, koovox_phrase_data->playback_rate);                               
                
                /* Get messages when source has finished */
                taskdata = MessageSinkTask( lSink , (TaskData*) &csr_voice_presences_plugin);

				PRINT(("PRESENT: sink task now %x was %x.\n",(uint16)&csr_voice_presences_plugin,(uint16)taskdata));
                /* Configure PCM prompt playback */    
                KalimbaSendMessage(MESSAGE_SET_TONE_RATE_MESSAGE_ID, koovox_phrase_data->playback_rate , (koovox_phrase_data->stereo?PROMPT_STEREO:0)|PROMPT_ISPROMPT, 0, 0);        
                
                /* Connect source to PCM */
                PanicFalse(StreamConnect(lSource, lSink));
            }
        }
        break;

        default:
            PRINT(("PRESENT: Codec Invalid\n"));
            Panic();
        break;
    }

}
/****************************************************************************
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();
		}
      
   }
/****************************************************************************
DESCRIPTION
    This function connects APTX low delay audio 
****************************************************************************/
void MusicConnectAptxLowLatency(A2dpPluginConnectParams *codecData, uint8 content_protection)
{
    Sink speaker_snk_a = NULL;
    Transform rtp_transform = 0;
    DECODER_t * DECODER = CsrA2dpDecoderGetDecoderData();
    
    /* when configured for using back channel low latency apps */
    if(isCodecLowLatencyBackChannel())
    {
        /* if the back channel is required and the mic/line input is configured */
        if (codecData->voice_rate)
        {
            /* Bidirectional channel uses faststream mono with the following settings */
            /*
               Configure the SBC format for the microphone data
               16kHz, Mono, Blocks 16, Sub-bands 8, Loudness, Bitpool = 32
               (data rate = 72kbps, packet size = 3*72 + 4 = 220 <= DM5).
            */
           codecData->format     = 0x31;
           codecData->bitpool    = 32;
           PRINT(("DECODER: apt-X Low Latency Bidirectional rate=0x%lx voice_rate=0x%lx\n format=0x%x\n",DECODER->rate,codecData->voice_rate,codecData->format));
        }
    }

    /* ensure the sample rate is valid */
    if (DECODER->rate)
    {
        /* disconnect media sink as it might be disposed */
        StreamDisconnect(StreamSourceFromSink(DECODER->media_sink), 0);

                /* determine the output hardware type */
        switch(DECODER->features.audio_output_type)
        {
            /* using the inbuilt dacs */
            case OUTPUT_INTERFACE_TYPE_NONE:
            case OUTPUT_INTERFACE_TYPE_DAC:
            {
                /* configure built-in audio hardware channel A */
                speaker_snk_a = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_A);
                PanicFalse(SinkConfigure(speaker_snk_a, STREAM_CODEC_OUTPUT_RATE, DECODER->rate));
    
                /* if STEREO mode configured then connect the output channel B */
                if(DECODER->features.stereo)
                {
                    Sink speaker_snk_b = NULL;
        
                    PRINT(("DECODER: Stereo\n"));
        
                    /* connect channels B */
                    speaker_snk_b = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, AUDIO_CHANNEL_B);
                    /* configure channel to required rate */
                    PanicFalse(SinkConfigure(speaker_snk_b, STREAM_CODEC_OUTPUT_RATE, DECODER->rate));
                    /* synchronise both sinks for channels A & B */
                    PanicFalse(SinkSynchronise(speaker_snk_a, speaker_snk_b));
                    /* plug port 1 into Right DAC */
                    PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT),speaker_snk_a));
                    PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT),speaker_snk_b));
                }
                /* mono operation, only connect left port */
                else
                {
                    /* plug port 0 into Left DAC */
                    PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT),speaker_snk_a));
                }
            }
            break;

            /* using the spdif digital output hardware */
            case OUTPUT_INTERFACE_TYPE_SPDIF:
            {
                Sink speaker_snk_b = NULL;
                /* configure spdif audio hardware channel 0 */
                speaker_snk_a = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_A);
                speaker_snk_b = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_B);
                /* configure channel to required rate */
                PanicFalse(SinkConfigure(speaker_snk_a,  STREAM_SPDIF_OUTPUT_RATE, DECODER->rate));
                PanicFalse(SinkConfigure(speaker_snk_b,  STREAM_SPDIF_OUTPUT_RATE, DECODER->rate));
                /* connect channels B */
                /* synchronise both sinks for channels A & B */
                PanicFalse(SinkSynchronise(speaker_snk_a, speaker_snk_b));
                /* plug port 1 into Right DAC */
                PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT),speaker_snk_a));
                PanicFalse(StreamConnect(StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT),speaker_snk_b));   
      
                PRINT(("DECODER: Stereo\n"));
            }
            break;
            
            /* using the i2s digital output hardware */
            case OUTPUT_INTERFACE_TYPE_I2S:
            {
                /* is a specified output frequency required? use resampling*/
                if(CsrI2SMusicResamplingFrequency())
                    CsrI2SAudioOutputConnect(CsrI2SMusicResamplingFrequency(), DECODER->features.stereo, StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT), StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT));                                 
                /* use the negotiated sample rate of the input, no resampling required */                
                else
                    CsrI2SAudioOutputConnect(DECODER->rate, DECODER->features.stereo, StreamKalimbaSource(AUDIO_OUT_FROM_DSP_LEFT), StreamKalimbaSource(AUDIO_OUT_FROM_DSP_RIGHT));                                                                
            }            
            break;
        }
    
        /* if content protection is required feed the media sink through the rtp decoder transform */
        if (content_protection)
        {
            rtp_transform = TransformRtpDecode(StreamSourceFromSink(DECODER->media_sink) , StreamKalimbaSink(LOW_LATENCY_CODEC_TO_DSP_PORT));
            TransformConfigure(rtp_transform, VM_TRANSFORM_RTP_SCMS_ENABLE, content_protection);
            /*start the transform decode*/
            PRINT(("aptX: RTP Transform \n"));
            (void)TransformStart( rtp_transform ) ;
        }
        /* connect the media sink to the dsp input port */
        else
        {
            PanicFalse(StreamConnect(StreamSourceFromSink(DECODER->media_sink),StreamKalimbaSink(LOW_LATENCY_CODEC_TO_DSP_PORT)));
        }
    }
    
    /* Send parameters that configure the SRA and buffer settings */
    PRINT(("aptX LL params: initial level=%d target level=%d sra max rate=%d/10000 sra avg time=%d good working buffer level=%d \n",
           codecData->aptx_sprint_params.target_codec_level,codecData->aptx_sprint_params.initial_codec_level,
           codecData->aptx_sprint_params.sra_max_rate,codecData->aptx_sprint_params.sra_avg_time,
           codecData->aptx_sprint_params.good_working_level));
    KalimbaSendMessage(MESSAGE_SET_APTX_LL_PARAMS1, codecData->aptx_sprint_params.target_codec_level,
                       codecData->aptx_sprint_params.initial_codec_level,
                       codecData->aptx_sprint_params.sra_max_rate,   /* Third field is scaled by 10000 */
                       codecData->aptx_sprint_params.sra_avg_time);
    KalimbaSendMessage(MESSAGE_SET_APTX_LL_PARAMS2, codecData->aptx_sprint_params.good_working_level,
                       0, 0, 0);

    /* update the current audio state */
    SetAudioInUse(TRUE);
}