移动了文件位置
This commit is contained in:
268
middleware/minimp3/minimp3.c
Normal file
268
middleware/minimp3/minimp3.c
Normal file
@@ -0,0 +1,268 @@
|
||||
/**
|
||||
* @file minimp3.c
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "projdefs.h"
|
||||
#include "portable.h"
|
||||
|
||||
#ifdef __FATFS_SUPPORTED__
|
||||
#include "ff.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
the follow 3 MACROS must be defined before incude minimp3.h,
|
||||
and the these MACROS can be defined only one time
|
||||
*/
|
||||
#define MINIMP3_IMPLEMENTATION
|
||||
#define MINIMP3_NO_SIMD
|
||||
#define MINIMP3_ALLOW_MONO_STEREO_TRANSITION
|
||||
#define MINIMP3_NO_STDIO
|
||||
#include "mp3.h"
|
||||
|
||||
#define SAMPLE_PER_FRAME 1152 /* the max samples of per frame */
|
||||
|
||||
static inline size_t mp3_read_cb(void *buff, size_t nbyte, void *user_data)
|
||||
{
|
||||
size_t ret = 0;
|
||||
mp3_dec_context *context = (mp3_dec_context *)user_data;
|
||||
|
||||
#ifdef __FATFS_SUPPORTED__
|
||||
if (context->src_type == MP3_IO_SOURCE_DISK) {
|
||||
uint8_t *temp_buff = pvPortMallocAligned(nbyte, 32);
|
||||
/*
|
||||
wrap the f_read here, a direct read may failed, because
|
||||
the decoder may read at any address not aligned with 32
|
||||
*/
|
||||
f_read((FIL *)context->bit_stream, temp_buff, nbyte, &ret);
|
||||
memcpy(buff, temp_buff, ret);
|
||||
vPortFree(temp_buff);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
if (context->bits_offset + nbyte > context->bit_size) {
|
||||
nbyte = context->bit_size - context->bits_offset;
|
||||
}
|
||||
|
||||
memcpy(buff, (uint8_t *)context->bit_stream + context->bits_offset,
|
||||
nbyte);
|
||||
context->bits_offset += nbyte;
|
||||
ret = nbyte;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int mp3_seek_cb(uint64_t position, void *user_data)
|
||||
{
|
||||
int ret = 0;
|
||||
mp3_dec_context *context = (mp3_dec_context *)user_data;
|
||||
|
||||
if (position > context->bit_size) {
|
||||
position = context->bit_size;
|
||||
}
|
||||
|
||||
#ifdef __FATFS_SUPPORTED__
|
||||
if (context->src_type == MP3_IO_SOURCE_DISK) {
|
||||
ret = f_lseek((FIL *)context->bit_stream, position);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
context->bits_offset = position;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
mp3_dec_context *mp3_init_dec(io_source_type type, void *data, uint32_t size)
|
||||
{
|
||||
mp3_dec_context *context = NULL;
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
context = (mp3_dec_context *)pvPortMalloc(sizeof(mp3_dec_context));
|
||||
if (!context)
|
||||
return NULL;
|
||||
|
||||
memset(context, 0x00, sizeof(mp3_dec_context));
|
||||
context->src_type = type;
|
||||
context->bits_offset = 0;
|
||||
context->repeat_count = 0;
|
||||
|
||||
if (context->src_type == MP3_IO_SOURCE_C_ARRAY) {
|
||||
// input data is stored in the ram already
|
||||
context->bit_stream = (uint8_t *)data;
|
||||
context->bit_size = size;
|
||||
}
|
||||
#ifdef __FATFS_SUPPORTED__
|
||||
else if (context->src_type == MP3_IO_SOURCE_DISK_PRELOAD) {
|
||||
size_t count = 0;
|
||||
FIL fp = {0};
|
||||
|
||||
FRESULT rc = FR_OK;
|
||||
char file_name[128] = {0};
|
||||
|
||||
strcpy(file_name, (char *)data);
|
||||
|
||||
rc = f_open(&fp, file_name, FA_READ);
|
||||
if (rc != FR_OK) {
|
||||
vPortFree(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->bit_size = f_size(&fp);
|
||||
context->bit_stream =
|
||||
(uint8_t *)pvPortMallocAligned(context->bit_size, 32);
|
||||
f_read(&fp, context->bit_stream, context->bit_size, &count);
|
||||
f_close(&fp);
|
||||
|
||||
if (count != context->bit_size) {
|
||||
vPortFree(context->bit_stream);
|
||||
vPortFree(context);
|
||||
return NULL;
|
||||
}
|
||||
} else if (context->src_type == MP3_IO_SOURCE_DISK) {
|
||||
|
||||
FRESULT rc = FR_OK;
|
||||
char file_name[128] = {0};
|
||||
strcpy(file_name, (char *)data);
|
||||
|
||||
context->bit_stream = pvPortMalloc(sizeof(FIL));
|
||||
rc = f_open((FIL *)context->bit_stream, file_name, FA_READ);
|
||||
if (rc != FR_OK) {
|
||||
vPortFree(context->bit_stream);
|
||||
vPortFree(context);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
context->bit_size = f_size((FIL *)context->bit_stream);
|
||||
}
|
||||
#endif
|
||||
return context;
|
||||
}
|
||||
|
||||
int mp3_open_dec(mp3_dec_context *context)
|
||||
{
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
context->io_context.read = mp3_read_cb;
|
||||
context->io_context.seek = mp3_seek_cb;
|
||||
context->io_context.read_data = context;
|
||||
context->io_context.seek_data = context;
|
||||
|
||||
mp3dec_ex_open_cb(&context->dec_context, &context->io_context,
|
||||
MP3D_SEEK_TO_SAMPLE);
|
||||
|
||||
context->duration =
|
||||
(context->dec_context.samples * 1000) /
|
||||
(context->dec_context.info.channels * context->dec_context.info.hz);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp3_close_dec(mp3_dec_context *context)
|
||||
{
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
#ifdef __FATFS_SUPPORTED__
|
||||
if (context->src_type == MP3_IO_SOURCE_DISK) {
|
||||
f_close((FIL *)context->bit_stream);
|
||||
vPortFree(context->bit_stream);
|
||||
} else if (context->src_type == MP3_IO_SOURCE_DISK_PRELOAD)
|
||||
vPortFree(context->bit_stream);
|
||||
#endif
|
||||
|
||||
mp3dec_ex_close(&context->dec_context);
|
||||
vPortFree(context);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp3_dec_get_frame_info(mp3_dec_context *context, mp3_frame_info *frame_info)
|
||||
{
|
||||
if (!context || !frame_info)
|
||||
return -1;
|
||||
|
||||
frame_info->channels = context->dec_context.info.channels;
|
||||
frame_info->bitrate = context->dec_context.info.bitrate_kbps;
|
||||
frame_info->samples = frame_info->channels * SAMPLE_PER_FRAME;
|
||||
frame_info->duration = context->duration;
|
||||
frame_info->samplerate = context->dec_context.info.hz;
|
||||
|
||||
#ifndef MINIMP3_FLOAT_OUTPUT
|
||||
frame_info->format = MP3_SAMPLE_FMT_S16;
|
||||
#else
|
||||
frame_info->format = MP3_SAMPLE_FMT_FLT;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mp3_dec_seek_frame(mp3_dec_context *context, uint64_t position)
|
||||
{
|
||||
int ret = 0;
|
||||
uint64_t sample_position = 0;
|
||||
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
// convert timestamp to sample position
|
||||
sample_position =
|
||||
context->dec_context.samples * position / context->duration;
|
||||
ret = mp3dec_ex_seek(&context->dec_context, sample_position);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mp3_dec_set_repeat_count(mp3_dec_context *context, uint32_t count)
|
||||
{
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
context->repeat_count = count;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp3_dec_rewind(mp3_dec_context *context)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
// check whether the end of file is reached
|
||||
if (!context ||
|
||||
(context->dec_context.cur_sample < context->dec_context.samples))
|
||||
return -1;
|
||||
// if repeat count is not zero, rewind count times
|
||||
if (context->repeat_count && --context->repeat_count > 0) {
|
||||
ret = mp3_dec_seek_frame(context, 0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mp3_dec_receive_frame(mp3_dec_context *context, mp3d_sample_t *buf,
|
||||
uint32_t samples)
|
||||
{
|
||||
size_t readed = 0;
|
||||
|
||||
if (!context)
|
||||
return -1;
|
||||
|
||||
readed = mp3dec_ex_read(&context->dec_context, buf, samples);
|
||||
mp3_dec_rewind(context);
|
||||
|
||||
return readed;
|
||||
}
|
||||
2203
middleware/minimp3/minimp3.h
Normal file
2203
middleware/minimp3/minimp3.h
Normal file
File diff suppressed because it is too large
Load Diff
1485
middleware/minimp3/minimp3_ex.h
Normal file
1485
middleware/minimp3/minimp3_ex.h
Normal file
File diff suppressed because it is too large
Load Diff
73
middleware/minimp3/mp3.h
Normal file
73
middleware/minimp3/mp3.h
Normal file
@@ -0,0 +1,73 @@
|
||||
/**
|
||||
* @file mp3.h
|
||||
*
|
||||
* Copyright (c) 2020 Semidrive Semiconductor.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Revision History:
|
||||
* -----------------
|
||||
*/
|
||||
#ifndef MP3_H
|
||||
#define MP3_H
|
||||
|
||||
#include <limits.h>
|
||||
#include "minimp3_ex.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DEC_COUNT_INFINITE UINT_MAX
|
||||
|
||||
typedef enum {
|
||||
MP3_IO_SOURCE_C_ARRAY = 0, /* the input stream is in the ram already*/
|
||||
MP3_IO_SOURCE_DISK_PRELOAD, /* the input stream is in file system, but we
|
||||
will load the whole file to ram once time */
|
||||
MP3_IO_SOURCE_DISK /* the input stream is in file system, and we will load
|
||||
the file when needed */
|
||||
} io_source_type;
|
||||
|
||||
typedef enum {
|
||||
MP3_SAMPLE_FMT_S16 = 0, /* signed 16 bits */
|
||||
MP3_SAMPLE_FMT_FLT, /* float */
|
||||
} sample_format;
|
||||
|
||||
typedef struct {
|
||||
io_source_type src_type;
|
||||
void *bit_stream; /* input bs buffer*/
|
||||
uint32_t bit_size;
|
||||
uint32_t bits_offset;
|
||||
uint64_t duration; /* duration with ms */
|
||||
uint32_t repeat_count; /* repeat count */
|
||||
|
||||
mp3dec_ex_t dec_context;
|
||||
mp3dec_io_t io_context;
|
||||
} mp3_dec_context;
|
||||
|
||||
typedef struct {
|
||||
uint8_t channels;
|
||||
uint32_t bitrate; /* kbps */
|
||||
uint32_t samples; /* samples per frame*/
|
||||
uint64_t duration; /* duration with ms */
|
||||
uint32_t samplerate; /* sample rate */
|
||||
|
||||
sample_format format; /* sample format */
|
||||
} mp3_frame_info;
|
||||
|
||||
int mp3_open_dec(mp3_dec_context *context);
|
||||
int mp3_close_dec(mp3_dec_context *context);
|
||||
int mp3_dec_seek_frame(mp3_dec_context *context, uint64_t position);
|
||||
mp3_dec_context *mp3_init_dec(io_source_type type, void *data, uint32_t size);
|
||||
int mp3_dec_set_repeat_count(mp3_dec_context *context, uint32_t count);
|
||||
int mp3_dec_get_frame_info(mp3_dec_context *context,
|
||||
mp3_frame_info *frame_info);
|
||||
int mp3_dec_receive_frame(mp3_dec_context *context, mp3d_sample_t *buf,
|
||||
uint32_t samples);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*MP3_H*/
|
||||
Reference in New Issue
Block a user