Skip to content

Commit

Permalink
update:改进一下audio record
Browse files Browse the repository at this point in the history
  • Loading branch information
allewalker committed Apr 28, 2024
1 parent acde7a4 commit 9a594f9
Show file tree
Hide file tree
Showing 3 changed files with 130 additions and 99 deletions.
203 changes: 110 additions & 93 deletions components/multimedia/luat_lib_multimedia_audio.c
Expand Up @@ -100,7 +100,8 @@ static int l_audio_start_raw(lua_State *L){
#include "interf_dec.h"
#endif
#include "luat_fs.h"
#define RECORD_ONCE_LEN 10 //单声道 8K录音单次10个编码块,总共200ms回调 320B 20ms,amr编码要求,20ms一个块
#define RECORD_ONCE_LEN 5


#ifdef LUAT_SUPPORT_AMR
static void record_encode_amr(uint8_t *data, uint32_t len){
Expand All @@ -109,8 +110,8 @@ static void record_encode_amr(uint8_t *data, uint32_t len){
uint32_t total_len = len >> 1;
uint32_t done_len = 0;
uint8_t out_len;

while ((total_len - done_len) >= 160){
uint32_t pcm_len = (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB)?160:320;
while ((total_len - done_len) >= pcm_len){
#ifdef LUAT_USE_INTER_AMR
luat_audio_inter_amr_coder_encode(g_s_record.encoder_handler, &pcm[done_len], outbuf,&out_len);
#else
Expand All @@ -121,59 +122,91 @@ static void record_encode_amr(uint8_t *data, uint32_t len){
}else{
luat_fs_fwrite(outbuf, out_len, 1, g_s_record.fd);
}
done_len += 160;
done_len += pcm_len;
}
}

static void record_stop_encode_amr(void){
luat_audio_record_stop(g_s_record.multimedia_id);
luat_audio_pm_request(g_s_record.multimedia_id, LUAT_AUDIO_PM_STANDBY);
if (g_s_record.fd){
#ifdef LUAT_USE_INTER_AMR
luat_audio_inter_amr_coder_deinit(g_s_record.encoder_handler);
luat_audio_inter_amr_coder_deinit(g_s_record.encoder_handler);
#else
Encoder_Interface_exit(g_s_record.encoder_handler);
Encoder_Interface_exit(g_s_record.encoder_handler);
#endif
g_s_record.encoder_handler = NULL;
luat_fs_fclose(g_s_record.fd);
g_s_record.fd = NULL;
}
luat_i2s_conf_t *i2s = luat_i2s_get_config(g_s_record.multimedia_id);
memcpy(i2s, &g_s_record.i2s_back, sizeof(luat_i2s_conf_t));
g_s_record.encoder_handler = NULL;
}
#endif

int record_cb(uint8_t id ,luat_i2s_event_t event, uint8_t *rx_data, uint32_t rx_len, void *param)
static void record_stop(uint8_t *data, uint32_t len);
static void record_run(uint8_t *data, uint32_t len)
{
rtos_msg_t msg = {0};
if (g_s_record.fd){
#ifdef LUAT_SUPPORT_AMR
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB||g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
record_encode_amr(data, len);
}
else
#endif
{
luat_fs_fwrite(data, len, 1, g_s_record.fd);
}
}else{
memcpy(g_s_record.record_buffer[g_s_record.record_buffer_index]->addr + g_s_record.record_buffer[g_s_record.record_buffer_index]->used, data, len);
g_s_record.record_buffer[g_s_record.record_buffer_index]->used += len;
if (g_s_record.record_buffer[g_s_record.record_buffer_index]->used >= g_s_record.record_buffer[g_s_record.record_buffer_index]->len)
{
msg.handler = l_multimedia_raw_handler;
msg.arg1 = LUAT_MULTIMEDIA_CB_RECORD_DATA;
msg.arg2 = g_s_record.multimedia_id;
msg.ptr = g_s_record.record_buffer_index;
luat_msgbus_put(&msg, 1);
g_s_record.record_buffer_index = !g_s_record.record_buffer_index;
g_s_record.record_buffer[g_s_record.record_buffer_index]->used = 0;
}


}
if (g_s_record.record_time)
{
g_s_record.record_time_tmp++;
if (g_s_record.record_time_tmp >= (g_s_record.record_time * 10) )
{
record_stop(NULL, 0);
}
}
}

static int record_cb(uint8_t id ,luat_i2s_event_t event, uint8_t *rx_data, uint32_t rx_len, void *param)
{
switch(event)
{
case LUAT_I2S_EVENT_RX_DONE:
luat_rtos_event_send(g_s_record.task_handle, LUAT_I2S_EVENT_RX_DONE, (uint32_t)rx_data, rx_len, 0, 0);
break;
case LUAT_I2S_EVENT_TRANSFER_DONE:
luat_audio_run_callback_in_task(record_run, rx_data, rx_len);
break;
default:
break;
}
return 0;
}

static void record_task(void *arg)
{
luat_event_t event;
rtos_msg_t msg = {0};
msg.handler = l_multimedia_raw_handler;
static void record_start(uint8_t *data, uint32_t len){
luat_i2s_conf_t *i2s = luat_i2s_get_config(g_s_record.multimedia_id);
memcpy(&g_s_record.i2s_back, i2s, sizeof(luat_i2s_conf_t));
i2s->cb_rx_len = g_s_record.record_buffer[g_s_record.record_buffer_index]->len;
g_s_record.bak_cb_rx_len = i2s->cb_rx_len;
g_s_record.bak_is_full_duplex = i2s->is_full_duplex;
g_s_record.bak_sample_rate = i2s->sample_rate;
g_s_record.bak_luat_i2s_event_callback = i2s->luat_i2s_event_callback;


i2s->is_full_duplex = 1;
i2s->luat_i2s_event_callback = record_cb;
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB){
i2s->cb_rx_len = 320 * RECORD_ONCE_LEN;
i2s->sample_rate = 8000;
}else if(g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
i2s->cb_rx_len = 640 * RECORD_ONCE_LEN;
i2s->sample_rate = 16000;
}

//需要保存文件,看情况打开编码功能
if (g_s_record.fd){
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB||g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
#ifdef LUAT_SUPPORT_AMR
Expand All @@ -186,57 +219,54 @@ static void record_task(void *arg)
#endif
}
}
luat_audio_record_and_play(g_s_record.multimedia_id, i2s->sample_rate, NULL, 3200, 2);
}

luat_audio_record_and_play(g_s_record.multimedia_id, i2s->sample_rate, NULL, 3200, 2);

while (1)
{
luat_rtos_event_recv(g_s_record.task_handle, 0, &event, NULL, LUAT_WAIT_FOREVER);
switch(event.id){
case LUAT_I2S_EVENT_RX_DONE:
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB||g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
static void record_stop(uint8_t *data, uint32_t len){
rtos_msg_t msg = {0};
//关闭audio硬件功能
luat_audio_record_stop(g_s_record.multimedia_id);
luat_audio_pm_request(g_s_record.multimedia_id, LUAT_AUDIO_PM_STANDBY);
//还原参数
luat_i2s_conf_t *i2s = luat_i2s_get_config(g_s_record.multimedia_id);
i2s->cb_rx_len = g_s_record.bak_cb_rx_len;
i2s->is_full_duplex = g_s_record.bak_is_full_duplex;
i2s->sample_rate = g_s_record.bak_sample_rate;
i2s->luat_i2s_event_callback = g_s_record.bak_luat_i2s_event_callback;
//录音存文件时,看情况关闭编码功能
if (g_s_record.fd) {
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB||g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
#ifdef LUAT_SUPPORT_AMR
if (g_s_record.fd){
record_encode_amr((uint8_t *)event.param1, event.param2);
}else{
memcpy(g_s_record.record_buffer[g_s_record.record_buffer_index]->addr, (uint8_t *)event.param1, event.param2);
g_s_record.record_buffer[g_s_record.record_buffer_index]->used = event.param2;

msg.arg1 = LUAT_MULTIMEDIA_CB_RECORD_DATA;
msg.arg2 = g_s_record.multimedia_id;
msg.ptr = g_s_record.record_buffer_index;
luat_msgbus_put(&msg, 1);
g_s_record.record_buffer_index = !g_s_record.record_buffer_index;
}
g_s_record.record_time_tmp++;
if (g_s_record.record_time_tmp >= (g_s_record.record_time * (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB?5:10) )) //8K 5秒 16K 10秒
{
record_stop_encode_amr();
msg.arg1 = LUAT_MULTIMEDIA_CB_RECORD_DONE;
msg.arg2 = g_s_record.multimedia_id;
luat_msgbus_put(&msg, 1);
goto end;
}
record_stop_encode_amr();
#endif
}
break;
}
}
end:
g_s_record.record_time_tmp = 0;
g_s_record.is_run = 0;
g_s_record.record_buffer_index = 0;
luat_rtos_task_delete(g_s_record.task_handle);
}else if(g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_PCM){
// 不需要特殊处理
}else{
LLOGE("not support %d", g_s_record.type);
}
luat_fs_fclose(g_s_record.fd);
g_s_record.fd = NULL;
}
//通知luat task清除zbuff数据,并回调用户
msg.handler = l_multimedia_raw_handler;
msg.arg1 = LUAT_MULTIMEDIA_CB_RECORD_DONE;
msg.arg2 = g_s_record.multimedia_id;
g_s_record.record_time_tmp = 0;
g_s_record.is_run = 0;
g_s_record.record_buffer_index = 0;
luat_msgbus_put(&msg, 1);
}

/**
录音
@api audio.record(id, record_type, record_time, amr_quailty, path)
@int id 多媒体播放通道号
@int record_type 录音文件音频格式,支持 audio.AMR audio.PCM
@int record_type 录音音频格式,支持 audio.AMR audio.PCM (部分平台支持audio.AMR_WB)
@int record_time 录制时长 单位秒
@int amr_quailty 质量,audio.AMR下有效
@string path 录音文件路径,可选,不指定则不保存,可在audio.on回调函数中处理原始PCM数据
@int record_callback_time 不指定录音文件路径时,单次录音回调时长,单位是100ms。默认1,既100ms
@return boolean 成功返回true,否则返回false
@usage
err,info = audio.record(id, type, record_time, quailty, path)
Expand All @@ -248,6 +278,7 @@ static int l_audio_record(lua_State *L){
g_s_record.type = luaL_optinteger(L, 2,LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB);
g_s_record.record_time = luaL_checkinteger(L, 3);
g_s_record.quailty = luaL_optinteger(L, 4, 0);

if (lua_isstring(L, 5)) {
const char *path = luaL_checklstring(L, 5, &len);
luat_fs_remove(path);
Expand All @@ -261,32 +292,34 @@ static int l_audio_record(lua_State *L){
LLOGE("record is running");
return 0;
}

record_buffer_len = luaL_optinteger(L, 6, 1);
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB||g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
#ifdef LUAT_SUPPORT_AMR
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB){
record_buffer_len = 320 * RECORD_ONCE_LEN;
record_buffer_len *= 320 * RECORD_ONCE_LEN;
}else if(g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
#ifdef LUAT_USE_INTER_AMR
record_buffer_len = 640 * RECORD_ONCE_LEN;
record_buffer_len *= 640 * RECORD_ONCE_LEN;
#else
LLOGE("not support 16k");
return 0;
#endif
}

g_s_record.record_buffer[0] = lua_newuserdata(L, sizeof(luat_zbuff_t));
g_s_record.record_buffer[0]->type = LUAT_HEAP_SRAM;
g_s_record.record_buffer[0]->type = LUAT_HEAP_AUTO;
g_s_record.record_buffer[0]->len = record_buffer_len;
g_s_record.record_buffer[0]->addr = luat_heap_opt_malloc(LUAT_HEAP_SRAM,g_s_record.record_buffer[0]->len);
g_s_record.record_buffer[0]->used = 0;
g_s_record.record_buffer[0]->addr = luat_heap_opt_malloc(LUAT_HEAP_AUTO,g_s_record.record_buffer[0]->len);
lua_pushlightuserdata(L, g_s_record.record_buffer[0]);
g_s_record.zbuff_ref[0] = luaL_ref(L, LUA_REGISTRYINDEX);
lua_pop(L, 1);

g_s_record.record_buffer[1] = lua_newuserdata(L, sizeof(luat_zbuff_t));
g_s_record.record_buffer[1]->type = LUAT_HEAP_SRAM;
g_s_record.record_buffer[1]->type = LUAT_HEAP_AUTO;
g_s_record.record_buffer[0]->used = 0;
g_s_record.record_buffer[1]->len = record_buffer_len;
g_s_record.record_buffer[1]->addr = luat_heap_opt_malloc(LUAT_HEAP_SRAM,g_s_record.record_buffer[1]->len);
g_s_record.record_buffer[1]->addr = luat_heap_opt_malloc(LUAT_HEAP_AUTO,g_s_record.record_buffer[1]->len);
lua_pushlightuserdata(L, g_s_record.record_buffer[1]);
g_s_record.zbuff_ref[1] = luaL_ref(L, LUA_REGISTRYINDEX);
lua_pop(L, 1);
Expand All @@ -301,9 +334,10 @@ static int l_audio_record(lua_State *L){
LLOGE("not support %d", g_s_record.type);
return 0;
}

luat_rtos_task_create(&g_s_record.task_handle, 8*1024, 100, "record_task", record_task, NULL, 0);
g_s_record.is_run = 1;
luat_audio_run_callback_in_task(record_start, NULL, 0);
// luat_rtos_task_create(&g_s_record.task_handle, 8*1024, 100, "record_task", record_task, NULL, 0);

lua_pushboolean(L, 1);
return 1;
}
Expand All @@ -317,26 +351,9 @@ static int l_audio_record(lua_State *L){
audio.recordStop(0)
*/
static int l_audio_record_stop(lua_State *L) {
rtos_msg_t msg = {0};
msg.handler = l_multimedia_raw_handler;

if (g_s_record.is_run) {
if (g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_NB||g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_AMR_WB){
#ifdef LUAT_SUPPORT_AMR
record_stop_encode_amr();
#endif
}else if(g_s_record.type==LUAT_MULTIMEDIA_DATA_TYPE_PCM){
// 不需要特殊处理
}else{
LLOGE("not support %d", g_s_record.type);
return 0;
}
msg.arg1 = LUAT_MULTIMEDIA_CB_RECORD_DONE;
msg.arg2 = g_s_record.multimedia_id;
luat_msgbus_put(&msg, 1);
g_s_record.record_time_tmp = 0;
g_s_record.is_run = 0;
g_s_record.record_buffer_index = 0;
luat_rtos_task_delete(g_s_record.task_handle);
luat_audio_run_callback_in_task(record_stop, NULL, 0);
lua_pushboolean(L, 1);
return 1;
} else {
Expand Down
5 changes: 4 additions & 1 deletion components/multimedia/luat_multimedia_audio.c
Expand Up @@ -407,5 +407,8 @@ LUAT_WEAK void luat_audio_power_keep_ctrl_by_bsp(uint8_t on_off)
;
}


LUAT_WEAK void luat_audio_run_callback_in_task(void *api, uint8_t *data, uint32_t len)
{
;
}

21 changes: 16 additions & 5 deletions luat/include/luat_audio.h
Expand Up @@ -76,20 +76,22 @@ typedef enum{
#ifdef LUAT_USE_RECORD
#include "luat_i2s.h"
typedef struct{
luat_rtos_task_handle task_handle;
// luat_rtos_task_handle task_handle;
FILE* fd;
luat_i2s_conf_t i2s_back;
uint8_t multimedia_id;
uint8_t quailty;
uint8_t type;
uint8_t is_run;
uint16_t record_time;
uint16_t record_time_tmp;
uint32_t record_time;
uint32_t record_time_tmp;
void* encoder_handler;
luat_zbuff_t * record_buffer[2];
int record_buffer_index;
int zbuff_ref[2];

uint32_t bak_sample_rate; // i2s采样率
uint32_t bak_cb_rx_len; // 接收触发回调数据长度
int (*bak_luat_i2s_event_callback)(uint8_t id ,luat_i2s_event_t event, uint8_t *rx_data, uint32_t rx_len, void *param); // i2s回调函数
uint8_t bak_is_full_duplex; // 是否全双工
}luat_record_ctrl_t;

#endif
Expand Down Expand Up @@ -369,6 +371,15 @@ void luat_audio_power(uint8_t multimedia_id,uint8_t on);
*/
void luat_audio_power_keep_ctrl_by_bsp(uint8_t on_off);

/**
* @brief 把api投放到audio task运行
*
* @param api 需要运行的api
* @param data api输入数据
* @param len api输入数据长度
*/
void luat_audio_run_callback_in_task(void *api, uint8_t *data, uint32_t len);

void *luat_audio_inter_amr_coder_init(uint8_t is_wb, uint8_t quality);
int luat_audio_inter_amr_coder_encode(void *handle, const uint16_t *pcm_buf, uint8_t *amr_buf, uint8_t *amr_len);
int luat_audio_inter_amr_coder_decode(void *handle, uint16_t *pcm_buf, const uint8_t *amr_buf, uint8_t *amr_len);
Expand Down

0 comments on commit 9a594f9

Please sign in to comment.