Files
banban/ql-application/threadx/interface/custom_app/mp3_player.c
T

486 lines
10 KiB
C

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#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 <netdb.h>
#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_length<session->content_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;
}