Ejemplo n.º 1
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)
    {       
        /* 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;
    }
}
Ejemplo n.º 2
0
/****************************************************************************
NAME 
    usbGetVolume
    
DESCRIPTION
    Extract USB volume setting from USB lib levels
    
RETURNS
    Volume to pass to csr_usb_audio_plugin
*/ 
static uint16 usbGetVolume(AUDIO_MODE_T* mode)
{
    uint16 result;
    bool mic_muted;
    bool spk_muted = FALSE;

    /* Get vol settings from USB lib */
    usb_device_class_audio_levels levels;
    UsbDeviceClassGetValue(USB_DEVICE_CLASS_GET_VALUE_AUDIO_LEVELS, (uint16*)&levels);

    /* limit check volume levels returned */
    if((levels.out_l_vol < 0)||(levels.out_l_vol > VOLUME_A2DP_MAX_LEVEL))
        levels.out_l_vol = VOLUME_A2DP_MAX_LEVEL;
    if((levels.out_r_vol < 0)||(levels.out_r_vol > VOLUME_A2DP_MAX_LEVEL))
        levels.out_r_vol = VOLUME_A2DP_MAX_LEVEL;

    USB_DEBUG(("USB: Gain L %X R %X\n", levels.out_l_vol, levels.out_r_vol));
    USB_DEBUG(("USB: Mute M %X S %X\n", levels.in_mute, levels.out_mute));

    if(theSink.usb.config.plugin_type == usb_plugin_stereo)
    {
        /* Use A2DP gain mappings */
        uint8 l_vol = theSink.conf1->gVolMaps[ levels.out_l_vol ].A2dpGain;
        uint8 r_vol = theSink.conf1->gVolMaps[ levels.out_r_vol ].A2dpGain;
        /* Convert A2DP gain setting to mute/gain */
        spk_muted = (r_vol == 0 && l_vol == 0);
        if(r_vol > 0) r_vol --;
        if(l_vol > 0) l_vol --;
        /* Pack result */
        result = ((l_vol << 8) | r_vol);
        displayUpdateVolume((levels.out_l_vol + levels.out_r_vol + 1) / 2);
#ifdef ENABLE_SUBWOOFER
        updateSwatVolume((levels.out_l_vol + levels.out_r_vol + 1) / 2);
#endif
    }
    
    else
    {
        /* Use HFP gain mappings */
        result = theSink.conf1->gVolMaps[ levels.out_l_vol ].VolGain;
        displayUpdateVolume(levels.out_l_vol);
#ifdef ENABLE_SUBWOOFER
        updateSwatVolume(levels.out_l_vol);
#endif
    }

    /* Mute if muted by host or not supported */
    mic_muted = levels.in_mute  || !USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_AUDIO_MICROPHONE);
    spk_muted = spk_muted || levels.out_mute || !USB_CLASS_ENABLED(USB_DEVICE_CLASS_TYPE_AUDIO_SPEAKER);

    if(mode)
    {
        if(mic_muted && spk_muted)
            *mode = AUDIO_MODE_MUTE_BOTH;
        else if(mic_muted)
            *mode = AUDIO_MODE_MUTE_MIC;
        else if(spk_muted)
            *mode = AUDIO_MODE_MUTE_SPEAKER;
        else
            *mode = AUDIO_MODE_CONNECTED;
    }

    return result;
}
Ejemplo n.º 3
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);    
}