pure sdk for main

This commit is contained in:
divadiow
2025-08-27 09:51:58 +01:00
parent f0d033f1c9
commit 0571416e7c
3283 changed files with 1577720 additions and 1 deletions
+445
View File
@@ -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);
}
+30
View File
@@ -0,0 +1,30 @@
#ifndef _MP3_DECODE_MSI_H_
#define _MP3_DECODE_MSI_H_
#include "basic_include.h"
#include "custom_mem/custom_mem.h"
#ifdef PSRAM_HEAP
#define MP3_DECODE_MALLOC custom_malloc_psram
#define MP3_DECODE_ZALLOC custom_zalloc_psram
#define MP3_DECODE_FREE custom_free_psram
#else
#define MP3_DECODE_MALLOC custom_malloc
#define MP3_DECODE_ZALLOC custom_zalloc
#define MP3_DECODE_FREE custom_free
#endif
typedef int32 (*mp3_read_func)(uint8_t *buf, uint32_t size);
enum
{
MP3_NOT_RUN, //代表可能创建了线程,但没有实际运行(可能是创建线程失败或者被其他高优先级任务一直卡住)
MP3_PLAY,
MP3_PAUSE,
MP3_STOP,
};
void mp3_decode_init(void *filename, void *read_func);
void set_mp3_decode_status(uint8_t status);
uint8_t get_mp3_decode_status(void);
#endif
+474
View File
@@ -0,0 +1,474 @@
#include "basic_include.h"
#include "keyWork.h"
#include "keyScan.h"
#include "osal_file.h"
#include "mp3_getInfo.h"
#include "mp3_decode.h"
#define MP3_SAVE_INFO 0
#if MP3_SAVE_INFO
#define MAX_FORWARD_TIME 10
struct key_callback_list_s *key_seek_list = NULL;
#endif
uint32_t bitrate_table[5][15] = {
/* MPEG-1 */
{ 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, /* Layer I */
256000, 288000, 320000, 352000, 384000, 416000, 448000 },
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer II */
128000, 160000, 192000, 224000, 256000, 320000, 384000 },
{ 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, /* Layer III */
112000, 128000, 160000, 192000, 224000, 256000, 320000 },
/* MPEG-2 ,MPEG-2.5 */
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, /* Layer I */
128000, 144000, 160000, 176000, 192000, 224000, 256000 },
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, /* Layer */
64000, 80000, 96000, 112000, 128000, 144000, 160000 } /* II & III */
};
uint32_t samplingrate_table[4][3] = { //value s are in Hz
{11025 , 12000 , 8000}, //MPEG Version 2.5
{0,0,0}, //reserved
{22050, 24000, 16000}, //MPEG Version 2 (ISO/IEC 13818-3)
{44100, 48000, 32000} //MPEG Version 1 (ISO/IEC 11172-3)
};
uint8_t layerIII_inbytes[4][4] = {
{17,17,17,9}, /*MPEG Version 2.5*/
{0, 0, 0, 0}, /*reserved*/
{17,17,17,9}, /*MPEG Version 2*/
{32,32,32,17} /*MPEG Version 1*/
};
uint16_t samples_table[4][4] = {
{0,576,1152,384}, /*MPEG Version 2.5 {reserve,layerIII,layerII,layerI}*/
{0,0,0,0}, /*reserved {reserve,layerIII,layerII,layerI}*/
{0,576,1152,384}, /*MPEG Version 2 {reserve,layerIII,layerII,layerI}*/
{0,1152,1152,384} /*MPEG Version 1 {reserve,layerIII,layerII,layerI}*/
};
uint32_t get_curmp3_size(uint32_t s)
{
if(!cur_mp3_info)
return 0;
cur_mp3_info->total_size =s;
return cur_mp3_info->total_size;
}
void curmp3_info_init(char *mp3_filename)
{
#if MP3_SAVE_INFO
char dirname_len = strlen("0:mp3/");
char extension_len = strlen("mp3");
char filename_temp[50] = {0};
#endif
if(!cur_mp3_info)
cur_mp3_info = (CUR_MP3_INFO*)MP3_DECODE_ZALLOC(sizeof(CUR_MP3_INFO));
else
os_memset(cur_mp3_info, 0, sizeof(cur_mp3_info));
#if MP3_SAVE_INFO
os_memcpy(filename_temp, mp3_filename+dirname_len, strlen(mp3_filename)-dirname_len-extension_len);
filename_temp[strlen(mp3_filename)-dirname_len-extension_len] = '\0';
os_sprintf(cur_mp3_info->mp3_st_filename, "0:MP3_SEEK/%s%s", filename_temp, "st");
os_printf("mp3_st_filename:%s\n",cur_mp3_info->mp3_st_filename);
#endif
}
void get_curmp3_totaltime_ergodic(void *fp, uint32_t first_frame_offset)
{
uint8_t bitrate_index = 0;
uint8_t padding = 0;
uint8_t frame_head[4];
int32_t read_len = 0;
uint32_t bitrate = 0;
uint32_t frame_len = 0;
uint32_t offset = 0;
uint32_t current_seek = 0;
uint32_t read_frame_cnt = 0;
uint32_t read_second_cnt = 0;
if(!cur_mp3_info)
return;
current_seek = osal_ftell(fp);
osal_fseek(fp, first_frame_offset);
osal_fread(frame_head, 1, 4, fp);
offset = first_frame_offset;
bitrate_index = (frame_head[2]>>4)&0xf;
bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
padding = ((frame_head[2]>>1)&0x1) * cur_mp3_info->padding_mul;
frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
offset = first_frame_offset+4;
// printf("samples:%d samplingrate:%d bitrate:%d\n",cur_mp3_info->samples,cur_mp3_info->samplingrate,bitrate);
INIT_LIST_HEAD((struct list_head *)&cur_mp3_info->seek_table_head);
MP3_SEEK_TABLE *sub_seek_table = custom_zalloc_psram(sizeof(MP3_SEEK_TABLE));
list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&cur_mp3_info->seek_table_head);
sub_seek_table->sub_table[0] = first_frame_offset;
while(1) {
osal_fseek(fp, offset+frame_len-4);
offset += frame_len;
read_len = osal_fread(frame_head, 1, 4, fp);
if(((cur_mp3_info->total_size-offset)==124) && (strncmp((const char*)frame_head, "TAG", 3)==0)) { //ID3V1
break;
}
if(((frame_head[0]<<8) | (frame_head[1]&0xE0)) != 0xFFE0) {
break;
}
if((offset+frame_len-4) >= cur_mp3_info->total_size ) { //end
break;
}
cur_mp3_info->total_frame++;
bitrate_index = (frame_head[2]>>4)&0xf;
bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
padding = ((frame_head[2]>>1)&0x1) * cur_mp3_info->padding_mul;
frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
read_frame_cnt++;
if(read_frame_cnt >= (cur_mp3_info->one_second_frame)) {
read_second_cnt++;
if(read_second_cnt >= 100) {
sub_seek_table = (MP3_SEEK_TABLE*)custom_zalloc_psram(sizeof(MP3_SEEK_TABLE));
list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&cur_mp3_info->seek_table_head);
read_second_cnt -= 100;
}
sub_seek_table->sub_table[read_second_cnt] = offset-4;
read_frame_cnt -= (cur_mp3_info->one_second_frame);
}
}
cur_mp3_info->totaltime = cur_mp3_info->total_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
cur_mp3_info->once_move_time = (cur_mp3_info->totaltime%100)?(cur_mp3_info->totaltime/100+1):(cur_mp3_info->totaltime/100);
os_printf("total_frame:%d total_time:%d once_move_time:%d\n",cur_mp3_info->total_frame, cur_mp3_info->totaltime,cur_mp3_info->once_move_time);
cur_mp3_info->get_totaltime = 1;
osal_fseek(fp, current_seek);
}
uint32_t get_mp3_seek(void)
{
if(!cur_mp3_info)
return 0;
return cur_mp3_info->offset_seek;
}
uint32_t get_curmp3_playtime(void)
{
if(!cur_mp3_info)
return 0;
cur_mp3_info->playtime = cur_mp3_info->play_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
// printf("record:%d %d\n",cur_mp3_info->playtime,cur_mp3_info->play_frame);
return cur_mp3_info->playtime;
}
uint32_t get_curmp3_playframe(void)
{
if(!cur_mp3_info)
return 0;
cur_mp3_info->play_frame++;
return cur_mp3_info->play_frame;
}
void update_curmp3_playtime(uint32_t update_time)
{
if(!cur_mp3_info)
return;
cur_mp3_info->playtime = update_time;
}
void update_curmp3_playframe(uint32_t update_frame)
{
if(!cur_mp3_info)
return;
cur_mp3_info->play_frame = update_frame;
}
void set_mp3_seek(int16_t move_time)
{
uint8_t table_pos = 0;
uint32_t offset_seek = 0;
uint32_t target_time = 0;
uint32_t target_frame = 0;
uint32_t table_index = 0;
struct list_head *seek_table_list = NULL;
MP3_SEEK_TABLE *seek_table = NULL;
target_time = ((cur_mp3_info->playtime + move_time)<0)?0:(cur_mp3_info->playtime + move_time);
target_time = (target_time>cur_mp3_info->totaltime)?cur_mp3_info->totaltime:target_time;
target_frame = cur_mp3_info->one_second_frame*target_time;
table_index = target_time/100;
table_pos = target_time%100;
seek_table_list = cur_mp3_info->seek_table_head.next;
while(table_index>0) {
seek_table_list = seek_table_list->next;
table_index--;
}
seek_table = list_entry((struct list_head *)seek_table_list,MP3_SEEK_TABLE,sub_table_list);
offset_seek = seek_table->sub_table[table_pos];
osal_fseek(cur_mp3_info->mp3_fp,offset_seek);
update_curmp3_playtime(target_time);
update_curmp3_playframe(target_frame);
cur_mp3_info->offset_seek = offset_seek;
_os_printf("**file pos:%x time:%d frame:%d**\n",offset_seek,cur_mp3_info->playtime,cur_mp3_info->play_frame);
}
uint32_t key_seek_callback(struct key_callback_list_s *callback_list,uint32_t keyvalue,uint32_t extern_value)
{
uint32 key_val = 0;
if(!cur_mp3_info)
return 0;
if(((keyvalue>>8) != AD_A) && ((keyvalue>>8) != AD_B))
return 0;
if(get_mp3_decode_status() == MP3_STOP) {
_os_printf("mp3 stop\n");
return 0;
}
key_val = (keyvalue & 0xff);
if((keyvalue>>8) == AD_A) {
if(key_val == KEY_EVENT_DOWN) {
os_sema_down(&seek_sema,5000);
set_mp3_seek(-cur_mp3_info->once_move_time);
}
else if((key_val == KEY_EVENT_LDOWN) || (key_val == KEY_EVENT_REPEAT)) {
set_mp3_seek(-cur_mp3_info->once_move_time);
}
else if((key_val == KEY_EVENT_SUP) || (key_val == KEY_EVENT_LUP)) {
cur_mp3_info->update_fops = 1;
os_sema_up(&seek_sema);
}
}
else if((keyvalue>>8) == AD_B) {
if(key_val == KEY_EVENT_DOWN) {
os_sema_down(&seek_sema,5000);
set_mp3_seek(cur_mp3_info->once_move_time);
}
else if((key_val == KEY_EVENT_LDOWN) || (key_val == KEY_EVENT_REPEAT)) {
set_mp3_seek(cur_mp3_info->once_move_time);
}
else if((key_val == KEY_EVENT_SUP) || (key_val == KEY_EVENT_LUP)) {
cur_mp3_info->update_fops = 1;
os_sema_up(&seek_sema);
}
}
return 1;
}
int32_t at_set_mp3_seek(const char *cmd, char *argv[], uint32_t argc)
{
int32_t seek_time = 0;
uint32_t forward_time = 0;
if(!cur_mp3_info)
return 0;
if(get_mp3_decode_status() == MP3_STOP) {
_os_printf("mp3 stop\n");
return 0;
}
if(argc < 1)
{
os_printf("%s %d,enter the seek\n",__FUNCTION__,argc);
return 0;
}
if(argv[0])
{
seek_time = os_atoi(argv[0]);
if(seek_time == 0)
return 1;
// forward_time = (seek_time<MAX_FORWARD_TIME)?seek_time:MAX_FORWARD_TIME;
forward_time = seek_time;
os_sema_down(&seek_sema,5000);
set_mp3_seek(forward_time);
cur_mp3_info->update_fops = 1;
os_sema_up(&seek_sema);
}
return 0;
}
int seektable_check(CUR_MP3_INFO *mp3_info)
{
int32_t ret = 0;
uint32_t read_buf[4] = {0};
uint32_t seek_table_len = 0;
uint32_t *cache_buf = NULL;
cache_buf = (uint32_t*)custom_malloc(sizeof(uint32_t)*100);
if(!cache_buf)
goto seektable_check_end;
osal_fread(read_buf, 4, 4, mp3_info->mp3_st_fp);
if((read_buf[0]==mp3_info->total_size) && (read_buf[1]==mp3_info->first_frame_offset)
&& (read_buf[2]==mp3_info->normal_frame_offset)) {
mp3_info->total_frame = read_buf[3];
seek_table_len = osal_fsize(mp3_info->mp3_st_fp) - sizeof(read_buf);
INIT_LIST_HEAD((struct list_head *)&mp3_info->seek_table_head);
while(seek_table_len) {
MP3_SEEK_TABLE *sub_seek_table = custom_zalloc_psram(sizeof(MP3_SEEK_TABLE));
list_add_tail((struct list_head *)&sub_seek_table->sub_table_list,(struct list_head *)&mp3_info->seek_table_head);
osal_fread((void*)cache_buf, 4, 100, mp3_info->mp3_st_fp);
os_memcpy(sub_seek_table->sub_table, cache_buf, sizeof(uint32_t)*100);
seek_table_len -= 100*4;
}
cur_mp3_info->totaltime = cur_mp3_info->total_frame * cur_mp3_info->samples / cur_mp3_info->samplingrate;
cur_mp3_info->once_move_time = (cur_mp3_info->totaltime%100)?(cur_mp3_info->totaltime/100+1):(cur_mp3_info->totaltime/100);
os_printf("total_frame:%d total_time:%d once_move_time:%d\n",cur_mp3_info->total_frame, cur_mp3_info->totaltime,cur_mp3_info->once_move_time);
cur_mp3_info->get_totaltime = 1;
ret = 1;
}
seektable_check_end:
if(cache_buf)
custom_free((void*)cache_buf);
osal_fclose(mp3_info->mp3_st_fp);
return ret;
}
void find_first_frame(void *fp)
{
uint8_t mp3_head[512];
uint8_t bitrate_index = 0;
uint8_t channel_mode = 0x11;
uint8_t padding = 0;
uint8_t layer_index = 0;
uint8_t mpeg_index = 0;
uint8_t samplingrate_index = 0;
int32_t bitrate = 0;
uint32_t offset = 0;
uint32_t first_frame_offset = 0;
uint32_t seek = 0;
uint32_t frame_len = 0;
if(!cur_mp3_info)
{
return;
}
osal_fread(mp3_head, 512, 1, fp);
if(os_strncmp(mp3_head+offset, "ID3", 3) == 0)
{
uint32_t ID3V2_len = (mp3_head[6]&0x7F)*0x200000+ (mp3_head[7]&0x7F)*0x4000 +
(mp3_head[8]&0x7F)*0x80 +(mp3_head[9]&0x7F);
offset += (ID3V2_len+10);
}
os_printf("ID3 offset:%x\n",offset);
osal_fseek(fp,offset);
seek = offset;
osal_fread(mp3_head,1,512,fp);
while(((mp3_head[offset-seek]<<8) | (mp3_head[offset-seek+1]&0xE0)) != 0xFFE0) {
offset++;
if((offset+1) > (seek+512)) {
osal_fseek(fp,offset);
osal_fread(mp3_head, 1, 512, fp);
seek = offset;
}
}
osal_fseek(fp,offset);
seek = offset;
osal_fread(mp3_head,1,512,fp);
cur_mp3_info->mp3_fp = fp;
first_frame_offset = offset;
// os_printf("\n***first frame offset:%x****\n",first_frame_offset);
cur_mp3_info->first_frame_offset = first_frame_offset;
layer_index = (mp3_head[first_frame_offset-seek+1]>>1)&0x3;
mpeg_index = (mp3_head[first_frame_offset-seek+1]>>3)&0x3;
samplingrate_index = (mp3_head[first_frame_offset-seek+2]>>2)&0x3;
cur_mp3_info->samplingrate = samplingrate_table[mpeg_index][samplingrate_index];
cur_mp3_info->samples = samples_table[mpeg_index][layer_index];
channel_mode = (mp3_head[first_frame_offset-seek+3]>>6)&0x3;
if(mpeg_index == 3) { /*MPEG 1*/
switch(layer_index) {
case 0:break;
case 1:cur_mp3_info->bitrate_table_index = 2;break; /*layer III*/
case 2:cur_mp3_info->bitrate_table_index = 1;break; /*layer II*/
case 3:cur_mp3_info->bitrate_table_index = 0;break; /*layer I*/
default:break;
}
}
else if((mpeg_index == 0) || (mpeg_index == 2)) { /*MPEG 2、MPEG2.5*/
switch(layer_index) {
case 0:break;
case 1:cur_mp3_info->bitrate_table_index = 4;break;
case 2:cur_mp3_info->bitrate_table_index = 4;break;
case 3:cur_mp3_info->bitrate_table_index = 3;break;
default:break;
}
}
bitrate_index = (mp3_head[first_frame_offset-seek+2]>>4)&0xf;
bitrate = bitrate_table[cur_mp3_info->bitrate_table_index][bitrate_index];
if(layer_index == 3)
cur_mp3_info->padding_mul = 4;
else if((layer_index == 1) || (layer_index == 2))
cur_mp3_info->padding_mul = 1;
padding = ((mp3_head[first_frame_offset-seek+2]>>1)&0x1) * cur_mp3_info->padding_mul;
frame_len = cur_mp3_info->samples/8*bitrate/cur_mp3_info->samplingrate + padding;
os_printf("first frame samples:%d samplingrate:%d channel_mode:%d bitrate:%d frame_len:%d\n",
cur_mp3_info->samples,cur_mp3_info->samplingrate,channel_mode,bitrate,frame_len);
cur_mp3_info->normal_frame_offset = cur_mp3_info->first_frame_offset+frame_len;
cur_mp3_info->one_second_frame = cur_mp3_info->samplingrate/cur_mp3_info->samples;
#if MP3_SAVE_INFO
int32_t ret = 0;
DIR st_dir;
os_sema_init(&seek_sema, 1);
if(!key_seek_list)
key_seek_list = add_keycallback(key_seek_callback, NULL);
os_printf("one_second_frame:%d",cur_mp3_info->one_second_frame);
ret = f_opendir(&st_dir,"0:/MP3_SEEK");
if(ret == FR_OK) {
cur_mp3_info->mp3_st_fp = osal_fopen(cur_mp3_info->mp3_st_filename, "r");
if(cur_mp3_info->mp3_st_fp) {
if(seektable_check(cur_mp3_info)) {
return;
}
osal_fclose(cur_mp3_info->mp3_st_fp);
}
}
else{
ret = f_mkdir("0:/MP3_SEEK");
}
get_curmp3_totaltime_ergodic(fp, first_frame_offset);
cur_mp3_info->mp3_st_fp = osal_fopen(cur_mp3_info->mp3_st_filename, "wb");
if(cur_mp3_info->mp3_st_fp) {
osal_fwrite(cur_mp3_info, 4, 4, cur_mp3_info->mp3_st_fp);
struct list_head *seek_table_list = cur_mp3_info->seek_table_head.next;
struct list_head *seek_table_head = &cur_mp3_info->seek_table_head;
while(seek_table_list != seek_table_head) {
MP3_SEEK_TABLE *seek_table = list_entry((struct list_head *)seek_table_list,MP3_SEEK_TABLE,sub_table_list);
osal_fwrite(seek_table->sub_table, 100, 4, cur_mp3_info->mp3_st_fp);
seek_table_list = seek_table_list->next;
}
osal_fclose(cur_mp3_info->mp3_st_fp);
}
#endif
}
uint32_t get_curmp3_songtime(uint32_t brate)
{
if(!cur_mp3_info) {
return 0;
}
if(cur_mp3_info->get_totaltime == 1) {
return cur_mp3_info->totaltime;
}
return 0;
}
void clear_curmp3_info(void)
{
if(cur_mp3_info) {
MP3_DECODE_FREE(cur_mp3_info);
cur_mp3_info = NULL;
}
#if MP3_SAVE_INFO
if(key_seek_list) {
remove_keycallback(key_seek_list);
key_seek_list = NULL;
}
struct list_head *list_n = (struct list_head *)&cur_mp3_info->seek_table_head;
struct list_head *head = (struct list_head *)&cur_mp3_info->seek_table_head;
MP3_SEEK_TABLE *seek_table = NULL;
while(list_n->next != head) {
list_n = list_n->next;
seek_table = list_entry((struct list_head *)list_n,MP3_SEEK_TABLE,sub_table_list);
MP3_DECODE_FREE(seek_table);
}
os_sema_del(&seek_sema);
#endif
}
+46
View File
@@ -0,0 +1,46 @@
#ifndef _MP3_GETINFO_H_
#define _MP3_GETINFO_H_
#include "basic_include.h"
typedef struct {
struct list_head sub_table_list;
uint32_t sub_table[100];
}MP3_SEEK_TABLE;
typedef struct {
uint32_t total_size;
uint32_t first_frame_offset;
uint32_t normal_frame_offset;
uint32_t total_frame;
uint32_t once_move_time;
uint32_t offset_seek;
uint32_t samplingrate;
uint32_t one_second_frame;
int32_t playtime;
int32_t play_frame;
uint16_t totaltime;
uint16_t samples;
uint8_t get_totaltime;
uint8_t update_fops;
uint8_t bitrate_table_index;
uint8_t padding_mul;
void *mp3_fp;
void *mp3_st_fp;
char mp3_st_filename[50];
struct list_head seek_table_head;
}CUR_MP3_INFO;
CUR_MP3_INFO *cur_mp3_info;
struct os_semaphore seek_sema;
uint32_t get_curmp3_size(uint32_t s);
void curmp3_info_init(char *mp3_filename);
void find_first_frame(void *fp);
void clear_curmp3_info(void);
#endif