📄 am_hw_primitive_builder_tone.cc
字号:
(UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, // 220 (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, // 230 (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved, (UINT8*)Alert_Reserved,// Ringers (UINT8*)Silent, // 237 (UINT8*)Vibrate, // VIBE_DOT (UINT8*)Vibrate, // VIBE_DASH (UINT8*)Vibrate, // 240 VIBE_DOT_DOT (UINT8*)Vibrate, // VIBE_DOT_DASH (UINT8*)Vibrate, // VIBE_PULSE (UINT8*)Continental, (UINT8*)Classic, (UINT8*)Attention, (UINT8*)Siren, // 246}; /* This table expects note as x index, and octave as y index. * IMPORTANT! In the note definition, the order is yx, * but in the table below, the order is xy! * Note that MAX of x is 12 (notes VY and VN are not included), * and y is 6 (octaves 10 and 11 are not included). * This table returns phase value wanted by DSP. */const UINT16 am_hw_phase_table[13][7] ={ /* [ 0][0] [ 0][1] [ 0][2] [ 0][3] [ 0][4] [ 0][5] [ 0][6] *//* A */ {FREQ_OF_55, FREQ_OF_110, FREQ_OF_220, FREQ_OF_440, FREQ_OF_880, FREQ_OF_1760, FREQ_OF_3520}, /* [ 1][0] [ 1][1] [ 1][2] [ 1][3] [ 1][4] [ 1][5] [ 1][6] *//* A# */ {FREQ_OF_58, FREQ_OF_117, FREQ_OF_233, FREQ_OF_466, FREQ_OF_932, FREQ_OF_1865, FREQ_OF_3729}, /* [ 2][0] [ 2][1] [ 2][2] [ 2][3] [ 2][4] [ 2][5] [ 2][6] *//* B */ {FREQ_OF_62, FREQ_OF_123, FREQ_OF_247, FREQ_OF_494, FREQ_OF_988, FREQ_OF_1976, FREQ_OF_3951}, /* [ 3][0] [ 3][1] [ 3][2] [ 3][3] [ 3][4] [ 3][5] [ 3][6] *//* C */ {FREQ_OF_33, FREQ_OF_65, FREQ_OF_131, FREQ_OF_262, FREQ_OF_523, FREQ_OF_1047, FREQ_OF_2093}, /* [ 4][0] [ 4][1] [ 4][2] [ 4][3] [ 4][4] [ 4][5] [ 4][6] *//* C# */ {FREQ_OF_35, FREQ_OF_69, FREQ_OF_139, FREQ_OF_277, FREQ_OF_554, FREQ_OF_1109, FREQ_OF_2217}, /* [ 5][0] [ 5][1] [ 5][2] [ 5][3] [ 5][4] [ 5][5] [ 5][6] *//* D */ {FREQ_OF_37, FREQ_OF_73, FREQ_OF_147, FREQ_OF_294, FREQ_OF_587, FREQ_OF_1175, FREQ_OF_2349}, /* [ 6][0] [ 6][1] [ 6][2] [ 6][3] [ 6][4] [ 6][5] [ 6][6] *//* D# */ {FREQ_OF_39, FREQ_OF_78, FREQ_OF_156, FREQ_OF_311, FREQ_OF_622, FREQ_OF_1245, FREQ_OF_2489}, /* [ 7][0] [ 7][1] [ 7][2] [ 7][3] [ 7][4] [ 7][5] [ 7][6] *//* E */ {FREQ_OF_41, FREQ_OF_82, FREQ_OF_165, FREQ_OF_330, FREQ_OF_659, FREQ_OF_1319, FREQ_OF_2637}, /* [ 8][0] [ 8][1] [ 8][2] [ 8][3] [ 8][4] [ 8][5] [ 8][6] *//* F */ {FREQ_OF_44, FREQ_OF_87, FREQ_OF_175, FREQ_OF_349, FREQ_OF_698, FREQ_OF_1397, FREQ_OF_2794}, /* [ 9][0] [ 9][1] [ 9][2] [ 9][3] [ 9][4] [ 9][5] [ 9][6] *//* F# */ {FREQ_OF_46, FREQ_OF_92, FREQ_OF_185, FREQ_OF_370, FREQ_OF_740, FREQ_OF_1480, FREQ_OF_2960}, /* [ A][0] [ A][1] [ A][2] [ A][3] [ A][4] [ A][5] [ A][6] *//* G */ {FREQ_OF_49, FREQ_OF_98, FREQ_OF_196, FREQ_OF_392, FREQ_OF_784, FREQ_OF_1568, FREQ_OF_3136}, /* [ B][0] [ B][1] [ B][2] [ B][3] [ B][4] [ B][5] [ B][6] *//* G# */ {FREQ_OF_52, FREQ_OF_104, FREQ_OF_208, FREQ_OF_415, FREQ_OF_831, FREQ_OF_1661, FREQ_OF_3322}, /* [ C][0] [ C][1] [ C][2] [ C][3] [ C][4] [ C][5] [ C][6] *//* R */ {FREQ_OF_0, FREQ_OF_0, FREQ_OF_0, FREQ_OF_0, FREQ_OF_0, FREQ_OF_0, FREQ_OF_0 }};/************** LOCAL FUNCTION PROTOTYPES *************************************//************** LOCAL MACROS **************************************************//************** LOCAL VARIABLES ***********************************************//************** FUNCTION DEFINITIONS ******************************************//* DESCRIPTION: This is a global c function to get the tone durations in the above tone table. This function has to reside in the same file as the data, since the data is static. INPUTS: id: the tone type. OUTPUTS: duration. IMPORTANT NOTES: None.*/extern "C"{UINT32 am_get_tone_duration(DL_AUDIO_TONE_TYPE_T id){ TD_AUD_TONE_UNION_T tone_union = {id}; UINT8* beginning_ptr = NULL; UINT16 numb_notes; UINT16 tempo; UINT32 duration = 0; UINT16 i; // Need to find the beginning point of the sound def data for later use. if (tone_union.fields.id < DL_AUDIO_TONE_TYPE_ALERT_PRESET_LIMIT) { beginning_ptr = (UINT8*)((AM_HW_SOUND_TONE_DEF*)am_hw_sound_table[tone_union.fields.id])->line_def + 2; numb_notes = ((AM_HW_SOUND_TONE_DEF*)am_hw_sound_table[tone_union.fields.id])->line_len; tempo = ((AM_HW_SOUND_TONE_DEF*)am_hw_sound_table[tone_union.fields.id])->tempo; } else if (tone_union.fields.id < DL_AUDIO_TONE_TYPE_ALERT_CUSTOM_LIMIT || tone_union.fields.id == DL_AUDIO_TONE_TYPE_CUSTOM_SAMPLE) { TUNE_REQUEST custom_tune_request = am_custom_tune_get_request_info(); // there is only duration when data in the buffer is valid if (custom_tune_request.req_type == AUD_TONE_START) { TUNE_META custom_tune_meta = am_custom_tune_get_meta_info(); beginning_ptr = custom_tune_meta.tune_ptr + 1; numb_notes = custom_tune_meta.note_numb; tempo = custom_tune_meta.tempo; } } if (beginning_ptr != NULL) { for (i = 0; i < numb_notes; i++) { duration += *beginning_ptr; beginning_ptr += 2; } // >> 3 is to convert the duration fro 125us unit to ms. duration = ((UINT32)AM_MUSIC_calc_DURATION(tempo, duration)) >> 3; } return duration;}}/* DESCRIPTION: This function checks whether the given tone is a tone to be played by DSP. INPUTS: tone: the tone to be checked. OUTPUTS: TRUE / FLASE. IMPORTANT NOTES: None.*/AM_HW_TONE_CATEGORYAM_HW_Primitive_Builder :: determine_tone (TD_AUD_TONE_REQ_TONE_TYPE_T tone_type, UINT8 dsp_seq){ TD_AUD_TONE_UNION_T tone = {tone_type}; AM_HW_TONE_CATEGORY category = AM_HW_NONE_TONE; if (tone.fields.media == 0) { if (dsp_seq == am_hw_current_info_ptr->dsp_seq && tone.fields.rerun != 1) { category = AM_HW_IDENTICAL_TONE; } else if (isVibAlert(tone.fields.id)) { category = AM_HW_PRESET_VIBRATE_TONE; } else if (tone.fields.id == DL_AUDIO_TONE_TYPE_CUSTOM_SAMPLE || ((isMediaTone(tone.fields.id) && (tone.fields.media == 0)))) { category = AM_HW_CUSTOMIZED_TUNE; } else if (tone.fields.id < DL_AUDIO_TONE_TYPE_ALERT_SOUND_LIMIT) { category = AM_HW_PRESET_AUDIBLE_TONE; } } return (category);}/* DESCRIPTION: This function updates the tone type. INPUTS: tone: requested tone type. mode: audio mode mask OUTPUTS: None. IMPORTANT NOTES: If a sound def is longer than the MDI buffer length, it has to be send by multiple messages. This applies only to preset sounds, since customized is always only one note long.*/voidAM_HW_Primitive_Builder :: ctg_start_tone (TD_AUD_TONE_UNION_T tone, INT16 ctg_gain, UINT8 dsp_seq, BOOL monophonic, UINT8 tone_insertion_method){ UINT8 current_set_length_changed = 0; UINT8* tmp_ptr = NULL; BOOL ctg_gain_applies = FALSE; switch (determine_tone(tone.type, dsp_seq)) { #if (AUDIO_GSM == TRUE ) case AM_HW_OPERATOR_RING_TONE: #endif case AM_HW_CUSTOMIZED_TUNE: { TUNE_META custom_tune_meta = am_custom_tune_get_meta_info(); /* customizable tone data */ AM_HW_SOUND_DATA tmp_data = {custom_tune_meta.tempo, custom_tune_meta.note_numb, 1, 0, 255, 1, custom_tune_meta.tune_ptr - 1}; sound_data = tmp_data; if (sound_data.header.line_len > 0) { ctg_gain_applies = TRUE; } else { ctg_gain_applies = FALSE; sound_data.def_data = NULL; aud_am_reply(tone.type, dsp_seq); } } break; case AM_HW_PRESET_AUDIBLE_TONE: /* read the sound definition data */ sound_data.header = ((AM_HW_SOUND_DATA*)am_hw_sound_table[tone.fields.id])->header; sound_data.def_data = (UINT8*)((AM_HW_SOUND_TONE_DEF*)am_hw_sound_table[tone.fields.id])->line_def; ctg_gain_applies = TRUE; break; case AM_HW_IDENTICAL_TONE: { AM_HW_SOUND_DATA tmp_data = {0, 0, 0, 0, 0, 0, NULL}; sound_data = tmp_data; ctg_gain_applies = TRUE; } break; default: { AM_HW_SOUND_DATA tmp_data = {0, 0, 0, 0, 0, 0, NULL}; sound_data = tmp_data; } } if (sound_data.def_data) { // If defined in the old format if (sound_data.header.tempo == OLD_TONE) { sound_data.header.line_numb = AM_HW_TONE_DEF_GET_CF(*(sound_data.def_data)); sound_data.header.line_len = (AM_HW_TONE_DEF_GET_NZF(*(sound_data.def_data)) - 1) / sound_data.header.line_numb + 1; sound_data.header.repetition = tone.fields.one_shot ? 1 : *(sound_data.def_data + 1); sound_data.header.volume = 1; current_set_length = sound_data.header.line_len; current_set_length_changed = current_set_length; /* Never need to rerun an old tone */ tone.fields.rerun = 0; } else { if (monophonic) { sound_data.header.line_numb = 1; } // This is a one shot tone if (tone.fields.one_shot == 1) { sound_data.header.repetition = 1; } /* This makes the first send nothing special from others */ if (dsp_seq != am_hw_current_info_ptr->dsp_seq || intermediate_ptr == NULL) { /* Align intermediate_ptr at the beginning of the data buffer */ intermediate_ptr = sound_data.def_data + 1; tone.fields.rerun = 1; } // if (intermediate_ptr == sound_data.def_data + 1)// { /* Calculate the number of notes in a line that one */ /* message can send with so many lines in this message */ /* This is due to the limited length of MCU_DSP_AUDIO_TONE_GEN_ON message */ /* Refer to ctg_mdi spec for the below equation */ current_set_length = (2 * (MCU_DSP_AUDIO_TONE_GEN_ON_WORD_LEN - AM_HW_MSG_HEADER_WORD_LEN) - 9) / (sound_data.header.line_numb * 2 + 5); /* This is due to the max number of frequencies one CTG MDI */ /* MCU_DSP_AUDIO_TONE_GEN_ON message takes */ UINT8 tmp_len = MAX_FREQ_A_MSG / sound_data.header.line_numb; if (current_set_length > tmp_len) { current_set_length = tmp_len; } current_set_length_changed = current_set_length;// } /* This is the number of notes in a line that have not been sent to DSP. */ UINT8 left_length = sound_data.header.line_len - (intermediate_ptr - sound_data.def_data - 1) / (sizeof(AM_HW_SOUND_NOTE_DEF) + sizeof(AM_HW_SOUND_DUR_DEF)); /* This is where the data of this send starts. We are now free */ /* to move intermediate_ptr to point to the end of this send */ tmp_ptr = intermediate_ptr; /* The case that this sound is going to terminate by this send, */ /* which is: "last send of a non-repetitive tone, */ /* or the only send of a short tone (once and for all)" */ if ((current_set_length >= left_length) && ((dsp_seq != am_hw_current_info_ptr->dsp_seq) || (sound_data.header.repetition == 1))) { /* restore intermediate_ptr when finishing a sound */ intermediate_ptr = NULL; /* adjust the set_len */ current_set_length = left_length; current_set_length_changed = current_set_length; /* restore the tone id */ tone.fields.rerun = 0; } /* The case that this sound is not going to terminate by this send,*/ /* which is: "last send of a repetitive tone, or not last send at all" */ /* This is just the complementary to the above case */ else { /* We can never let this guy to be sent to DSP as 0 in this case */ sound_data.header.repetition = 1; /* When it is the last send, again */ if (current_set_length >= left_length) { /* Align intermediate_ptr to the beginning of the sound definition data buffer */ intermediate_ptr = sound_data.def_data + 1; /* adjust the set_len */ current_set_length = left_length; current_set_length_changed = current_set_length; } else { intermediate_ptr += current_set_length * (sizeof(AM_HW_SOUND_NOTE_DEF) + sizeof(AM_HW_SOUND_DUR_DEF)); } } } sound_data.header.set_len = current_set_length; } // Whenever there is a ctg_gain change, send it to DSP if (ctg_gain_applies && ((ctg_gain != am_hw_current_info_ptr->ctg_gain) || current_set_length_changed)) { /* Build and send the CTG gains to the DSP before sending the frequency data.*/ set_ctg_gain (ctg_gain, monophonic, FALSE); if ((tone_insertion_method) & AM_ANALOG_DTMF_TX_MASK) { /* TX DTMF will generate tone contol, ctg gain, then tone control again to DSP, the gain for uplink is read from AM's copy of factory. NOTE: the AM_DOWNLINK_TONE_REPLACE_MASK must be unmasked in tone_insertion_method because the gains to be sent following this message is for uplink only */ update_tone_control(to
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -