pure sdk for main
This commit is contained in:
@@ -0,0 +1,445 @@
|
||||
#include "basic_include.h"
|
||||
#include "csi_kernel.h"
|
||||
#include "stream_define.h"
|
||||
#include "stream_frame.h"
|
||||
#include "custom_mem/custom_mem.h"
|
||||
#include "osal_file.h"
|
||||
#include "audio_dac.h"
|
||||
#include "mad.h"
|
||||
#include "mp3_decode.h"
|
||||
#include "mp3_getInfo.h"
|
||||
|
||||
#define BUFF_SIZE 2048
|
||||
#define MAX_MP3_DECODE_TXBUF 4
|
||||
|
||||
struct mp3_decode_struct {
|
||||
struct os_semaphore clean_sema;
|
||||
struct os_task task_hdl;
|
||||
stream *mp3_stream;
|
||||
uint8_t get_first_frame;
|
||||
uint8_t buf[BUFF_SIZE*2];
|
||||
uint32_t buf_size;
|
||||
uint32_t cur_sampleRate;
|
||||
mp3_read_func mp3_read;
|
||||
};
|
||||
static struct mp3_decode_struct *mp3_decode_s = NULL;
|
||||
|
||||
uint8_t mp3_play_finish = 1;
|
||||
static void *mp3_fp = NULL;
|
||||
static char *mp3_filename = NULL;
|
||||
static uint8_t next_status = MP3_STOP;
|
||||
static uint8_t current_status = MP3_STOP;
|
||||
static uint32_t file_size = 0;
|
||||
|
||||
void mp3_decode_deinit(void);
|
||||
|
||||
uint8_t get_mp3_decode_status(void)
|
||||
{
|
||||
return current_status;
|
||||
}
|
||||
|
||||
void set_mp3_decode_status(uint8_t status)
|
||||
{
|
||||
next_status = status;
|
||||
}
|
||||
|
||||
int32_t mp3_file_read(uint8_t *buf, uint32_t size)
|
||||
{
|
||||
int32_t read_len = 0;
|
||||
|
||||
read_len = osal_fread(buf, size, 1, mp3_fp);
|
||||
return read_len;
|
||||
}
|
||||
|
||||
static uint16_t CRC_16(uint8_t *temp,uint16_t len)
|
||||
{
|
||||
uint16_t i,j;
|
||||
uint16_t CRC_1 = 0xFFFF;
|
||||
|
||||
for(i = 0;i < len;i++)
|
||||
{
|
||||
CRC_1 ^= temp[i];
|
||||
for(j = 0;j < 8;j++)
|
||||
{
|
||||
if(CRC_1 & 0x01)
|
||||
{
|
||||
CRC_1 >>=1;
|
||||
CRC_1 ^= 0xA001;
|
||||
}
|
||||
else
|
||||
{
|
||||
CRC_1 >>=1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(CRC_1);
|
||||
}
|
||||
|
||||
static enum mad_flow error(void *data,struct mad_stream *stream, struct mad_frame *frame)
|
||||
{
|
||||
struct mp3_decode_struct *s = (struct mp3_decode_struct *)data;
|
||||
|
||||
os_printf("decoding error 0x%04x (%s) at byte offset %u\n",
|
||||
stream->error, mad_stream_errorstr(stream),
|
||||
stream->this_frame - s->buf);
|
||||
|
||||
/* return MAD_FLOW_BREAK here to stop decoding (and propagate an error) */
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
static enum mad_flow input(void *cb_data, struct mad_stream *stream)
|
||||
{
|
||||
uint8_t *mp3_buf = NULL;
|
||||
int32_t read_len = 0;
|
||||
int32_t ret_code;
|
||||
uint32_t ID3V2_len = 0;
|
||||
int32_t ID3V2_offset = 0;
|
||||
uint32_t unproc_data_size = 0; /*the unprocessed data's size*/
|
||||
struct mp3_decode_struct *s = (struct mp3_decode_struct *)cb_data;
|
||||
|
||||
if(os_sema_down(&mp3_decode_s->clean_sema, 0))
|
||||
mad_stream_init(stream);
|
||||
mp3_buf = s->buf;
|
||||
while(!s->get_first_frame) {
|
||||
read_len = s->mp3_read(s->buf+unproc_data_size,BUFF_SIZE);
|
||||
if(read_len <= 0) {
|
||||
os_printf("%s %d err!\n",__FUNCTION__,__LINE__);
|
||||
return MAD_FLOW_STOP;
|
||||
}
|
||||
s->buf_size = read_len + unproc_data_size;
|
||||
if(os_strncmp(mp3_buf, "ID3", 3) == 0)
|
||||
{
|
||||
if (s->buf_size < 10) {
|
||||
unproc_data_size = s->buf_size;
|
||||
os_sleep_ms(5);
|
||||
continue;
|
||||
}
|
||||
ID3V2_len = (mp3_buf[6]&0x7F)*0x200000+ (mp3_buf[7]&0x7F)*0x4000 +
|
||||
(mp3_buf[8]&0x7F)*0x80 +(mp3_buf[9]&0x7F);
|
||||
ID3V2_offset = (ID3V2_len+10);
|
||||
while(ID3V2_offset >= read_len) {
|
||||
os_sleep_ms(5);
|
||||
ID3V2_offset -= read_len;
|
||||
read_len = s->mp3_read(s->buf,BUFF_SIZE);
|
||||
s->buf_size = read_len;
|
||||
}
|
||||
if(ID3V2_offset) {
|
||||
s->buf_size -= ID3V2_offset;
|
||||
os_memcpy(mp3_buf, mp3_buf+ID3V2_offset, (read_len-ID3V2_offset));
|
||||
}
|
||||
if(s->buf_size <= 1) {
|
||||
os_sleep_ms(5);
|
||||
unproc_data_size = s->buf_size;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
for(uint32_t i=0; i<(s->buf_size-1); i++) {
|
||||
if( ( (mp3_buf[i] << 8) | (mp3_buf[i+1] & 0xE0) ) == 0xFFE0 ) {
|
||||
s->get_first_frame = 1;
|
||||
unproc_data_size = s->buf_size - i;
|
||||
s->buf_size = unproc_data_size;
|
||||
mad_stream_buffer(stream, s->buf, s->buf_size);
|
||||
unproc_data_size = 0;
|
||||
ret_code = MAD_FLOW_CONTINUE;
|
||||
return ret_code;
|
||||
}
|
||||
}
|
||||
if(!s->get_first_frame) {
|
||||
unproc_data_size = 1;
|
||||
mp3_buf[0] = mp3_buf[s->buf_size-1];
|
||||
}
|
||||
os_sleep_ms(5);
|
||||
}
|
||||
unproc_data_size += stream->bufend - stream->next_frame;
|
||||
if(unproc_data_size)
|
||||
os_memcpy(s->buf, s->buf+s->buf_size-unproc_data_size, unproc_data_size);
|
||||
read_len = s->mp3_read(s->buf+unproc_data_size,BUFF_SIZE);
|
||||
if(read_len <= 0)
|
||||
ret_code = MAD_FLOW_STOP;
|
||||
else {
|
||||
s->buf_size = read_len + unproc_data_size;
|
||||
/*Hand off the buffer to the mp3 input stream*/
|
||||
mad_stream_buffer(stream, s->buf, s->buf_size);
|
||||
ret_code = MAD_FLOW_CONTINUE;
|
||||
}
|
||||
unproc_data_size = 0;
|
||||
return ret_code;
|
||||
}
|
||||
|
||||
static enum mad_flow output(void *cb_data, struct mad_header const *header, struct mad_pcm *pcm)
|
||||
{
|
||||
int16_t sample_val = 0;
|
||||
int16_t *data = NULL;
|
||||
uint32_t offset = 0;
|
||||
uint32_t nchannels, nsamples;
|
||||
uint32_t samplerate;
|
||||
int16_t *left_ch, *right_ch;
|
||||
struct data_structure *data_s = NULL;
|
||||
struct mp3_decode_struct *s = (struct mp3_decode_struct *)cb_data;
|
||||
stream *mp3_stream = s->mp3_stream;
|
||||
|
||||
/* pcm->samplerate contains the sampling frequency */
|
||||
samplerate = pcm->samplerate;
|
||||
nchannels = pcm->channels;
|
||||
nsamples = pcm->length;
|
||||
left_ch = pcm->samples[0];
|
||||
right_ch = pcm->samples[1];
|
||||
|
||||
get_data_structure:
|
||||
data_s = get_src_data_f(mp3_stream);
|
||||
if(data_s) {
|
||||
data = (int16_t*)get_stream_real_data(data_s);;
|
||||
while (nsamples--) {
|
||||
sample_val = (*left_ch++);
|
||||
data[offset] = sample_val;
|
||||
if (nchannels == 2) {
|
||||
sample_val = (*right_ch++);
|
||||
data[offset] = (data[offset]+sample_val)/2;
|
||||
}
|
||||
offset++;
|
||||
}
|
||||
set_stream_real_data_len(data_s, pcm->length*2);
|
||||
data_s->type = SET_DATA_TYPE(SOUND,SOUND_FILE);
|
||||
|
||||
if(s->cur_sampleRate != samplerate)
|
||||
{
|
||||
s->cur_sampleRate = samplerate;
|
||||
audio_da_recfg(samplerate);
|
||||
}
|
||||
|
||||
send_data_to_stream(data_s);
|
||||
}
|
||||
else {
|
||||
os_sleep_ms(1);
|
||||
goto get_data_structure;
|
||||
}
|
||||
|
||||
if(next_status == MP3_PAUSE)
|
||||
{
|
||||
current_status = MP3_PAUSE;
|
||||
while(next_status == MP3_PAUSE)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
}
|
||||
|
||||
if(next_status == MP3_STOP)
|
||||
{
|
||||
return MAD_FLOW_STOP;
|
||||
}
|
||||
current_status = MP3_PLAY;
|
||||
|
||||
return MAD_FLOW_CONTINUE;
|
||||
}
|
||||
|
||||
static int decode(struct mp3_decode_struct *s)
|
||||
{
|
||||
int result;
|
||||
struct mad_decoder decoder;
|
||||
|
||||
/* configure input, output, and error functions */
|
||||
mad_decoder_init(&decoder, s,
|
||||
input, 0 /* header */, 0 /* filter */, output,
|
||||
error, 0 /* message */);
|
||||
|
||||
/* start decoding */
|
||||
result = mad_decoder_run(&decoder, MAD_DECODER_MODE_SYNC);
|
||||
|
||||
/* release the decoder */
|
||||
mad_decoder_finish(&decoder);
|
||||
return result;
|
||||
}
|
||||
|
||||
void mp3_decode_file_thread(void *d)
|
||||
{
|
||||
int32_t former_dac_filter_type = 0;
|
||||
int32_t former_dac_samplingrate = 0;
|
||||
struct mp3_decode_struct *s = (struct mp3_decode_struct *)d;
|
||||
|
||||
if(mp3_fp) {
|
||||
curmp3_info_init(mp3_filename);
|
||||
file_size = osal_fsize(mp3_fp);
|
||||
get_curmp3_size(file_size);
|
||||
find_first_frame(mp3_fp);
|
||||
}
|
||||
if(cur_mp3_info)
|
||||
osal_fseek(mp3_fp, cur_mp3_info->first_frame_offset);
|
||||
|
||||
former_dac_filter_type = get_audio_dac_set_filter_type();
|
||||
audio_dac_set_filter_type(SOUND_FILE);
|
||||
former_dac_samplingrate = audio_dac_get_samplingrate();
|
||||
s->cur_sampleRate = former_dac_samplingrate;
|
||||
|
||||
next_status = MP3_PLAY;
|
||||
current_status = MP3_PLAY;
|
||||
mp3_play_finish = 0;
|
||||
|
||||
decode(s);
|
||||
|
||||
clear_curmp3_info();
|
||||
mp3_decode_deinit();
|
||||
if(s->mp3_stream)
|
||||
{
|
||||
close_stream(s->mp3_stream);
|
||||
}
|
||||
while(mp3_play_finish != 1) {
|
||||
os_sleep_ms(1);
|
||||
}
|
||||
audio_dac_set_filter_type(former_dac_filter_type);
|
||||
if(former_dac_samplingrate != audio_dac_get_samplingrate())
|
||||
audio_da_recfg(former_dac_samplingrate);
|
||||
}
|
||||
|
||||
void mp3_decode_deinit(void)
|
||||
{
|
||||
if(mp3_fp) {
|
||||
osal_fclose(mp3_fp);
|
||||
mp3_fp = NULL;
|
||||
}
|
||||
if(mp3_decode_s->clean_sema.hdl)
|
||||
os_sema_del(&mp3_decode_s->clean_sema);
|
||||
next_status = MP3_STOP;
|
||||
current_status = MP3_STOP;
|
||||
}
|
||||
|
||||
static uint32_t get_mp3_data_len(void *data)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
return ((uint32_t)d->priv);
|
||||
}
|
||||
|
||||
static uint32_t set_mp3_data_len(void *data,uint32_t len)
|
||||
{
|
||||
struct data_structure *d = (struct data_structure *)data;
|
||||
d->priv = (void*)len;
|
||||
return (uint32_t)len;
|
||||
}
|
||||
|
||||
static stream_ops_func stream_sound_ops =
|
||||
{
|
||||
.get_data_len = get_mp3_data_len,
|
||||
.set_data_len = set_mp3_data_len,
|
||||
};
|
||||
|
||||
static int opcode_func(stream *s,void *priv,int opcode)
|
||||
{
|
||||
int res = 0;
|
||||
switch(opcode)
|
||||
{
|
||||
case STREAM_OPEN_EXIT:
|
||||
{
|
||||
stream_data_dis_mem_custom(s);
|
||||
streamSrc_bind_streamDest(s,R_SPEAKER);
|
||||
s->priv = priv;
|
||||
}
|
||||
break;
|
||||
case STREAM_DATA_DIS:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
data->priv = (void*)(1152*2);
|
||||
data->ops = &stream_sound_ops;
|
||||
data->data = (void*)MP3_DECODE_MALLOC((1152*2));
|
||||
}
|
||||
break;
|
||||
case STREAM_DATA_DESTORY:
|
||||
{
|
||||
struct data_structure *data = (struct data_structure *)priv;
|
||||
if(data->data)
|
||||
{
|
||||
MP3_DECODE_FREE(data->data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case STREAM_DEL:
|
||||
{
|
||||
if(s->priv)
|
||||
{
|
||||
MP3_DECODE_FREE(s->priv);
|
||||
}
|
||||
MP3_DECODE_FREE(mp3_decode_s);
|
||||
mp3_decode_s = NULL;
|
||||
mp3_play_finish = 1;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
void mp3_decode_clean_stream(void)
|
||||
{
|
||||
if(mp3_decode_s->clean_sema.hdl)
|
||||
os_sema_up(&(mp3_decode_s->clean_sema));
|
||||
}
|
||||
|
||||
void mp3_decode_init(void *d, void *read_func)
|
||||
{
|
||||
uint8_t status = 0;
|
||||
uint32_t count = 0;
|
||||
mp3_read_func func = NULL;
|
||||
stream *mp3_stream = NULL;
|
||||
char *mp3_stream_name = NULL;
|
||||
|
||||
status = get_mp3_decode_status();
|
||||
if(status != MP3_STOP)
|
||||
{
|
||||
set_mp3_decode_status(MP3_STOP);
|
||||
}
|
||||
while((get_mp3_decode_status() != MP3_STOP) && count < 1000)
|
||||
{
|
||||
os_sleep_ms(1);
|
||||
count ++;
|
||||
}
|
||||
if(count >= 1000)
|
||||
{
|
||||
os_printf("%s creat fail:%d\n",__FUNCTION__,get_mp3_decode_status());
|
||||
return;
|
||||
}
|
||||
mp3_filename = (char*)d;
|
||||
if(mp3_filename){
|
||||
mp3_fp = osal_fopen(mp3_filename, "rb");
|
||||
if(!mp3_fp)
|
||||
return;
|
||||
func = mp3_file_read;
|
||||
}
|
||||
else if(read_func) {
|
||||
func = (mp3_read_func)read_func;
|
||||
}
|
||||
else
|
||||
return;
|
||||
|
||||
mp3_stream_name = (char*)MP3_DECODE_ZALLOC(64);
|
||||
os_sprintf(mp3_stream_name,"%s_%d",S_MP3_AUDIO,(int)(os_jiffies()%1000));
|
||||
mp3_stream = open_stream_available(mp3_stream_name,MAX_MP3_DECODE_TXBUF,0,opcode_func,mp3_stream_name);
|
||||
if(!mp3_stream) {
|
||||
os_printf("%s %d err!\n",__FUNCTION__,__LINE__);
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
|
||||
mp3_decode_s = (struct mp3_decode_struct *)MP3_DECODE_ZALLOC(sizeof(struct mp3_decode_struct));
|
||||
if(!mp3_decode_s) {
|
||||
os_printf("%s %d err!\n",__FUNCTION__,__LINE__);
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
mp3_decode_s->mp3_stream = mp3_stream;
|
||||
mp3_decode_s->mp3_read = func;
|
||||
if(os_sema_init(&mp3_decode_s->clean_sema, 0) != RET_OK) {
|
||||
os_printf("%s %d err!\n",__FUNCTION__,__LINE__);
|
||||
goto mp3_decode_init_err;
|
||||
}
|
||||
#if FORCE_MONO_CHANNEL
|
||||
os_task_create("mp3_decode_file_thread", mp3_decode_file_thread, (void*)mp3_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 6144);
|
||||
#else
|
||||
os_task_create("mp3_decode_file_thread", mp3_decode_file_thread, (void*)mp3_decode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 8192);
|
||||
#endif
|
||||
return;
|
||||
|
||||
mp3_decode_init_err:
|
||||
if(mp3_stream)
|
||||
close_stream(mp3_stream);
|
||||
if(mp3_fp)
|
||||
osal_fclose(mp3_fp);
|
||||
}
|
||||
Reference in New Issue
Block a user