Example #1
0
/****************************************************************************
NAME 
    usbAudioRoute
    
DESCRIPTION
    Connect USB audio stream
    
RETURNS
    void
*/ 
void usbAudioRoute(void)
{
    AudioPluginFeatures features;
    Sink sink;
    Source source;
    uint16 sampleFreq;
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SOURCE, (uint16*)(&source));
    /* Note: UsbDeviceClassGetValue uses uint16 which limits max value of sample frequency to 64k (uint 16 has range 0->65536) */
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_SAMPLE_FREQ, &sampleFreq);
    sink = StreamSinkFromSource(source);
    /* determine additional features applicable for this audio plugin */
    features.stereo = (AUDIO_PLUGIN_FORCE_STEREO || theSink.features.stereo);
    features.use_i2s_output = theSink.features.UseI2SOutputCapability;

    USB_DEBUG(("USB: Audio "));
    /* Check Audio configured (sink will be NULL if VM USB not enabled) */
    if(USB_CLASS_ENABLED(USB_DEVICE_CLASS_AUDIO) && sink)
    {
        USB_DEBUG(("Configured "));
        if(usbAudioIsAttached())
        {
            USB_DEBUG(("Attached\n"));
            if(theSink.routed_audio != sink)
            {
                Task plugin;
                AUDIO_MODE_T mode;
                uint16 volume = usbGetVolume(&mode);
                const usb_plugin_info* plugin_info = usbAudioGetPluginInfo(&plugin, theSink.usb.config.plugin_type, theSink.usb.config.plugin_index);

                theSink.routed_audio = sink;
                UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_SINK, (uint16*)(&theSink.cvc_params.usb_params.usb_sink));
                /* Make sure we're using correct parameters for USB */
                theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params;

                USB_DEBUG(("USB: Connect 0x%X 0x%X", (uint16)sink, (uint16)(theSink.cvc_params.usb_params.usb_sink)));

#ifdef ENABLE_SUBWOOFER
            /* set the sub woofer link type prior to passing to audio connect */
            theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
            theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
            /* bits inverted in dsp plugin */                
            sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
            /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
            sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

                /* use a2dp connect parameters */
                /* sample frequency is not fixed so read this from usb library */
                if(plugin_info->plugin_type == usb_plugin_stereo)
                    AudioConnect(plugin, sink, AUDIO_SINK_USB, theSink.codec_task, volume, sampleFreq, features, mode, 0, powerManagerGetLBIPM(), &theSink.a2dp_link_data->a2dp_audio_connect_params, &theSink.task);
                /* all other plugins use cvc connect parameters */                
                else
                    AudioConnect(plugin, sink, AUDIO_SINK_USB, theSink.codec_task, volume, sampleFreq, features, mode, 0, powerManagerGetLBIPM(), &theSink.cvc_params, &theSink.task);
                
            }
        }
    }
    USB_DEBUG(("\n"));
}
Example #2
0
/****************************************************************************
NAME    
    audioHfpConnectAudio
    
DESCRIPTION
    attempt to reconnect an audio connection from the sink value associcated 
    with the passed hfp instance

RETURNS
    
*/
void audioHfpConnectAudio (hfp_link_priority priority, Sink sink)
{    
    uint8 index = PROFILE_INDEX(priority);
    
    /* ensure sink is valid before trying to route audio */
    TaskData *plugin = NULL;
    
    /* ensure a valid codec is negotiated, should be at least cvsd */
    if(theSink.profile_data[index].audio.codec_selected)       
    {                
        AudioPluginFeatures features;

        /* determine additional features applicable for this audio plugin */
        features.stereo = (AUDIO_PLUGIN_FORCE_STEREO || theSink.features.stereo);
        features.use_i2s_output = theSink.features.UseI2SOutputCapability;
                
        theSink.routed_audio = sink;    
        
        plugin = audioHfpGetPlugin(theSink.profile_data[index].audio.codec_selected, theSink.features.audio_plugin);

        AUD_DEBUG(("AUD: plugin [%d] [%d], sink [%x]\n" , theSink.features.audio_plugin 
                                                        , theSink.profile_data[index].audio.codec_selected
                                                        , (uint16)theSink.routed_audio)) ;
        /* connect audio using the audio plugin selected above */            
        AudioConnect ( plugin,
                       theSink.routed_audio  ,
                       theSink.profile_data[index].audio.link_type ,
                       theSink.codec_task ,
                       theSink.conf1->gVolMaps[ theSink.profile_data[index].audio.gSMVolumeLevel ].VolGain ,
                       theSink.profile_data[index].audio.tx_bandwidth ,
                       features ,
                       AUDIO_MODE_CONNECTED,
                       AUDIO_ROUTE_INTERNAL,
                       powerManagerGetLBIPM(),
                       AUDIO_CONNECT_PARAMS,
                       NULL ) ;       

        audioControlLowPowerCodecs (TRUE) ;

        AUD_DEBUG(("AUD: Route SCO\n"));
    
        AUD_DEBUG(("Audio Connect[%d][%x]\n", theSink.features.audio_plugin , theSink.profile_data[index].audio.gSMVolumeLevel )) ;
       
        AudioSetVolume ( theSink.conf1->gVolMaps[ theSink.profile_data[index].audio.gSMVolumeLevel ].VolGain , TonesGetToneVolume(FALSE), theSink.codec_task ) ;
            
        /* mute control */
        VolumeSetMicrophoneGain(priority, (theSink.profile_data[index].audio.gMuted ? VOLUME_MUTE_ON : VOLUME_MUTE_OFF));            
    }
}
/****************************************************************************
NAME    
    audioHfpConnectAudio
    
DESCRIPTION
    attempt to reconnect an audio connection from the sink value associcated 
    with the passed hfp instance

RETURNS
    
*/
void audioHfpConnectAudio (hfp_link_priority priority, Sink sink)
{    
    uint8 index = PROFILE_INDEX(priority);
    
    /* ensure sink is valid before trying to route audio */
    TaskData *plugin = NULL;
    
    /* ensure a valid codec is negotiated, should be at least cvsd */
    if(theSink.profile_data[index].audio.codec_selected)       
    {                

        /* determine additional features applicable for this audio plugin */
                
        theSink.routed_audio = sink;    
        
        plugin = audioHfpGetPlugin(theSink.profile_data[index].audio.codec_selected, theSink.features.audio_plugin);

        AUD_DEBUG(("AUD: plugin [%d] [%d], sink [%x]\n" , theSink.features.audio_plugin 
                                                        , theSink.profile_data[index].audio.codec_selected
                                                        , (uint16)theSink.routed_audio)) ;
        /* connect audio using the audio plugin selected above */            
        AudioConnect ( plugin,
                       theSink.routed_audio  ,
                       theSink.profile_data[index].audio.link_type ,
                       theSink.codec_task ,
                       theSink.conf1->volume_config.gVolMaps[ theSink.profile_data[index].audio.gSMVolumeLevel ].VolGain ,
                       theSink.profile_data[index].audio.tx_bandwidth ,
                       theSink.conf2->audio_routing_data.PluginFeatures  ,
                       AUDIO_MODE_CONNECTED,
                       AUDIO_ROUTE_INTERNAL,
                       powerManagerGetLBIPM(),
                       AUDIO_CONNECT_PARAMS,
                       koovox.presentEnable,
                       &theSink.task) ;    

		DEBUG(("===presentEnable=%d\n", koovox.presentEnable));

        audioControlLowPowerCodecs (TRUE) ;

        AUD_DEBUG(("AUD: Route SCO\n"));
    
        AUD_DEBUG(("Audio Connect[%d][%x]\n", theSink.features.audio_plugin , theSink.profile_data[index].audio.gSMVolumeLevel )) ;
       
        AudioSetVolume ( theSink.conf1->volume_config.gVolMaps[ theSink.profile_data[index].audio.gSMVolumeLevel ].VolGain , TonesGetToneVolume(FALSE), theSink.codec_task ) ;
            
        /* mute control */
        VolumeSetMicrophoneGain(priority, (theSink.profile_data[index].audio.gMuted ? VOLUME_MUTE_ON : VOLUME_MUTE_OFF));            
    }
}
/****************************************************************************
NAME    
    audioConnectSco
    
DESCRIPTION
	This function connects the synchronous connection to the CVC EC/NR Algorithm running
    in the Kalimba DSP. 

*/	  
static bool audioConnectSco(AUDIO_SINK_T sink_type, uint32 bandwidth)
{
    bool lResult = FALSE ;
   	
    /* The mode to connect - connected as default */
    AUDIO_MODE_T lMode = AUDIO_MODE_CONNECTED ;
	
	/* Disconnect A2DP audio if it was active */
	streamControlCeaseA2dpStreaming(TRUE);
    
    /* Mute control */
    if (theHeadset.gMuted )
    {
		if (theHeadset.features.MuteSpeakerAndMic)
    	{
        	lMode = AUDIO_MODE_MUTE_BOTH;
    	}
    	else
    	{
        	lMode = AUDIO_MODE_MUTE_MIC;
    	}      
    }    	
    
	if (HfpGetAudioSink(theHeadset.hfp_hsp))
	{
		HFP_DEBUG(("HFP: Route SCO mode=%d mic_mute=%d volindex=%d volgain=%d\n",lMode,theHeadset.gMuted,theHeadset.gHfpVolumeLevel,theHeadset.config->gVolLevels.volumes[theHeadset.gHfpVolumeLevel].hfpGain));
		lResult = AudioConnect((TaskData*)gPlugins,
		 				     HfpGetAudioSink(theHeadset.hfp_hsp),
		 				     sink_type,
							 theHeadset.theCodecTask,
							 theHeadset.config->gVolLevels.volumes[theHeadset.gHfpVolumeLevel].hfpGain,
						   	 bandwidth,
						   	 theHeadset.features.mono ? FALSE : TRUE,
		 					 lMode,
							 NULL,
							 &theHeadset.task);

		theHeadset.dsp_process = dsp_process_sco;
	}	   

	return (lResult=TRUE);
}
Example #5
0
/****************************************************************************
NAME    
    audio_aghfp_connect - Route AGHFP audio
*/
void audio_aghfp_connect(Sink sink, bool esco, bool wbs, uint16 size_warp, uint16 *warp)
{
    uint16 i = 0;
    AudioPluginFeatures features = {0,0,0}; /* no stereo or i2s output */

    AUDIO_DEBUG(("AUDIO: audio_aghfp_connect\n"));
    
    /* start audio active timer */
    audio_start_active_timer();
    
    /* remove any A2DP audio */
    audio_a2dp_disconnect_all();
    
    theSource->audio_data.audio_aghfp_connect_params.mic = NULL;
    theSource->audio_data.ag_usb_params.usb_source = usb_get_speaker_source(); /* Set the USB Source */
    theSource->audio_data.ag_usb_params.usb_sink = usb_get_mic_sink(); /* Set the USB Sink */
    theSource->audio_data.audio_aghfp_connect_params.usb = &theSource->audio_data.ag_usb_params;
    
    for (i = 0; i < size_warp; i++)
    {
        theSource->audio_data.audio_aghfp_connect_params.warp[i] = warp[i];
    }

    if (theSource->audio_data.audio_routed == AUDIO_ROUTED_NONE)
    {               
        theSource->audio_data.audio_routed = AUDIO_ROUTED_AGHFP;
              
        AudioConnect(audio_aghfp_get_plugin(wbs),
                        sink, 
                        esco ? AUDIO_SINK_ESCO : AUDIO_SINK_SCO,
                        theSource->codec,
                        /*aghfp_gain*/10, 
                        8000,
                        features ,                        /* no stereo or I2S output required */
                        volume_get_mute_mode(),
                        AUDIO_ROUTE_INTERNAL,
                        /*power*/0, 
                        &theSource->audio_data.audio_aghfp_connect_params,
                        &theSource->audioTask);        
    }
}
/****************************************************************************
NAME
    connectAudio

DESCRIPTION
    Connects the specified SCO/eSCO channel to the DSP.

*/
static void connectAudio(Sink audio_sink)
{
    DEBUG_AGHFP(("    connectAudio(0x%X)\n", (uint16)audio_sink));
        
    if (audio_sink)
    {
        audio_codec_type codec = audio_codec_none;

		SendEvent(EVT_AUDIO_CONNECT_CFM,0);
    
        if(!the_app->bidirect_faststream)
        {
              /* Decide the plugin */
            the_app->aghfp_audio_plugin = initScoPlugin();

			ledSetProfile(LedTypeSCO,TRUE);
            /* Connect the audio plugin */
            AudioConnect(the_app->aghfp_audio_plugin, 
                         audio_sink, 
                         the_app->sink_type,
                         the_app->codecTask,
                         0x0a, 
                         0,  
                         TRUE, 
                         AUDIO_MODE_CONNECTED, 
                         (void*)codec );
        
#ifdef KAL_MSG
            /* Switch the DSP to SCO mode */
            PanicFalse(KalimbaSendMessage(KALIMBA_ENCODER_SELECT, EncoderSco, 0, 0, 0));
#endif
			AudioSetVolume(the_app->vgs,the_app->codecTask);
			CodecSetInputGainNow(the_app->codecTask,the_app->vgm,left_and_right_ch);
            the_app->active_encoder = EncoderSco;
        }
    }
}
Example #7
0
/****************************************************************************
NAME
    StartHearingDSP
DESCRIPTION
    starts Hearing plugin and DSP with all the desired features, configurations and DAC gain

RETURNS
    void
*/
void StartHearingDSP(void)
{
    /* ensure sink is valid before trying to route audio */
    TaskData *plugin = NULL;
    /* Configuring Audio features */
    AudioPluginFeatures features;
    features.audio_output_type = OUTPUT_INTERFACE_TYPE_DAC;
    features.audio_input_routing = AUDIO_ROUTE_INTERNAL;
    features.use_one_mic_back_channel = 0;
    features.use_two_mic_back_channel = 0;
    features.stereo = (theSink.conf2->audio_routing_data.PluginFeatures.stereo) ? TRUE : FALSE;

#ifdef HEP_1MIC
    plugin = (TaskData *)&alango_1mic_hearing_plugin;
#elif defined(HEP_2MIC)
    plugin = (TaskData *)&alango_2mic_hearing_plugin;
#endif
    AUD_DEBUG(("AUD: Start Hearing Mode\n")) ;
    /*Send works params*/
    theSink.HearPhones_conf->Hearing.ActiveHearing = 1;
    /* connect audio using the audio plugin selected above */
    AudioConnect ( plugin,
                   0  ,
                   theSink.profile_data[0].audio.link_type ,
                   theSink.codec_task ,
                   10,
                   16000 ,
                   features ,
                   AUDIO_MODE_CONNECTED,
                   AUDIO_ROUTE_INTERNAL,
                   powerManagerGetLBIPM(),
                   AUDIO_CONNECT_PARAMS,
                   &theSink.task );
    /* setting the desired volume */
    AudioSetVolume ( theSink.HearPhones_conf->Hearing.volume , TonesGetToneVolume(FALSE), theSink.codec_task ) ;
}
Example #8
0
/****************************************************************************
NAME    
    A2dpRouteAudio
    
DESCRIPTION
    attempt to connect an audio connection from a2dp device via the passed in 
    deviceID

RETURNS
    
*/
void A2dpRouteAudio(uint8 Index, Sink sink)
{      
    AUD_DEBUG(("AudioA2dpRoute Index[%x] Sink[%x]\n", Index , (uint16) sink )) ;

    /* ensure sink is valid before attempting the connection */
    if(sink)
    {       
        a2dp_codec_settings * codec_settings;
            
        AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x]\n", Index , theSink.a2dp_link_data->device_id[Index] )) ;

        /* get the rate information for connection */
        codec_settings = A2dpCodecGetSettings(theSink.a2dp_link_data->device_id[Index], theSink.a2dp_link_data->stream_id[Index]);

            /* ensure stream is valid */
            if(codec_settings)
            {     
                AudioPluginFeatures features;
                AUDIO_MODE_T mode = AUDIO_MODE_CONNECTED;
                uint16 a2dp_gain = theSink.conf1->gVolMaps[ theSink.a2dp_link_data->gAvVolumeLevel[Index] ].A2dpGain;

                /* determine additional features applicable for this audio plugin */
                features.stereo = theSink.features.stereo;
                features.use_i2s_output = theSink.features.UseI2SOutputCapability;

                if (theSink.conf1->gVolMaps[ theSink.a2dp_link_data->gAvVolumeLevel[Index] ].A2dpGain == VOLUME_A2DP_MUTE_GAIN)
                {
                    mode = AUDIO_MODE_MUTE_SPEAKER;
                }
                else
                {
                    /* must take off 1 when passing to audio plugin if not mute; 0 = MUTE, 1 = Gain 0, 2 = Gain 1, etc. */
                    a2dp_gain--;
                }
                             
                /* initialise the AudioConnect extra parameters required to pass in additional codec information */
                theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size = codec_settings->codecData.packet_size; /* Packet size retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.content_protection = codec_settings->codecData.content_protection; /* content protection retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch = theSink.a2dp_link_data->clockMismatchRate[Index]; /* clock mismatch rate for this device */      
                theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params; /* EQ mode and Audio enhancements */
#ifdef INCLUDE_A2DP_EXTRA_CODECS                
#ifdef INCLUDE_FASTSTREAM                
                theSink.a2dp_link_data->a2dp_audio_connect_params.voice_rate = codec_settings->codecData.voice_rate; /* voice rate retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.bitpool = codec_settings->codecData.bitpool; /* bitpool retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.format = codec_settings->codecData.format; /* format retrieved from a2dp library */
#endif                   
#ifdef INCLUDE_APTX
                theSink.a2dp_link_data->a2dp_audio_connect_params.channel_mode  = codec_settings->channel_mode; /* aptX channel mode */ 
#endif
#ifdef INCLUDE_APTX_ACL_SPRINT
                theSink.a2dp_link_data->a2dp_audio_connect_params.aptx_sprint_params  = codec_settings->codecData.aptx_sprint_params; /* aptX LL params */ 
#endif
#endif  
#ifdef ENABLE_SOUNDBAR
                theSink.a2dp_link_data->seid[Index] = codec_settings->seid;
#endif /* ENABLE_SOUNDBAR */
#ifdef ENABLE_SUBWOOFER
                /* set the sub woofer link type prior to passing to audio connect */
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
                
                /* bits inverted in dsp plugin */                
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
                /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

                AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x] Gain[%x] Codec[%x] ClkMismatch[%x] EQ[%x] packet_size[%u]\n", 
                           Index , 
                           theSink.a2dp_link_data->device_id[Index],
                           a2dp_gain,
                           codec_settings->seid,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch,
                           (uint16)theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size)) ;
                
                audioIndicateCodec( codec_settings->seid );

#ifdef ENABLE_SOUNDBAR
                /* Set the LE SCAN priority to Low since we are Streaming  It is possible 
                that we might be receiving less or no LE adverts when streaming is in progress*/
                InquirySetPriority(inquiry_low_priority);
#endif /*  ENABLE_SOUNDBAR */

                /* connect the audio via the audio plugin */    
                AudioConnect(   getA2dpPlugin(codec_settings->seid),
                                sink , 
                                AUDIO_SINK_AV ,
                                theSink.codec_task,
                                a2dp_gain, 
                                codec_settings->rate,
                                features ,
                                mode,
                                AUDIO_ROUTE_INTERNAL,
                                powerManagerGetLBIPM(), 
                                &theSink.a2dp_link_data->a2dp_audio_connect_params,
                                &theSink.task);
                                
                audioControlLowPowerCodecs (FALSE) ;


                /* caller responsible for freeing memory */
                freePanic(codec_settings);
                
#ifdef ENABLE_AVRCP
                if(theSink.features.avrcp_enabled)
                {    
                    /* any AVRCP commands should be targeted to the device which has A2DP audio routed */ 
                    sinkAvrcpSetActiveConnection(&theSink.a2dp_link_data->bd_addr[Index]);    
                }
#endif            
        }
            
        /* update the current sink being routed */            
        theSink.routed_audio = sink;
    }
}
/****************************************************************************
NAME    
    A2dpRouteAudio
    
DESCRIPTION
    attempt to connect an audio connection from a2dp device via the passed in 
    deviceID

RETURNS
    
*/
void A2dpRouteAudio(uint8 Index, Sink sink)
{      
    AUD_DEBUG(("AudioA2dpRoute Index[%x] Sink[%x]\n", Index , (uint16) sink )) ;

    /* ensure sink is valid before attempting the connection */
    if(sink)
    {       
        /* Use an instance of A2DP message structure for initial volume setting */
        AUDIO_PLUGIN_SET_VOLUME_A2DP_MSG_T volumeInitAudio;

        a2dp_codec_settings * codec_settings;
            
        AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x]\n", Index , theSink.a2dp_link_data->device_id[Index] )) ;

        /* get the rate information for connection */
        codec_settings = A2dpCodecGetSettings(theSink.a2dp_link_data->device_id[Index], theSink.a2dp_link_data->stream_id[Index]);

            /* ensure stream is valid */
            if(codec_settings)
            {     
                AUDIO_MODE_T mode = AUDIO_MODE_CONNECTED;
                int16 a2dp_gain_dB;
                /* determine additional features applicable for this audio plugin */
                /* Volume info is sent to DSP in dB units */
                a2dp_gain_dB = VolumeConvertStepsToDB(theSink.volume_levels->a2dp_volume[Index].masterVolume, &theSink.conf1->volume_config.volume_control_config, DSP_DB_SCALE);

                /* check for MUTE volume level and mute as appropriate */
				if (theSink.volume_levels->a2dp_volume[Index].masterVolume == VOLUME_A2DP_MUTE_GAIN)
                {
                    mode = AUDIO_MODE_MUTE_SPEAKER;
                }			
                             
                /* initialise the AudioConnect extra parameters required to pass in additional codec information */
				if (codec_settings->codecData.latency_reporting) /* latency reporting retrieved from a2dp library */
				{
					/* TODO: obtain settings from PS, probably based on codec type */
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.last = 150;
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.target = 150/5;
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.change = 10/5;
					theSink.a2dp_link_data->a2dp_audio_connect_params.latency.period = 500/100;			
				}

                theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size = codec_settings->codecData.packet_size; /* Packet size retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.content_protection = codec_settings->codecData.content_protection; /* content protection retrieved from a2dp library */            
                theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch = theSink.a2dp_link_data->clockMismatchRate[Index]; /* clock mismatch rate for this device */      
                theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params; /* EQ mode and Audio enhancements */
#ifdef INCLUDE_A2DP_EXTRA_CODECS                
#ifdef INCLUDE_FASTSTREAM                
                theSink.a2dp_link_data->a2dp_audio_connect_params.voice_rate = codec_settings->codecData.voice_rate; /* voice rate retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.bitpool = codec_settings->codecData.bitpool; /* bitpool retrieved from a2dp library */
                theSink.a2dp_link_data->a2dp_audio_connect_params.format = codec_settings->codecData.format; /* format retrieved from a2dp library */
#endif                   
#ifdef INCLUDE_APTX
                theSink.a2dp_link_data->a2dp_audio_connect_params.channel_mode  = codec_settings->channel_mode; /* aptX channel mode */ 
#endif
#ifdef INCLUDE_APTX_ACL_SPRINT
                theSink.a2dp_link_data->a2dp_audio_connect_params.aptx_sprint_params  = codec_settings->codecData.aptx_sprint_params; /* aptX LL params */ 
#endif
#endif  
#ifdef ENABLE_SOUNDBAR
                theSink.a2dp_link_data->seid[Index] = codec_settings->seid;
#endif /* ENABLE_SOUNDBAR */
#ifdef ENABLE_SUBWOOFER
                /* set the sub woofer link type prior to passing to audio connect */
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
                theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
                
                /* bits inverted in dsp plugin */                
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
                /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
                sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

                AUD_DEBUG(("AudioA2dpRoute Index[%d] DevId[%x] Gain[%x] Codec[%x] ClkMismatch[%x] EQ[%x] packet_size[%u]\n", 
                           Index , 
                           theSink.a2dp_link_data->device_id[Index],
                           a2dp_gain_dB,
                           codec_settings->seid,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.clock_mismatch,
                           (uint16)theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params,
                           theSink.a2dp_link_data->a2dp_audio_connect_params.packet_size)) ;
                
                audioIndicateCodec( codec_settings->seid );

#ifdef ENABLE_SOUNDBAR
                /* Set the LE SCAN priority to Low since we are Streaming  It is possible 
                that we might be receiving less or no LE adverts when streaming is in progress*/
                InquirySetPriority(inquiry_low_priority);
#endif /*  ENABLE_SOUNDBAR */

                /* We need to set A2DP volume info as the audio is in mute state after connection */ 
				volumeInitAudio.volume_type = theSink.conf1->volume_config.volume_control_config.volume_type;
                volumeInitAudio.codec_task = theSink.codec_task;
        		volumeInitAudio.master_gain = a2dp_gain_dB;
                volumeInitAudio.system_gain = theSink.conf1->volume_config.volume_control_config.system_volume;
        		volumeInitAudio.trim_gain_left = theSink.conf1->volume_config.volume_control_config.trim_volume_left;
        		volumeInitAudio.trim_gain_right= theSink.conf1->volume_config.volume_control_config.trim_volume_right;	
                volumeInitAudio.device_trim_master = theSink.conf1->volume_config.volume_control_config.device_trim_master;
                volumeInitAudio.device_trim_slave = theSink.conf1->volume_config.volume_control_config.device_trim_slave;
          		volumeInitAudio.tones_gain = VolumeConvertStepsToDB(((TonesGetToneVolume(FALSE) * theSink.conf1->volume_config.volume_control_config.no_of_steps)/VOLUME_NUM_VOICE_STEPS), &theSink.conf1->volume_config.volume_control_config, DSP_DB_SCALE);
                volumeInitAudio.mute_active = theSink.sink_enable_present;
                
                /* connect the audio via the audio plugin */    
  			    AudioConnect(getA2dpPlugin(codec_settings->seid),
                             sink , 
                             AUDIO_SINK_AV ,
                             theSink.codec_task,
                             volumeInitAudio.tones_gain, 
                             codec_settings->rate,
                             theSink.conf2->audio_routing_data.PluginFeatures ,
                             mode,
                             AUDIO_ROUTE_INTERNAL,
                             powerManagerGetLBIPM(), 
                             &theSink.a2dp_link_data->a2dp_audio_connect_params,
                             FALSE,
                             &theSink.task);
               
				AudioSetVolumeA2DP(&volumeInitAudio);

#ifdef ENABLE_SUBWOOFER
                /* set subwoofer volume level */
                updateSwatVolume(theSink.volume_levels->a2dp_volume[Index].masterVolume);

                SWAT_DEBUG(("SW : Send sample rate to Sub, rate is %ld\n",codec_settings->rate));
                
                /* send sample rate to sub */
                sendSampleRateToSub(codec_settings->rate);                        
#endif
                
                audioControlLowPowerCodecs (FALSE) ;

                /* caller responsible for freeing memory */
                freePanic(codec_settings);
                
#ifdef ENABLE_AVRCP
                if(theSink.features.avrcp_enabled)
                {    
                    UpdateAvrpcMessage_t * lUpdateMessage = mallocPanic ( sizeof(UpdateAvrpcMessage_t) ) ;        
                    lUpdateMessage->bd_addr = theSink.a2dp_link_data->bd_addr[Index];                            
                    /* any AVRCP commands should be targeted to the device which has A2DP audio routed */ 
                    MessageSend( &theSink.task, EventSysSetActiveAvrcpConnection, lUpdateMessage);
                }
#endif            
        }
            
        /* update the current sink being routed */            
        theSink.routed_audio = sink;
    }
}
Example #10
0
/****************************************************************************
NAME    
    sinkFmRxAudioConnect
    
DESCRIPTION
    connects the I2S FM audio via the FM audio plugin which allows tones play
    and volume control
RETURNS
    nothing
*/   
void sinkFmRxAudioConnect(void)
{    
    AUDIO_PLUGIN_SET_VOLUME_A2DP_MSG_T volumeDsp;
    
    uint16 volume_dB = VolumeConvertStepsToDB(theSink.volume_levels->fm_volume.masterVolume, &theSink.conf1->volume_config.volume_control_config, DSP_DB_SCALE);
    uint16 mode   = (theSink.volume_levels->fm_volume.masterVolume == VOLUME_A2DP_MUTE_GAIN) ? AUDIO_MODE_MUTE_SPEAKER : AUDIO_MODE_CONNECTED;
 
    FM_DEBUG(("sinkFmRxAudioConnect \n"));

    theSink.volume_levels->fm_volume.tonesVolume = VolumeConvertStepsToDB(((TonesGetToneVolume(FALSE) * theSink.conf1->volume_config.volume_control_config.no_of_steps)/VOLUME_NUM_VOICE_STEPS), &theSink.conf1->volume_config.volume_control_config, DSP_DB_SCALE);
   
    /* Make sure we're using correct parameters for FM audio */
    theSink.a2dp_link_data->a2dp_audio_connect_params.mode_params = &theSink.a2dp_link_data->a2dp_audio_mode_params;

#ifdef ENABLE_SUBWOOFER
    /* set the sub woofer link type prior to passing to audio connect */
    theSink.a2dp_link_data->a2dp_audio_connect_params.sub_woofer_type  = AUDIO_SUB_WOOFER_NONE;  
    theSink.a2dp_link_data->a2dp_audio_connect_params.sub_sink  = NULL;  
    /* bits inverted in dsp plugin */                
    sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,TRUE);
#else
    /* no subwoofer support, set the sub woofer bypass bit in music config message sent o dsp */
    sinkAudioSetEnhancement(MUSIC_CONFIG_SUB_WOOFER_BYPASS,FALSE);
#endif          

    FM_DEBUG(("FM: Routing (Vol %d)\n", theSink.volume_levels->fm_volume.masterVolume));

    AudioConnect((TaskData *)&csr_fm_decoder_plugin,
                 theSink.routed_audio,
                 AUDIO_SINK_FM, 
                 theSink.codec_task, 
                 volume_dB, 
                 FM_RATE, 
                 theSink.conf2->audio_routing_data.PluginFeatures, 
                 mode,
                 AUDIO_ROUTE_INTERNAL,
                 powerManagerGetLBIPM(), 
                 &theSink.a2dp_link_data->a2dp_audio_connect_params, 
                 &theSink.task);
                
    audioControlLowPowerCodecs (FALSE) ;
    
    /* update volume via a2dp common plugin */
    volumeDsp.volume_type = theSink.conf1->volume_config.volume_control_config.volume_type;
    volumeDsp.codec_task = theSink.codec_task;
    volumeDsp.master_gain = volume_dB;
    volumeDsp.tones_gain =  theSink.volume_levels->fm_volume.tonesVolume;
    volumeDsp.system_gain = theSink.conf1->volume_config.volume_control_config.system_volume;
    volumeDsp.trim_gain_left = theSink.conf1->volume_config.volume_control_config.trim_volume_left;
    volumeDsp.trim_gain_right= theSink.conf1->volume_config.volume_control_config.trim_volume_right;
    volumeDsp.device_trim_master = theSink.conf1->volume_config.volume_control_config.device_trim_master;
    volumeDsp.device_trim_slave = theSink.conf1->volume_config.volume_control_config.device_trim_slave;
    volumeDsp.mute_active = theSink.sink_mute_status;

    AudioSetVolumeA2DP ( &volumeDsp);

#ifdef ENABLE_SUBWOOFER
    /* set subwoofer volume level */
    updateSwatVolume(volume_dB);
#endif    
    /* tune to stored frequency after initilising the I2S interface otherwise FM receiver
       may be in an unknown state which may not work reliably */
    fmRxTuneFrequency(theSink.conf2->sink_fm_data.fmRxTunedFreq);    
}
/****************************************************************************
NAME 
    a2dpStreamConnectA2dpAudio

DESCRIPTION
    To connnect the audio plugin for a2dp audio streaming;
 
*/
void a2dpStreamConnectA2dpAudio(Sink media_sink)
{
    uint16 i, counter = 0;
    Sink media_sink_arr[MAX_NUM_DEV_CONNECTIONS];
    
    DEBUG_A2DP(("a2dpStreamConnectA2dpAudio\n"));
    
    MessageCancelAll(&the_app->task, APP_CONNECT_A2DP_AUDIO);
    
    if (the_app->active_encoder == EncoderAv)
    {
        /* This indicates streaming is already active and now a second audio connection has
           to be routed. Use the AudioSetMode function to start the second audio stream. 
        */
        dualstream_mode_params *dual_mode = (dualstream_mode_params *)PanicUnlessMalloc(sizeof(dualstream_mode_params));
        dual_mode->connect_sink = TRUE; /* Indicate the audio is being connected */
        dual_mode->media_sink = media_sink; /* Supply the second media sink that is being connected */
        AudioSetMode(AUDIO_MODE_CONNECTED, (void*)dual_mode);

        DEBUG_A2DP(("AudioSetMode connect_sink:0x%x \n",(uint16)media_sink));
    }
    else
    {
        /* No audio is currently active, so route the audio for all active streams */
        for (i = 0; i < MAX_NUM_DEV_CONNECTIONS; i++)
        {
            if ((the_app->dev_inst[i] != NULL) && (the_app->dev_inst[i]->a2dp_state == A2dpStateStreaming))
            {
                DEBUG_A2DP(("*** streaming found i:%d a2dp:0x%x sink:0x%x ***\n",i,(uint16)the_app->dev_inst[i]->a2dp, (uint16)the_app->dev_inst[i]->a2dp_media_sink));
                media_sink_arr[counter++] = the_app->dev_inst[i]->a2dp_media_sink;
            }
        }
    
        /* Pass the second media sink as a parameter into the AudioConnect function that the audio plugin
           can recognise. 
        */
        if (counter > 1)
        {
            the_app->a2dp_data.codecData.media_sink_b = media_sink_arr[1];
        }
        else
        {
            the_app->a2dp_data.codecData.media_sink_b = 0;
        }
        
        /* Connect the audio plugin */
        AudioConnect(the_app->a2dp_audio_plugin , 
                 media_sink_arr[0] , 
                 AUDIO_SINK_AV ,
                 the_app->codecTask,
                 0x0a , 
                 the_app->a2dp_sample_rate ,  
                 (TRUE), 
                 AUDIO_MODE_CONNECTED, 
                 (source_codec_data_type *) &the_app->a2dp_data.codecData ) ;
        
        the_app->active_encoder = EncoderAv;
        
        DEBUG_A2DP(("AudioConnect devices:%d\n",counter));
    }
}
Example #12
0
/****************************************************************************
NAME    
    audio_a2dp_connect - Route A2DP audio
*/
void audio_a2dp_connect(Sink sink, uint16 device_id, uint16 stream_id)
{
    uint8 bitpool;
    uint8 bad_link_bitpool;
    bool multiple_streams;
    
    /* start audio active timer */
    audio_start_active_timer();
    
    /* remove any AGHFP audio */
    audio_aghfp_disconnect();
               
    AUDIO_DEBUG(("AUDIO: audio_a2dp_connect\n"));
    
    if (theSource->audio_data.audio_routed == AUDIO_ROUTED_NONE)
    {
    
        theSource->audio_data.audio_a2dp_connect_params.input_source = usb_get_speaker_source(); /* Set the USB Source, not used for Analogue */
        theSource->audio_data.audio_a2dp_connect_params.input_sink = usb_get_mic_sink(); /* Set the USB Sink, not used for Analogue */
        theSource->audio_data.audio_a2dp_connect_params.a2dp_sink[device_id] = sink; /* Set the A2DP media Sink */    
    
        AUDIO_DEBUG(("  audio_routed [%d] input_source [0x%x] input_sink [0x%x] a2dp_sink_0 [0x%x] a2dp_sink_1 [0x%x]\n", 
                     theSource->audio_data.audio_routed, 
                     (uint16)theSource->audio_data.audio_a2dp_connect_params.input_source,
                     (uint16)theSource->audio_data.audio_a2dp_connect_params.input_sink,
                     (uint16)theSource->audio_data.audio_a2dp_connect_params.a2dp_sink[0],
                     (uint16)theSource->audio_data.audio_a2dp_connect_params.a2dp_sink[1]));

        if (theSource->audio_data.audio_a2dp_connect_params.a2dp_sink[0] || theSource->audio_data.audio_a2dp_connect_params.a2dp_sink[1])
        {        
            AudioPluginFeatures features = {0,0,0}; /* no stereo or i2s output */
            a2dp_codec_settings *codec_settings = A2dpCodecGetSettings(device_id, stream_id);
                    
            if (codec_settings)
            {                            
                AUDIO_DEBUG(("  codec ; voice_rate[0x%lx] packet_size[0x%x] bitpool[0x%x] format[0x%x] CP[0x%x]\n",
                             codec_settings->codecData.voice_rate,
                             codec_settings->codecData.packet_size,
                             codec_settings->codecData.bitpool,
                             codec_settings->codecData.format,
                             codec_settings->codecData.content_protection
                             ));
                
                theSource->audio_data.audio_a2dp_connect_params.rate = codec_settings->codecData.voice_rate;
                theSource->audio_data.audio_a2dp_connect_params.packet_size = codec_settings->codecData.packet_size; 
                if (a2dp_get_sbc_bitpool(&bitpool, &bad_link_bitpool, &multiple_streams))
                {
                    theSource->audio_data.audio_a2dp_connect_params.bitpool = bitpool;    
                    theSource->audio_data.audio_a2dp_connect_params.bad_link_bitpool = bad_link_bitpool;
                }
                else
                {
                    theSource->audio_data.audio_a2dp_connect_params.bitpool = codec_settings->codecData.bitpool;
                }                
                theSource->audio_data.audio_a2dp_connect_params.format = codec_settings->codecData.format;                        
                theSource->audio_data.audio_a2dp_mode_params.eq_mode = theSource->volume_data.eq_index;
                theSource->audio_data.audio_a2dp_connect_params.mode = &theSource->audio_data.audio_a2dp_mode_params;
                /* turn on content protection if negotiated */
                theSource->audio_data.audio_a2dp_connect_params.content_protection = codec_settings->codecData.content_protection;

                /* remember if the remote device supports bidirectional audio, i.e. has a MIC back channel */
                theSource->audio_data.audio_remote_bidir_support = audio_is_bidir_supported(codec_settings) ? 1 : 0;
                                       
                theSource->audio_data.audio_routed = AUDIO_ROUTED_A2DP;
                                
                audio_a2dp_get_plugin();
                
                AudioConnect(audio_a2dp_get_plugin(),
                         0, 
        		     	 AUDIO_SINK_AV,
        		    	 theSource->codec,
        		    	 /*a2dp_gain*/10, 
                         codec_settings->rate,
        		    	 features, /* stereo supported, no i2s output */
        		     	 volume_get_mute_mode(),
                         AUDIO_ROUTE_INTERNAL,
        		    	 /*power*/0, 
                         &theSource->audio_data.audio_a2dp_connect_params,
                         &theSource->audioTask);   
                  
                /* free the codec_settings memory that the A2DP library allocated */
                memory_free(codec_settings);
            }
        }   
    }
    else if (theSource->audio_data.audio_routed == AUDIO_ROUTED_A2DP)
    {
        /* connecting additional A2DP device */
        theSource->audio_data.audio_a2dp_connect_params.a2dp_sink[device_id] = sink;
        theSource->audio_data.audio_a2dp_mode_params.connect_sink = sink;
        if (a2dp_get_sbc_bitpool(&bitpool, &bad_link_bitpool, &multiple_streams))
        {
            theSource->audio_data.audio_a2dp_mode_params.bitpool = bitpool;  
            theSource->audio_data.audio_a2dp_mode_params.bad_link_bitpool = bad_link_bitpool;
        }
        
        AUDIO_DEBUG(("  audio_routed [%d] connect_sink [0x%x] bitpool [%d] bad_link_bitpool [%d]\n",
                      theSource->audio_data.audio_routed,
                      (uint16)sink,
                      bitpool,
                      bad_link_bitpool));
         
        audio_update_mode_parameters();  
    }
}