⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 headset_tones.c

📁 针对bluelab3.42的handsfree车载蓝牙的参考
💻 C
📖 第 1 页 / 共 2 页
字号:

/* Major Scale ring tone (default) */
static const audio_note tone_ring_default_delayed[] =
{
    AUDIO_TEMPO(300), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),

    AUDIO_NOTE(REST, SEMIBREVE),
    AUDIO_NOTE(REST, SEMIBREVE),
    AUDIO_NOTE(REST, SEMIBREVE),
    AUDIO_NOTE(E6,QUAVER),                                    
    AUDIO_NOTE(FS6,QUAVER),                                           
    AUDIO_NOTE(GS6,QUAVER),                           
    AUDIO_NOTE(A6,QUAVER),                            
    AUDIO_NOTE(B6,QUAVER),                                            
    AUDIO_NOTE(CS7,QUAVER),                           
    AUDIO_NOTE(DS7,QUAVER),                                           
    AUDIO_NOTE(E7,QUAVER),    

    AUDIO_END
};

/* Twilight ring tone */
static const audio_note tone_ring_twilight_delayed[] =
{
    AUDIO_TEMPO(180), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),
    
    AUDIO_NOTE(REST, SEMIBREVE),
    AUDIO_NOTE(REST, CROTCHET),
    AUDIO_NOTE(E7, QUAVER),
    AUDIO_NOTE(F7, QUAVER),
    AUDIO_NOTE(E7, QUAVER),
    AUDIO_NOTE(C7, QUAVER),
    AUDIO_NOTE(E7, QUAVER),
    AUDIO_NOTE(F7, QUAVER),
    AUDIO_NOTE(E7, QUAVER),
    AUDIO_NOTE(C7, QUAVER),

    AUDIO_END
};

static const audio_note tone_mute_reminder_delayed[] =
		
		
{
	AUDIO_TEMPO(400), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),
	
    AUDIO_TEMPO(600), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),
    AUDIO_NOTE(REST, SEMIQUAVER),
    AUDIO_TEMPO(120), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),
    AUDIO_NOTE(G5, CROTCHET),
    AUDIO_NOTE(REST, CROTCHET),
    AUDIO_NOTE(G5, CROTCHET),
    AUDIO_END
};

static const audio_note tone_call_end_delayed[] =
{
    AUDIO_TEMPO(120), AUDIO_VOLUME(64), AUDIO_TIMBRE(sine),
   	AUDIO_NOTE(REST, SEMIBREVE),
    AUDIO_NOTE(REST, SEMIQUAVER),
 	AUDIO_NOTE(FS7 , CROTCHET),
    
    AUDIO_END
};

/********************************************************************************
    The tones array
*********************************************************************************/

#define NUM_FIXED_TONES (12)
#define ABORT_TONE      (0)
#define ABORT_TIME      (4000)

static const audio_note * const gFixedTones [ (NUM_FIXED_TONES * 2) ] = 
{
    /* Immediate tones */
    tone_power_on,
    tone_power_off,
    tone_error,
    tone_button_press,
    tone_battery_low,
    tone_vol_limit,
    tone_connect,
	tone_mute_reminder,
    tone_pairing,
	tone_call_end,
    tone_ring_default,
    tone_ring_twilight,
	
    /* Delayed tones */
    tone_power_on_delayed,
    tone_power_off_delayed,
    tone_error_delayed,
    tone_button_press_delayed,
    tone_battery_low_delayed,
    tone_vol_limit_delayed,
    tone_connect_delayed,
	tone_mute_reminder_delayed,
    tone_pairing_delayed,
	tone_call_end_delayed,
    tone_ring_default_delayed,
    tone_ring_twilight_delayed
	
};


/****************************************************************************
NAME    
    TonesHandler
    
DESCRIPTION
  	Message handler - arrived at on completion of a tone playback - deletes any queued messages
    and attempts to reconnect the last used audio (av or sco), if it existed.
    
    
RETURNS
    void
*/
static void TonesHandler ( Task task, MessageId id, Message message )
{
    headsetTaskData *app = (headsetTaskData *) getAppTask() ;
    
    /* No need to abort tone playing now we have got to the end-of-tone handler */
    MessageCancelAll(&app->theSoundTask, ABORT_TONE);
    
    TONES_DEBUG(("TONE: Tones handler id:0x%x  pcm:0x%x\n",id,app->pcm_audio_state));
    
	if (app->headset_power_state == power_state_powering_down)
        /* If we are powering down, want to turn the amp off asap */
        MessageSendLater(getAppTask(), APP_AMP_IDLE_IND, 0, 0);
	else
        /* Start the timer to shut down the audio amp */
        MessageSendLater(getAppTask(), APP_AMP_IDLE_IND, 0, AMP_IDLE_TIMER);
	
    switch (app->pcm_audio_state)
    {
    case pcm_tone_to_av:
        /* Connect up AV to PCM, only if SLC is not happening or the headset is powering off*/
        setPcmState(app, pcm_av);
        if (!app->headset_connecting_hfp && app->media_sink && (app->hfp_state != headsetOutgoingCallEstablish) && 
			(app->headset_power_state != power_state_powering_down)&&!(app->voice.voice_recognition_enabled))
            avHeadsetAvStreamStart(app);
        break;

    case pcm_tone_to_sco:
        /* Connect up SCO to PCM and restore HF Volume */
        setPcmState(app, pcm_sco);
        if ((app->sco_sink) && (app->headset_power_state != power_state_powering_down))
            hfpSetupScoRouting(app);
        break;

    case pcm_tone:
        /* Restore HF Volume (which is the default if no AV in use) */
        setPcmState(app, pcm_none);
        headsetUpdateVolume(app->codec_task, app->speaker_volume.hfp_volume);
        break;

    case pcm_ringing:
        /* End of incoming ring */
        setPcmState(app, pcm_ring);
        break;

    case pcm_ring:
        break;
        
    case pcm_sco:
        /* Case where SCO is established while a ring is still playing. 
           Need to cancel the amp shut off timer. */
        MessageCancelAll(getAppTask(), APP_AMP_IDLE_IND);
        break;

    default:
        TONES_DEBUG(("TONE: Invalid pcm state!\n"));
        break;       
    }
    
    MessageFlushTask(&app->theSoundTask);
    
    if (app->amp.amp_powering_on)
        app->amp.amp_powering_on = 0;
}


/*****************************************************************************/
bool isTonePlaying(pcmAudioState state)
{
    return (state >= pcm_tone);
}

/*****************************************************************************/
bool isRingTone(pcmAudioState state)
{
    return ((state == pcm_ring) || (state == pcm_ringing));
}

/*****************************************************************************/
bool isRingOrTonePlaying(pcmAudioState state)
{
    return (state >= pcm_ringing);
}

/*****************************************************************************/
bool isRinging(pcmAudioState state)
{
    return (state == pcm_ringing);
}

/*****************************************************************************/
void tonesInit(headsetTaskData *app) 
{
    /*set up the callback message handler*/
    app->theSoundTask.handler = TonesHandler ; 
}

/*****************************************************************************/
void headsetPlayTone(headsetTaskData *app, toneType type_of_tone)
{
    Source stream_source;
    bool ring_success = FALSE;
    bool amp_inactive = FALSE;
    
    /* Tones can interrupt rings */
    if (!isRingOrTonePlaying(app->pcm_audio_state) || (isRinging(app->pcm_audio_state) && (type_of_tone != tone_type_ring)))               
    {
        TONES_DEBUG(("TONE: Play Tone type:0x%x  pcm:0x%x\n",type_of_tone,app->pcm_audio_state));

        if (!headsetIsAmpPowered(app))
        {
            amp_inactive = TRUE;   
            app->amp.amp_powering_on = 1;
            headsetPowerAmp(app, TRUE);
        }

        if (type_of_tone == tone_type_ring)
        {
            setPcmState(app, pcm_ringing);
            avHeadsetAvStreamStop(app,TRUE);
        }
        else
        {
            avHeadsetAvStreamStop(app,FALSE);
        }
        
        /* Cancel the timer to shut down the audio amp */
        MessageCancelAll(getAppTask(), APP_AMP_IDLE_IND);

        switch (app->pcm_audio_state)
        {
        case pcm_sco:   setPcmState(app, pcm_tone_to_sco); break;
        case pcm_av:    setPcmState(app, pcm_tone_to_av);  break;
        case pcm_ring:  if (type_of_tone != tone_type_ring) setPcmState(app, pcm_tone); break;
        case pcm_ringing:                                  break;
        default:        setPcmState(app, pcm_tone);        break;
        }
        
        /* Check if a tone is interrupting a ring */
        if (isRinging(app->pcm_audio_state) && (type_of_tone != tone_type_ring))
        {
            TONES_DEBUG(("TONE: Tone interrupted ring\n"));
            MessageFlushTask(&app->theSoundTask);
            setPcmState(app, pcm_tone);
        }         
       
#ifdef INCLUDE_CVC
        if (app->cvc.hfkdspready)
        {
            StreamDisconnect(0, StreamPcmSink(0));
        }
        else
        {
#endif

        /* Set volume to mute */
        headsetUpdateVolume(app->codec_task, 0);       
        /* Disconnect anything already connected to PCM slots 0 and 1 */   
        StreamDisconnect(StreamPcmSource(0), StreamPcmSink(0));
        StreamDisconnect(StreamPcmSource(1), StreamPcmSink(1));

        /*
            Reconfigure the DACs to output the ring to left and right
        */
		(void) PanicFalse(PcmClearRouting(0));
		(void) PanicFalse(PcmClearRouting(1));

#ifdef WOLFSON_CODEC
        (void) PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, 8000, 8000, VM_PCM_EXTERNAL_I2S));
        CodecConfigure(app->codec_task,0);
#else
	    (void) PanicFalse(PcmRateAndRoute(0, PCM_NO_SYNC, (uint32) 8000, (uint32) 8000, VM_PCM_INTERNAL_A_AND_B));
#endif
        
#ifdef INCLUDE_CVC
        }
#endif

        /* If a ring tone, then check features to get the required tune */
        if (type_of_tone == tone_type_ring)
            type_of_tone += app->features.ring_tone_select;
    
        /* If amp was turned off then play delayed tone, else play immediate tone */
        if (amp_inactive)
        {
            type_of_tone += NUM_FIXED_TONES;
            TONES_DEBUG(("TONE: Play delayed tone  type:%d\n",type_of_tone));
        }

        /* Set tone to required volume */
        headsetUpdateVolume(app->codec_task, 15);
        
	    stream_source = StreamAudioSource(gFixedTones[type_of_tone]);
 
        ring_success =  StreamConnectAndDispose(stream_source, StreamPcmSink(0));
    
        TONES_DEBUG(("TONE: Ring success %d\n",ring_success));
    
        /* send a message to indicate when the PCM connect disconnects */
        MessageSinkTask ( StreamPcmSink(0) , &app->theSoundTask )  ;
        /* The above line CAN fail so abort playing a tone after a certain time anyway,
           so that we don't get stuck in thinking a tone is playing.
        */
        MessageSendLater(&app->theSoundTask, ABORT_TONE, 0, ABORT_TIME);
    }
    else
    {
        TONES_DEBUG(("TONE: Tone already playing\n"));
        if (isTonePlaying(app->pcm_audio_state) && (type_of_tone != tone_type_ring))
        {
            if (app->amp.amp_powering_on)
            {
                APP_TONE_TO_PLAY_IND_T* message;
                TONES_DEBUG(("TONE: Play new tone once delayed tone played %d\n",type_of_tone));
                MessageCancelAll(getAppTask(), APP_TONE_TO_PLAY_IND);
	            message = malloc(sizeof(APP_TONE_TO_PLAY_IND_T));
	            message->id = type_of_tone;
                MessageSendConditionally(getAppTask(), APP_TONE_TO_PLAY_IND, message, &app->amp.amp_powering_on);
            }
            else
            {
                TONES_DEBUG(("TONE: Play new tone %d\n",type_of_tone));
                MessageFlushTask(&app->theSoundTask);
                MessageCancelAll(&app->theSoundTask, ABORT_TONE);
                StreamDisconnect(0, StreamPcmSink(0));
                stream_source = StreamAudioSource(gFixedTones[type_of_tone]);
                ring_success =  StreamConnectAndDispose(stream_source, StreamPcmSink(0));
                MessageSinkTask ( StreamPcmSink(0) , &app->theSoundTask );
                MessageSendLater(&app->theSoundTask, ABORT_TONE, 0, ABORT_TIME);
            }
        }
    }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -