/**************************************************************************** DESCRIPTION Stop prompt where DSP has not been loaded by the plugin, e.g. (adpcm or pcm) Prompt is either mixing in an existing DSP app or not using the DSP. */ static void CsrVoicePresencesPluginStopPhraseMixable ( void ) { Sink lSink=NULL; Task taskdata = NULL; /* Check for DSP mixing */ if(GetCurrentDspStatus()) { lSink = StreamKalimbaSink(PRESENT_DSP_PORT); /* reset the volume levels of the dsp plugin */ if(GetAudioPlugin()) MessageSend( GetAudioPlugin(), AUDIO_PLUGIN_RESET_VOLUME_MSG, 0 ) ; } else /* Must be ADPCM not mixing */ { switch(koovox_phrase_data->features.audio_output_type) { /* is the I2S required? */ case OUTPUT_INTERFACE_TYPE_I2S: { CsrI2SAudioOutputDisconnect( koovox_phrase_data->features.stereo); } break; /* spdif output? */ case OUTPUT_INTERFACE_TYPE_SPDIF: { Sink rSink = NULL; /* obtain source to SPDIF hardware and disconnect it */ lSink = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_A ); rSink = StreamAudioSink(AUDIO_HARDWARE_SPDIF, AUDIO_INSTANCE_0, SPDIF_CHANNEL_B ); StreamDisconnect(0, lSink); StreamDisconnect(0, rSink); SinkClose(lSink); SinkClose(rSink); } break; /* use built in codec */ default: { lSink = StreamAudioSink(AUDIO_HARDWARE_CODEC,AUDIO_INSTANCE_0, (koovox_phrase_data->features.stereo ? AUDIO_CHANNEL_A_AND_B : AUDIO_CHANNEL_A)); /* Disconnect PCM source/sink */ StreamDisconnect(StreamSourceFromSink(lSink), lSink); } } } /* close sink and cancel any messages if valid */ if(lSink) { /* Cancel all the messages relating to VP that have been sent */ taskdata = MessageSinkTask(lSink, NULL); SinkClose(lSink); } PRINT(("PRESENT: SinkTask now NULL was %x\n",(uint16)taskdata)); MessageCancelAll((TaskData*) &csr_voice_presences_plugin, MESSAGE_STREAM_DISCONNECT); }
/**************************************************************************** NAME audioControlLowPowerCodecs DESCRIPTION Enables / disables the low power codecs. will only use low power codecs is the flag UseLowPowerCodecs is set and enable == TRUE This fn is called whenever an audioConnect occurs in order to select the right codec ouptut stage power . RETURNS none */ void audioControlLowPowerCodecs( bool enable ) { audio_channel channel = AUDIO_CHANNEL_A ; Sink sink = NULL ; if ( theSink.features.stereo ) { channel = AUDIO_CHANNEL_A_AND_B; } /* obtain sink to audio hardware */ sink = StreamAudioSink(AUDIO_HARDWARE_CODEC, AUDIO_INSTANCE_0, channel); /* ensure sink is valid */ if(sink) { /* if low power codec use is disabled in features ps or enable is false */ if ((!theSink.features.UseLowPowerAudioCodecs)||(!enable)) { /*disable low power codecs as feature disabled or enable override is set */ AUD_DEBUG(("AUD:LowPowerCodecDisable CODEC NORMAL, feature [%c] enable [%c]\n", theSink.features.UseLowPowerAudioCodecs? 'T':'F', enable? 'L':'N')) ; #ifdef BC5_MULTIMEDIA /* set to normal mode */ PanicFalse(SinkConfigure(sink, STREAM_CODEC_LOW_POWER_OUTPUT_STAGE_ENABLE, FALSE )); #else /* set codec to high quality mode */ PanicFalse(SinkConfigure(sink, STREAM_CODEC_QUALITY_MODE, CODEC_HIGH_MODE )) ; #endif } /* if the low power audio codec feature is enabled and the enable is true */ else { #ifdef BC5_MULTIMEDIA /* enable the low power mode */ PanicFalse(SinkConfigure(sink, STREAM_CODEC_LOW_POWER_OUTPUT_STAGE_ENABLE, TRUE)) ; #else /* set the codec type to low power telephony mode */ PanicFalse(SinkConfigure(sink, STREAM_CODEC_QUALITY_MODE, CODEC_TELEPHONY_MODE )) ; #endif AUD_DEBUG(("AUD:LowPowerCodecEnable CODEC LOW POWER, feature [%c] enable [%c]\n", theSink.features.UseLowPowerAudioCodecs? 'T':'F', enable? 'L':'N')) ; } /* Close the Source/Sink */ SinkClose(sink); } }
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)); }
/**************************************************************************** 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); }
/**************************************************************************** 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); }