#include #include #include #include "ql_rtos.h" #include "ql_application.h" #include "ql_audio.h" #include "ql_iic.h" #include "ql_gpio.h" #include "ql_fs.h" #include "webclient.h" #include #include "sockets.h" #include "mp3dec.h" #include "test_mp3.h" #define RLOGD printf struct webclient_session *session = NULL; static int pos_length,total_length = 0; static Mp3PlaybackHandle mp3_handle; static Mp3PlayConfigInfo mp3_configInfo; static unsigned char mp3_player_status = 0; QFILE *local_mp3_file_fd=NULL; static int mp3_player_end_frame = 0; int current_sample_rate = 0; static audio_track_handle track_hd; static unsigned short pcm_buff[1152*2]={0x00}; struct mp3_decoder { /* mp3 information */ HMP3Decoder decoder; MP3FrameInfo frame_info; // rt_uint32_t frames; /* mp3 read session */ uint8_t *read_buffer, *read_ptr; u32 bytes_left; }; static void mp3_decoder_track_callback(acm_audio_track_handle handle, acm_audio_track_event_t event) { if(mp3_player_status==1 && mp3_player_end_frame==1){ if(event == AUDIO_TRACK_EVENT_UNDERRUN){ printf("AUDIO_TRACK_EVENT_UNDERRUN\r\n"); mp3_player_status = 2;// } } if(mp3_player_status==2){ if(event == AUDIO_TRACK_EVENT_DRAINING){ printf("AUDIO_TRACK_EVENT_DRAINING\r\n"); mp3_player_status = 3;// } } } void mp3_decoder_init(struct mp3_decoder* decoder) { /* init read session */ decoder->read_ptr = NULL; decoder->bytes_left = 0; decoder->decoder = MP3InitDecoder(); } void mp3_decoder_detach(struct mp3_decoder* decoder) { /* release mp3 decoder */ MP3FreeDecoder(decoder->decoder); } struct mp3_decoder* mp3_decoder_create() { struct mp3_decoder* decoder; /* allocate object */ decoder = (struct mp3_decoder*) malloc(sizeof(struct mp3_decoder)); if (decoder != NULL) { mp3_decoder_init(decoder); } return decoder; } void mp3_decoder_delete(struct mp3_decoder* decoder) { /* de-init mp3 decoder object */ mp3_decoder_detach(decoder); /* release this object */ free(decoder); decoder = NULL; } static int check_mp3_sync_word(struct mp3_decoder *codec) { int err; memset(&codec->frame_info, 0, sizeof(MP3FrameInfo)); err = MP3GetNextFrameInfo(codec->decoder, &codec->frame_info, codec->read_ptr); if (err == ERR_MP3_INVALID_FRAMEHEADER) { goto __err; } else if (err != ERR_MP3_NONE) { goto __err; } else if (codec->frame_info.nChans != 1 && codec->frame_info.nChans != 2) { goto __err; } else if (codec->frame_info.bitsPerSample != 16 && codec->frame_info.bitsPerSample != 8) { goto __err; } return 0; __err: return -1; } int mp3_decoder_run(struct mp3_decoder* decoder) { int err; int read_offset = 0;; // rt_kprintf("decoder->bytes_left:%d,mp3_player_end_frame:%d\n", decoder->bytes_left,mp3_player_end_frame); extern int tts_playing; if(tts_playing==2){ return -1; } if ((decoder->read_ptr == NULL) || decoder->bytes_left < 2 * MAINBUF_SIZE) { mp3_player_end_frame = 1; } // printf("mp3_player_end_frame:%d,decoder->bytes_left:%d\n", mp3_player_end_frame, decoder->bytes_left); if(mp3_player_end_frame&& (decoder->bytes_left==0)){ //mp3_player_end_frame = 0; return -1; } //loop_find: // rt_kprintf("read offset: 0x%08x\n", decoder->read_ptr - decoder->read_buffer); read_offset = MP3FindSyncWord(decoder->read_ptr, decoder->bytes_left); if (read_offset < 0) { //if(mp3_decoder_fill_buffer(decoder) == 0) goto loop_find; /* discard this data */ RLOGD("outof sync, byte left: %d\n", decoder->bytes_left); decoder->bytes_left = 0; return 0; } if(read_offset > decoder->bytes_left) { RLOGD("find sync exception: %d:%d.", read_offset, decoder->bytes_left); decoder->read_ptr += decoder->bytes_left; decoder->bytes_left = 0; } else { decoder->read_ptr += read_offset; decoder->bytes_left -= read_offset; } if (check_mp3_sync_word(decoder) == -1) { if (decoder->bytes_left > 0) { decoder->bytes_left --; decoder->read_ptr ++; } return 0; } if (decoder->bytes_left < 1024) { mp3_player_end_frame = 1; if(decoder->bytes_left==0) return -1; } err = MP3Decode(decoder->decoder, &decoder->read_ptr, (int*)&decoder->bytes_left, (short*)pcm_buff, 0); if (err != ERR_MP3_NONE) { switch (err) { case ERR_MP3_INDATA_UNDERFLOW: RLOGD("ERR_MP3_INDATA_UNDERFLOW\n"); //decoder->bytes_left = 0; if(mp3_player_end_frame == 1) { /* release this memory block */ if(decoder->bytes_left==0){ return -1; } } break; case ERR_MP3_MAINDATA_UNDERFLOW: /* do nothing - next call to decode will provide more mainData */ RLOGD("ERR_MP3_MAINDATA_UNDERFLOW\n"); break; default: RLOGD("unknown error: %d, left: %d\n", err, decoder->bytes_left); // skip this frame if (decoder->bytes_left > 0) { decoder->bytes_left --; decoder->read_ptr ++; } else { // TODO //RT_ASSERT(0); } break; } } else { int outputSamps; /* no error */ MP3GetLastFrameInfo(decoder->decoder, &decoder->frame_info); /* set sample rate */ if (decoder->frame_info.samprate != current_sample_rate) { current_sample_rate = decoder->frame_info.samprate; } ql_audio_track_write(track_hd, (char*)pcm_buff, 1152); } return 0; } u32 local_mp3_data_fetch(const char *uri, uint8_t *buffer, u32 length) { int read_bytes; if(local_mp3_file_fd==NULL){ local_mp3_file_fd= ql_fopen(uri, "r"); if (local_mp3_file_fd==NULL){ return 0; } } read_bytes = ql_fread(buffer, 1, length, local_mp3_file_fd); if (read_bytes <= 0) return 0; return read_bytes; } size_t url_mp3_data_fetch(const char *uri, uint8_t *buffer, size_t length) { int resp_status = -1; uint32_t nw = length; uint32_t page_pos = 0; int error_cnt = 0; //printf("fd_fetch start\n"); session = webclient_session_create(1024); if (!session) { printf("open uri failed."); goto __exit; } resp_status = webclient_get(session, uri); if (resp_status == 304) { printf("file download failed! Server http response : 304 not modified!"); goto __exit; } if (resp_status != 200) { printf("file download failed! Server http response : %d,%s !", resp_status, uri); goto __exit; } if (session->content_length == 0) { printf("Request file size is 0!"); goto __exit; } printf("start read\n"); if(total_length < session->content_length) { if ((nw + total_length) > session->content_length) { nw = session->content_length - total_length; //log_i("last page, content_length:%d, total_length:%d, nw:%d\n", session->content_length, total_length, nw); } /* read */ page_pos = 0; do { if(vad_audio_is_recording()) { break; } pos_length = webclient_read(session, buffer + page_pos, nw - page_pos); if(pos_length<0){ if(error_cnt++<3){ continue; }else{ break; } } if (pos_length == 0) { printf("read error: %d, content_pos:%d, page_pos:%d\n", pos_length, total_length, page_pos); break; } //LOG_I("webclient_read %d\n", length); page_pos += pos_length; } while (page_pos < nw); /* read */ total_length += page_pos; } printf("end read:%d, %d\n", total_length, session->content_length); __exit: //printf("fd_fetch end\n"); if (session != NULL){ webclient_close(session); session = NULL; } if(total_lengthcontent_length){ total_length = 0; return -1; } return 0; } struct mp3_decoder* aofei_mp3_decoder = NULL; int aofei_mp3_player_init(void) { if(aofei_mp3_decoder==NULL){ aofei_mp3_decoder = mp3_decoder_create(); if (aofei_mp3_decoder == NULL){ RLOGD("mp3_decoder_create error\n"); return -1; } } return 0; } void aofei_mp3_player(char *file_name) { int ret = 0; uint8_t *mp3_buff = malloc(100*1024); memset(mp3_buff, 0, 100*1024); //直接下载到一个100k的buffer if(strstr(file_name, "http:")){//播放url ret = url_mp3_data_fetch(file_name, mp3_buff, 100*1024); }else if(strstr(file_name, "test.mp3")){//播放本地音频 total_length = test_data_size; memcpy(mp3_buff, test_data, total_length); }else{//播放本地音频 total_length = local_mp3_data_fetch(file_name, mp3_buff, 100*1024); } mp3_player_end_frame = 0; if(aofei_mp3_player_init()==-1)return; if(ret>=0){ aofei_mp3_decoder->read_ptr = mp3_buff; aofei_mp3_decoder->bytes_left = total_length; track_hd = ql_audio_track_open(16000, 1, 0, mp3_decoder_track_callback); app_codec_pa_open(); mp3_player_status = 1; RLOGD("aofei_mp3_player0\n"); while(mp3_decoder_run(aofei_mp3_decoder)!=-1){ if(vad_audio_is_recording()||tts_playing_ret()==2){ mp3_player_status = 0; break; } ql_rtos_task_sleep_ms(35); } while(mp3_player_status!=2){ if(vad_audio_is_recording() || tts_playing_ret()==2){ mp3_player_status = 0; break; } ql_rtos_task_sleep_ms(30); } RLOGD("aofei_mp3_player1\n"); ql_audio_track_close(track_hd, 1); while(mp3_player_status!=3){ if(vad_audio_is_recording()||tts_playing_ret()==2){ mp3_player_status = 0; break; } ql_rtos_task_sleep_ms(30); } if(!vad_audio_is_recording()){ ql_rtos_task_sleep_ms(200); } RLOGD("aofei_mp3_player2\n"); app_codec_pa_close(); } if(aofei_mp3_decoder!=NULL){ mp3_decoder_delete(aofei_mp3_decoder); aofei_mp3_decoder = NULL; } if(local_mp3_file_fd!=NULL){ ql_fclose(local_mp3_file_fd); local_mp3_file_fd = NULL; } if (session != NULL){ webclient_close(session); session = NULL; } if(mp3_buff!=NULL){ free(mp3_buff); mp3_buff = NULL; } total_length = 0; mp3_player_end_frame = 0; mp3_player_status = 0; }