📄 headset_tones.c
字号:
/* 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 + -