1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006 |
- /*================================================================
- Copyright (c) 2020 Quectel Wireless Solution, Co., Ltd. All Rights Reserved.
- Quectel Wireless Solution Proprietary and Confidential.
- =================================================================*/
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #include "ql_api_osi.h"
- #include "ql_log.h"
- #include "audio_demo.h"
- #include "ql_osi_def.h"
- #include "ql_audio.h"
- #include "ql_fs.h"
- #include "ql_i2c.h"
- #include "quec_pin_index.h"
- #include "ql_gpio.h"
- #define QL_AUDIO_LOG_LEVEL QL_LOG_LEVEL_INFO
- #define QL_AUDIO_LOG(msg, ...) QL_LOG(QL_AUDIO_LOG_LEVEL, "ql_audio", msg, ##__VA_ARGS__)
- #define QL_AUDIO_LOG_PUSH(msg, ...) QL_LOG_PUSH("ql_AUDIO", msg, ##__VA_ARGS__)
- #if !defined(audio_demo_no_err)
- #define audio_demo_no_err(x, action, str) \
- do \
- { \
- if(x != 0) \
- { \
- QL_AUDIO_LOG(str); \
- {action;} \
- } \
- } while( 1==0 )
- #endif
- /* for headset_det */
- #ifdef QL_APP_FEATURE_HEADSET_DET
- #define QL_HEADSET_DETECT_PIN QUEC_PIN_DNAME_GPIO_8
- #define QL_HEADSET_DETECT_GPIO QUEC_GPIO_DNAME_GPIO_8
- #define QL_HEADSET_DETECT_FUNC_GPIO 0
- #define QL_HEADSET_DETECT_DEBOUNCE_TIME 300 //unit: ms
- #define DEMO_HEADSET_DETECT_PLUG_IN 1
- #define DEMO_HEADSET_DETECT_PLUG_OUT 0
- ql_task_t headset_det_task = NULL;
- ql_timer_t headset_det_debounce_timer = NULL;
- #endif
- #define ID_RIFF 0x46464952
- #define ID_WAVE 0x45564157
- #define ID_FMT 0x20746d66
- #define FORMAT_PCM 1
- #define CHECK_AUDIO_CORRECT 0
- #define CHECK_AUDIO_INVALID_PARAMETER 1
- #define CHECK_AUDIO_WAV_ERR 2
- #define CHECK_AUDIO_MP3_ERR 3
- #define CHECK_AUDIO_AMR_ERR 4
- struct wav_header{
- unsigned int riff_id;
- unsigned int riff_sz;
- unsigned int riff_fmt;
- unsigned int fmt_id;
- unsigned int fmt_sz;
- unsigned short audio_format;
- unsigned short num_channels;
- unsigned int sample_rate;
- unsigned int byte_rate;
- unsigned short block_align;
- unsigned short bits_per_sample;
- unsigned int data_id;
- unsigned int data_sz;
- };
- typedef struct
- {
- PCM_HANDLE_T recorder;
- PCM_HANDLE_T player;
- }ql_demo_poc_t;
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- static uint8 *pcm_buffer = NULL;
- static uint pcm_data_size = 0;
- #endif
- static bool ring_tone_start = 0;
- ql_task_t ql_play_task = NULL;
- static int play_callback(char *p_data, int len, enum_aud_player_state state)
- {
- if(state == AUD_PLAYER_START)
- {
- QL_AUDIO_LOG("player start run");
- }
- else if(state == AUD_PLAYER_FINISHED)
- {
- QL_AUDIO_LOG("player stop run");
- }
- else
- {
- QL_AUDIO_LOG("type is %d", state);
- }
- return QL_AUDIO_SUCCESS;
- }
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- static int record_callback(char *p_data, int len, enum_aud_record_state state)
- {
- if(state == AUD_RECORD_START)
- {
- QL_AUDIO_LOG("recorder start run");
- }
- else if(state == AUD_RECORD_CLOSE)
- {
- QL_AUDIO_LOG("recorder stop run");
- }
- else if(state == AUD_RECORD_CALL_INT)
- {
- QL_AUDIO_LOG("recorder int from ring/call");
- }
- else if(state == AUD_RECORD_DATA)
- {
- if(len <= 0)
- return -1;
- if(pcm_data_size > RECORD_BUFFER_MAX){
- return -1;
- }
- else{
- memcpy(pcm_buffer+pcm_data_size, p_data, len);
- pcm_data_size += len;
- }
- }
- return QL_AUDIO_SUCCESS;
- }
- #endif
- static void ql_audio_demo_thread(void *param)
- {
- QL_AUDIO_LOG("enter audio demo");
-
- //ql_ext_codec_cb_init(); //用户使用外置codec或外置DAC播放时,可参考此demo
- //test_pcm();
- //test_mp3();
- //test_wav();
- //test_amr();
- //test_amr_stream();
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- //test_record_file();
- //test_record_stream();
- //test_poc_full_duplex();
- //test_poc_half_duplex();
- #endif
- QL_AUDIO_LOG("test done, exit audio demo");
- ql_rtos_task_delete(NULL);
- }
- static int check_wav_file(QFILE fd)
- {
- int ret = 0;
- struct wav_header hdr;
- ret = ql_fseek(fd, 0, SEEK_SET);
- if(ret < 0)
- {
- return -1;
- }
- ret = ql_fread(&hdr, sizeof(hdr), 1, fd);
- if(ret < sizeof(hdr))
- {
- ql_fseek(fd, 0, SEEK_SET);
- return -1;
- }
- if( (hdr.riff_id != ID_RIFF) || (hdr.riff_fmt != ID_WAVE)
- || (hdr.fmt_id != ID_FMT) )
- {
- return -1;
- }
- if(hdr.audio_format != FORMAT_PCM)
- {
- return -1;
- }
- return 0;
- }
- static int check_mp3_file(QFILE fd)
- {
- int64 ret = 0;
- char head[10] = {0};
- ret = ql_fseek(fd, 0, SEEK_SET);
- if(ret < 0)
- {
- return -1;
- }
- ret = ql_fread(head, sizeof(head), 1, fd);
- if(ret < sizeof(head))
- {
- ql_fseek(fd, 0, SEEK_SET);
- return -1;
- }
- if(strncmp(head, "ID3", 3) == 0)
- {
- return 0;
- }
- else if( (head[0] == 0xFF) && (head[1] & 0xF0) == 0xF0 )
- {
- return 0;
- }
- return 1;
- }
- static int check_amr_file(QFILE fd)
- {
- return 0;
- }
- //Whether the audio format is correct?
- int check_audio_format(char *fname)
- {
- int err = CHECK_AUDIO_CORRECT;
- if (fname == NULL)
- return CHECK_AUDIO_INVALID_PARAMETER;
- char *dot = strrchr(fname, '.');
- if (dot == NULL)
- return CHECK_AUDIO_INVALID_PARAMETER;
- QFILE fd = ql_fopen(fname, "r");
- if(fd<0)
- {
- return CHECK_AUDIO_INVALID_PARAMETER;
- }
-
- if(!check_wav_file(fd))
- {
- if (strcasecmp(dot, ".wav") != 0)
- {
- err = CHECK_AUDIO_WAV_ERR;
- }
- }
- else if(!check_mp3_file(fd))
- {
- if (strcasecmp(dot, ".mp3") != 0)
- {
- err = CHECK_AUDIO_MP3_ERR;
- }
- }
- else if(!check_amr_file(fd))
- {
- if (strcasecmp(dot, ".amr") != 0)
- {
- err = CHECK_AUDIO_AMR_ERR;
- }
- }
-
- ql_fclose(fd);
- return err;
- }
- static void ql_audio_play_thread(void *ctx)
- {
- int err = 0;
- ql_event_t event = {0};
- while(1)
- {
- err = ql_event_try_wait(&event);
- audio_demo_no_err(err, continue, "wait event failed");
-
- switch(event.id)
- {
- case QL_AUDIO_RINGTONE_PLAY:
- do
- {
- err = ql_aud_play_file_start("ring_tone.mp3", QL_AUDIO_PLAY_TYPE_LOCAL, NULL);
- if(err)
- {
- ring_tone_start = FALSE;
- break;
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- }while(ring_tone_start);
- break;
- }
- }
- }
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- void test_poc_full_duplex(void)
- {
- QL_PCM_CONFIG_T config = {0};
- int err = 0, cnt_read=0, cnt_write;
- char *buffer = NULL;
- static ql_demo_poc_t *demo_poc = NULL;
- config.channels = 1; //单声道
- config.samplerate = 16000;
- ql_set_audio_path_earphone();
- ql_aud_set_volume(QL_AUDIO_PLAY_TYPE_VOICE, AUDIOHAL_SPK_VOL_6); //POC mode use the param of voice call
-
- buffer = calloc(1, 1024);
- audio_demo_no_err(!buffer, return, "no memory");
- demo_poc = calloc(1, sizeof(ql_demo_poc_t));
- audio_demo_no_err(!demo_poc, return, "no memory");
- demo_poc->recorder = ql_aud_pcm_open(&config, QL_AUDIO_FORMAT_PCM, QL_PCM_BLOCK_FLAG|QL_PCM_READ_FLAG, QL_PCM_POC);
- audio_demo_no_err(!demo_poc->recorder, goto exit, "player created failed");
- demo_poc->player = ql_aud_pcm_open(&config, QL_AUDIO_FORMAT_PCM, QL_PCM_BLOCK_FLAG|QL_PCM_WRITE_FLAG, QL_PCM_POC);
- audio_demo_no_err(!demo_poc->player, goto exit, "player created failed");
- err = ql_aud_start_poc_mode(QL_POC_TYPE_FULL_DUPLEX);
- audio_demo_no_err(err, goto exit, "player created failed");
- while(1)
- {
- memset(buffer, 0, 1024);
-
- cnt_read = ql_pcm_read(demo_poc->recorder, buffer, 640);
- audio_demo_no_err((cnt_read<=0), goto exit, "read data failed");
- cnt_write = ql_pcm_write(demo_poc->player, buffer, cnt_read);
- audio_demo_no_err((cnt_write!=cnt_read), goto exit, "read data failed");
- }
- exit:
- if(buffer)
- {
- free(buffer);
- }
- ql_aud_stop_poc_mode(); //users must call "ql_aud_stop_poc_mode" then call "ql_pcm_close", otherwise may leed to some errors
- if(demo_poc)
- {
- if(demo_poc->player)
- {
- ql_pcm_close(demo_poc->player);
- }
-
- if(demo_poc->recorder)
- {
- ql_pcm_close(demo_poc->recorder);
- }
-
- free(demo_poc);
- }
- }
- void test_poc_half_duplex(void)
- {
- PCM_HANDLE_T recorder = NULL;
- PCM_HANDLE_T player = NULL;
- QL_PCM_CONFIG_T config;
- void *data = NULL;
- int size, total_size = 0, cnt=0, write_cnt=0;
- config.channels = 1; //单声道
- config.samplerate = 16000;
- config.amrwb_param.amrwb_mode = AMRWB_MODE_2385;
- data = calloc(1, 200*1024);
- if(data == NULL)
- {
- goto exit;
- }
- ql_set_audio_path_earphone();
- ql_aud_set_volume(QL_AUDIO_PLAY_TYPE_VOICE, AUDIOHAL_SPK_VOL_6); //POC mode use the param of voice call
- recorder = ql_aud_pcm_open(&config, QL_AUDIO_FORMAT_PCM, QL_PCM_BLOCK_FLAG|QL_PCM_READ_FLAG, QL_PCM_POC);
- audio_demo_no_err(!recorder, goto exit, "recorder created failed");
- player = ql_aud_pcm_open(&config, QL_AUDIO_FORMAT_PCM, QL_PCM_BLOCK_FLAG|QL_PCM_WRITE_FLAG, QL_PCM_POC);
- audio_demo_no_err(!player, goto exit, "player created failed");
-
- int err = ql_aud_start_poc_mode(QL_POC_TYPE_HALF_DUPLEX);
- audio_demo_no_err(err, goto exit, "poc mode start failed");
- err = ql_aud_poc_switch(QL_POC_MODE_REC);
- audio_demo_no_err(err, goto exit, "poc mode switch failed");
- //start record
- while(total_size < 200*1024)
- {
- size = ql_pcm_read(recorder, data+total_size, 1024);
- if(size <= 0)
- {
- break;
- }
-
- total_size += size;
- }
- err = ql_aud_poc_switch(QL_POC_MODE_PLAY);
- audio_demo_no_err(err, goto exit, "poc mode switch failed");
- while(write_cnt < total_size)
- {
- if(total_size - write_cnt > PACKET_WRITE_MAX_SIZE) //单次最多可写入 PACKET_WRITE_MAX_SIZE 字节
- {
- cnt = ql_pcm_write(player, data+write_cnt, PACKET_WRITE_MAX_SIZE);
- }
- else
- {
- cnt = ql_pcm_write(player, data+write_cnt, total_size - write_cnt);
- }
- if(cnt <= 0)
- {
- QL_AUDIO_LOG("write failed");
- goto exit;
- }
- write_cnt += cnt;
- }
- while(ql_pcm_buffer_used(player)) //in poc mode, player will not stop if not ql_aud_stop_poc_mode called
- {
- ql_rtos_task_sleep_ms(20); //wait the write buffer empty
- }
- ql_rtos_task_sleep_ms(200);
-
- exit:
- ql_aud_stop_poc_mode(); //users must call "ql_aud_stop_poc_mode" then call "ql_pcm_close", otherwise may leed to some errors
- ql_pcm_close(recorder);
- ql_pcm_close(player);
-
- if(data)
- {
- free(data);
- }
- QL_AUDIO_LOG("test done");
- }
- #endif
- void ql_audio_app_init(void)
- {
- QlOSStatus err = QL_OSI_SUCCESS;
- ql_task_t ql_audio_task = NULL;
-
- QL_AUDIO_LOG("audio demo enter");
-
- err = ql_rtos_task_create(&ql_audio_task, 4096*2, APP_PRIORITY_NORMAL, "ql_audio", ql_audio_demo_thread, NULL, 5);
- if(err != QL_OSI_SUCCESS)
- {
- QL_AUDIO_LOG("audio task create failed");
- }
- err = ql_rtos_task_create(&ql_play_task, 4096, APP_PRIORITY_NORMAL, "ql_audio", ql_audio_play_thread, NULL, 2);
- if(err != QL_OSI_SUCCESS)
- {
- QL_AUDIO_LOG("audio task create failed");
- }
- }
- void test_amr_stream(void)
- {
- PCM_HANDLE_T PCM = NULL;
- QL_PCM_CONFIG_T config;
- void *data = NULL;
- int total_size = 0, cnt=0, write_cnt=0;
- config.channels = 1; //单声道
- config.samplerate = 16000;
- config.amrwb_param.amrwb_mode = AMRWB_MODE_2385;
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- int size=0;
- PCM = ql_aud_pcm_open(&config, QL_AUDIO_FORMAT_AMRWB, QL_PCM_BLOCK_FLAG|QL_PCM_READ_FLAG, QL_PCM_LOCAL);
- if(PCM == NULL)
- {
- QL_AUDIO_LOG("open pcm failed");
- goto exit;
- }
- data = malloc(100*1024);
- if(data == NULL)
- {
- goto exit;
- }
- QL_AUDIO_LOG("start read");
- //start record
- while(total_size < 10*1024)
- {
- size = ql_pcm_read(PCM, data+total_size, 41);
- if(size <= 0)
- {
- break;
- }
-
- total_size += size;
- }
- QL_AUDIO_LOG("exit record");
- if(total_size <= 0)
- {
- QL_AUDIO_LOG("read pcm failed");
- goto exit;
- }
- QL_AUDIO_LOG("size is %d", total_size);
- if(ql_pcm_close(PCM) != 0)
- {
- QL_AUDIO_LOG("close pcm failed");
- goto exit;
- }
- PCM = NULL;
- #endif
- PCM = ql_aud_pcm_open(&config, QL_AUDIO_FORMAT_AMRWB, QL_PCM_BLOCK_FLAG|QL_PCM_WRITE_FLAG, QL_PCM_LOCAL);
- if(PCM == NULL)
- {
- QL_AUDIO_LOG("open pcm failed");
- goto exit;
- }
- while(write_cnt < total_size)
- {
- if(total_size - write_cnt > PACKET_WRITE_MAX_SIZE) //单次最多可写 PACKET_WRITE_MAX_SIZE 字节
- {
- cnt = ql_pcm_write(PCM, data+write_cnt, PACKET_WRITE_MAX_SIZE);
- }
- else
- {
- cnt = ql_pcm_write(PCM, data+write_cnt, total_size - write_cnt);
- }
- if(cnt <= 0)
- {
- QL_AUDIO_LOG("write failed");
- goto exit;
- }
- write_cnt += cnt;
- }
- ql_aud_data_done();
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
-
- QL_AUDIO_LOG("play finish");
- exit:
- if(PCM != NULL)
- {
- ql_pcm_close(PCM);
- }
- if(data != NULL)
- {
- free(data);
- data = NULL;
- }
- }
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- void test_record_stream(void)
- {
- ql_aud_config config = {0};
- int cnt = 0, total_cnt=0, err;
- config.amrwb_param.amrwb_mode = AMRWB_MODE_2385;
-
- pcm_buffer = malloc(RECORD_BUFFER_MAX);
- if(!pcm_buffer){
- return;
- }
-
- /* 录音 */
- if(ql_aud_record_stream_start_ex(&config, QL_REC_TYPE_MIC, QL_AUDIO_FORMAT_AMRWB, record_callback))
- {
- QL_AUDIO_LOG("record fail");
- goto exit;
- }
-
- ql_rtos_task_sleep_s(5); //record 5s
- ql_aud_record_stop();
- if(pcm_data_size <= 0){
- QL_AUDIO_LOG("data invalid");
- goto exit;
- }
- /* 读取录音文件用于播放,此处也可调用 ql_aud_play_file_start,或者ql_pcm_open+ql_pcm_write去播放 */
- ql_set_audio_path_speaker();
- ql_set_volume(TEST_PLAY_VOLUME);
-
- while(total_cnt < pcm_data_size)
- {
- if(pcm_data_size - total_cnt > PACKET_WRITE_MAX_SIZE) //单次最多可播放 PACKET_WRITE_MAX_SIZE 字节
- {
- cnt = PACKET_WRITE_MAX_SIZE;
- err = ql_aud_play_stream_start(QL_AUDIO_FORMAT_AMRWB, pcm_buffer+total_cnt, cnt, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback);
- }
- else
- {
- cnt = pcm_data_size - total_cnt;
- err = ql_aud_play_stream_start(QL_AUDIO_FORMAT_AMRWB, pcm_buffer+total_cnt, cnt, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback);
- }
-
- if(err < 0)
- {
- QL_AUDIO_LOG("start failed");
- goto exit;
- }
- else
- {
- QL_AUDIO_LOG("play %d bytes, total %d", cnt, total_cnt);
- total_cnt += cnt;
- }
- }
- ql_aud_data_done();
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- ql_aud_player_stop();
-
- QL_AUDIO_LOG("test successful");
- exit:
- if(pcm_buffer){
- free(pcm_buffer);
- pcm_buffer = NULL;
- pcm_data_size = 0;
- }
- }
- void test_record_file(void)
- {
- ql_aud_config config = {0};
- config.samplerate = 8000;
- ql_aud_adc_cfg adc_cfg={0};
- adc_cfg.adc_gain = QL_ADC_GAIN_LEVEL_12;
- ql_aud_dac_cfg dac_cfg={0};
- dac_cfg.dac_gain = 0xff;//32db
- if(ql_aud_record_file_start(TEST_RECORD_WAV_NAME, &config, QL_REC_TYPE_MIC, NULL) != QL_AUDIO_SUCCESS)
- {
- QL_AUDIO_LOG("record failed");
- return;
- }
- QL_AUDIO_LOG("record start");
- ql_rtos_task_sleep_s(3); //record 3s
- ql_aud_set_adc_gain(&adc_cfg);
- ql_rtos_task_sleep_s(3); //record 3s
- ql_aud_record_stop();
- QL_AUDIO_LOG("record finish, start play");
- ql_aud_set_dac_gain(&dac_cfg);
- ql_set_audio_path_speaker();
- if(ql_aud_play_file_start(TEST_RECORD_WAV_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- return;
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- ql_aud_player_stop();
- QL_AUDIO_LOG("test successful");
- }
- #endif
- void test_mp3(void)
- {
- //检测MP3文件格式是否正确,防止误将其他格式的文件命名为MP3格式
- //int err = check_audio_format(TEST_MP3_FILE_NAME);//路径为客户预置音频文件放置的路径
- //if(err)
- //{
- //QL_AUDIO_LOG("err = %d",err);
- //return;
- //}
-
- if(ql_aud_play_file_start(TEST_MP3_FILE_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- return;
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- if(ql_aud_play_file_start(TEST_MP3_FILE_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- return;
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- ql_aud_player_stop(); //播放结束,释放播放资源
-
- QL_AUDIO_LOG("test mp3 successful");
- }
- void test_wav(void)
- {
- int cnt = 0;
- //检测WAV文件格式是否正确,防止误将其他格式的文件命名为WAV格式
- //int err = check_audio_format(TEST_WAV_FILE_NAME);//路径为客户预置音频文件放置的路径
- //if(err)
- //{
- //QL_AUDIO_LOG("err = %d",err);
- //return;
- //}
- if(ql_aud_play_file_start(TEST_WAV_FILE_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- return;
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- QL_AUDIO_LOG("play %d times ok", ++cnt);
- if(ql_aud_play_file_start(TEST_WAV_FILE_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- return;
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
-
- QL_AUDIO_LOG("play %d times ok", ++cnt);
-
- ql_aud_player_stop(); //播放结束,释放播放资源
- QL_AUDIO_LOG("test wav successful");
- }
- void test_amr(void)
- {
- int cnt = 0;
- //检测AMR文件格式是否正确,防止误将其他格式的文件命名为AMR格式
- //int err = check_audio_format(TEST_AMR_FILE_NAME);//路径为客户预置音频文件放置的路径
- //if(err)
- //{
- //QL_AUDIO_LOG("err = %d",err);
- //return;
- //}
-
- if(ql_aud_play_file_start(TEST_AMR_FILE_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- QL_AUDIO_LOG("play %d times ok", ++cnt);
- if(ql_aud_play_file_start(TEST_AMR_FILE_NAME, QL_AUDIO_PLAY_TYPE_LOCAL, play_callback))
- {
- QL_AUDIO_LOG("play failed");
- }
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- QL_AUDIO_LOG("play %d times ok", ++cnt);
- ql_aud_player_stop(); //播放结束,释放播放资源
- QL_AUDIO_LOG("test wav successful");
- }
- void test_pcm(void)
- {
- PCM_HANDLE_T PCM = NULL;
- QL_PCM_CONFIG_T config;
- void *data = NULL;
- int size=0, write_cnt=0, cnt=0;
- ql_aud_dac_cfg dac_cfg={0};
- dac_cfg.dac_gain = 0xff;//32db
- config.channels = 1; //单声道
- config.samplerate = 8000;
- #ifdef QL_APP_FEATURE_AUDIO_RECORD
- PCM = ql_pcm_open(&config, QL_PCM_BLOCK_FLAG|QL_PCM_READ_FLAG);
- if(PCM == NULL)
- {
- QL_AUDIO_LOG("open pcm failed");
- goto exit;
- }
- data = malloc(50*1024);
- if(data == NULL)
- {
- goto exit;
- }
- QL_AUDIO_LOG("start read");
- size = ql_pcm_read(PCM, data, 50*1024);
- if(size <= 0)
- {
- QL_AUDIO_LOG("read pcm failed");
- goto exit;
- }
- QL_AUDIO_LOG("size is %d", size);
- if(ql_pcm_close(PCM) != 0)
- {
- QL_AUDIO_LOG("close pcm failed");
- goto exit;
- }
- PCM = NULL;
- #endif
- ql_set_audio_path_speaker();
-
- PCM = ql_pcm_open(&config, QL_PCM_BLOCK_FLAG|QL_PCM_WRITE_FLAG);
- if(PCM == NULL)
- {
- QL_AUDIO_LOG("open pcm failed");
- goto exit;
- }
- QL_AUDIO_LOG("start write");
- ql_aud_set_dac_gain(&dac_cfg);
- while(write_cnt < size)
- {
- if(size - write_cnt > PACKET_WRITE_MAX_SIZE) //单次最多可播放 PACKET_WRITE_MAX_SIZE 字节
- {
- cnt = ql_pcm_write(PCM, data+write_cnt, PACKET_WRITE_MAX_SIZE);
- }
- else
- {
- cnt = ql_pcm_write(PCM, data+write_cnt, size - write_cnt);
- }
- if(cnt <= 0)
- {
- QL_AUDIO_LOG("write failed");
- goto exit;
- }
- write_cnt += cnt;
- }
- ql_aud_data_done();
- ql_aud_wait_play_finish(QL_WAIT_FOREVER);
- QL_AUDIO_LOG("play done");
-
- if(ql_pcm_close(PCM) != 0)
- {
- QL_AUDIO_LOG("close pcm failed");
- goto exit;
- }
- PCM = NULL;
- QL_AUDIO_LOG("play finish");
- exit:
- if(PCM != NULL)
- {
- ql_pcm_close(PCM);
- }
- if(data != NULL)
- {
- free(data);
- data = NULL;
- }
- }
- /*
- ES8311寄存器组,用户可以对照ES8311手册在此修改寄存器
- g_codecInitRegList: 初始化codec时会将此结构体中的配置发送给codec
- g_codecrecRegList: 开始播放时会将此结构体中的配置发送给codec
- g_codecplayRegList: 开始录音时会将此结构体中的配置发送给codec
- g_codecCloseRegList:关闭codec时会将此结构体中的配置发送给codec
- 播放时的调用流程: g_codecInitRegList --> g_codecplayRegList --> g_codecCloseRegList
- 录音时的调用流程: g_codecInitRegList --> g_codecrecRegList --> g_codecCloseRegList
- */
- ql_codec_reg_t g_codecInitRegList[] = ES8311_INIT_CONFIG;
- ql_codec_reg_t g_codecrecRegList[] = ES8311_PLAY_CONFIG;
- ql_codec_reg_t g_codecplayRegList[] = ES8311_RECORD_CONFIG;
- ql_codec_reg_t g_codecCloseRegList[] = ES8311_CLOSE_CONFIG;
- typedef struct
- {
- uint8_t addr;
- uint8_t data;
- } extcodecReg_t;
- ql_audio_errcode_e ql_app_es8311_read_reg(uint8 RegAddr, uint8 *p_value)
- {
- uint8 retry_count = 5;
- while(retry_count--)
- {
- if(QL_I2C_SUCCESS == ql_I2cRead(QL_CUR_IIC_CHANNEL, ES8311_I2C_SLAVE_ADDR, RegAddr, p_value, 1))
- {
- return QL_AUDIO_SUCCESS;
- }
- }
-
- QL_EXT_CODEC_LOG("es311 read reg err 0x%x", RegAddr);
- return QL_AUDIO_CODEC_RD_FAIL;
- }
- ql_audio_errcode_e ql_app_es8311_write_reg(uint8 RegAddr, uint8 RegData)
- {
- uint8 retry_count = 5;
- while(retry_count--)
- {
- if(QL_I2C_SUCCESS == ql_I2cWrite(QL_CUR_IIC_CHANNEL, ES8311_I2C_SLAVE_ADDR, RegAddr, &RegData, 1))
- {
- return QL_AUDIO_SUCCESS;
- }
- }
- QL_EXT_CODEC_LOG("es311 write reg err 0x%x 0x%x",RegAddr, RegData);
- return QL_AUDIO_CODEC_WR_FAIL;
- }
- void ql_app_es8311_write_list(ql_codec_reg_t *regList, uint16_t len)
- {
- uint16_t regCount;
- for (regCount = 0; regCount < len; regCount++)
- {
- ql_app_es8311_write_reg(regList[regCount].addr, regList[regCount].data);
- }
- }
- int ql_app_es8311_cfg_cb(ql_codec_cb_param_t *param)
- {
- switch(param->stage)
- {
- case QL_EXT_CODEC_INIT:
- ql_pin_set_func(QL_CUR_IIC_CLK_PIN, 0);
- ql_pin_set_func(QL_CUR_IIC_SDA_PIN, 0);
- ql_I2cInit(QL_CUR_IIC_CHANNEL, STANDARD_MODE);
- ql_app_es8311_write_list(g_codecInitRegList, sizeof(g_codecInitRegList) / sizeof(ql_codec_reg_t));
- break;
- case QL_EXT_CODEC_REC:
- ql_app_es8311_write_list(g_codecrecRegList, sizeof(g_codecrecRegList) / sizeof(ql_codec_reg_t));
- break;
- case QL_EXT_CODEC_PLAY:
- ql_app_es8311_write_list(g_codecplayRegList, sizeof(g_codecplayRegList) / sizeof(ql_codec_reg_t));
- break;
-
- case QL_EXT_CODEC_DEINIT:
- ql_app_es8311_write_list(g_codecCloseRegList, sizeof(g_codecCloseRegList) / sizeof(ql_codec_reg_t));
- ql_I2cRelease(QL_CUR_IIC_CHANNEL);
- break;
-
- default:
- break;
- }
- return QL_AUDIO_SUCCESS;
- }
- void ql_ext_codec_cb_init(void)
- {
- ql_extcodec_info_t codec_cfg = {0};
- #if QL_USE_DAC_TM8211
- /*
- 使用TM8211时启用此demo;由于TM8211没有寄存器,所以不需要配置回调函数
- */
- codec_cfg.extcodec_enable = true;
- codec_cfg.callback = NULL;
- codec_cfg.protocal = QL_DATA_PROROCOL_IIS;
- codec_cfg.data_bits = QL_AUD_DATA_BIT_16;
- codec_cfg.rx_delay = QL_AUD_RXDELAY_0;
- codec_cfg.tx_delay = QL_AUD_TXDELAY_0;
- #elif QL_USE_DAC_ES7148
- /*
- 使用ES7148时启用此demo;由于ES7148没有寄存器,所以不需要配置回调函数
- */
- codec_cfg.extcodec_enable = true;
- codec_cfg.callback = ql_app_es8311_cfg_cb;
- codec_cfg.protocal = QL_DATA_PROROCOL_IIS;
- codec_cfg.data_bits = QL_AUD_DATA_BIT_32;
- codec_cfg.rx_delay = QL_AUD_RXDELAY_DEFAULT;
- codec_cfg.tx_delay = QL_AUD_RXDELAY_DEFAULT;
- #elif QL_USE_CODEC_ES8311
- /*
- 使用ES8311等需要配置寄存器的codec时,需要定义回调函数;
- 播放时,内核会按照 init -> play -> deinit的顺序调用
- 录音时,内核会按照 init -> rec -> deinit的顺序调用
- */
- codec_cfg.extcodec_enable = true;
- codec_cfg.callback = ql_app_es8311_cfg_cb;
- codec_cfg.protocal = QL_DATA_PROROCOL_IIS;
- codec_cfg.data_bits = QL_AUD_DATA_BIT_32;
- codec_cfg.rx_delay = QL_AUD_RXDELAY_DEFAULT;
- codec_cfg.tx_delay = QL_AUD_RXDELAY_DEFAULT;
- #endif
- ql_aud_ext_codec_cfg(&codec_cfg);
- }
|