Files
TAIXIN/sdk/app/audio_media_ctrl/wave/wave_encode.c

256 lines
8.5 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "basic_include.h"
#include "csi_kernel.h"
#include "lib/multimedia/msi.h"
#include "lib/multimedia/framebuff.h"
#include "osal_file.h"
#include "wave_code.h"
#define MAX_WAVE_ENCODE_RXBUF 4
struct wave_encode_struct {
struct os_event event;
struct msi *msi;
struct msi *src_msi;
void *task_hdl;
void *wave_fp;
uint8_t destroy_self;
uint8_t next_status;
uint8_t current_status;
uint32_t samplerate;
uint32_t data_size;
TYPE_WAVE_HEAD wave_head;
};
const unsigned char wav_header[] = {
'R', 'I', 'F', 'F', // "RIFF" 标志
0, 0, 0, 0, // 文件长度
'W', 'A', 'V', 'E', // "WAVE" 标志
'f', 'm', 't', ' ', // "fmt" 标志
16, 0, 0, 0, // 过渡字节(不定)
0x01, 0x00, // 格式类别
0x01, 0x00, // 声道数
0, 0, 0, 0, // 采样率
0, 0, 0, 0, // 位速
0x01, 0x00, // 一个采样多声道数据块大小
0x10, 0x00, // 一个采样占的 bit 数
'd', 'a', 't', 'a', // 数据标记符data
0, 0, 0, 0 // 语音数据的长度比文件长度小42一般。这个是计算音频播放时长的关键参数~
};
static void wave_encode_thread(void *d)
{
uint8_t *data = NULL;
uint32_t data_len = 0;
struct wave_encode_struct *s = (struct wave_encode_struct *)d;
struct framebuff *frame_buf = NULL;
s->msi->enable = 1;
msi_get(s->msi);
while(1)
{
frame_buf = msi_get_fb(s->msi, 0);
if(frame_buf)
{
if(s->next_status == AUCODEC_PAUSE)
s->current_status = AUCODEC_PAUSE;
else {
s->current_status = AUCODEC_RUN;
data = frame_buf->data;
data_len = frame_buf->len;
osal_fwrite(data, 2, data_len/2, s->wave_fp);
s->data_size += data_len;
}
msi_delete_fb(s->msi, frame_buf);
WAVE_DEBUG("wave encode delete framebuff:%p,len:%d,\r\n",frame_buf,frame_buf->len);
frame_buf = NULL;
}
else
os_sleep_ms(1);
if(s->next_status == AUCODEC_EXIT) {
s->current_status = AUCODEC_EXIT;
s->wave_head.riff_chunk.ChunkSize = s->data_size + sizeof(TYPE_WAVE_HEAD) - 8;
s->wave_head.fmt_chunk.SampleRate = s->samplerate;
s->wave_head.fmt_chunk.ByteRate = s->samplerate*2;
s->wave_head.data_chunk.DataSize = s->data_size;
osal_fseek(s->wave_fp, 0);
osal_fwrite(&(s->wave_head), 1, sizeof(TYPE_WAVE_HEAD), s->wave_fp);
goto wave_encode_thread_end;
}
}
wave_encode_thread_end:
os_event_set(&s->event, coder_exit_event, NULL);
while((s->next_status != AUCODEC_EXIT) && (s->destroy_self == 0)) {
s->current_status = AUCODEC_END;
os_sleep_ms(5);
}
if(s->src_msi) {
msi_del_output(s->src_msi, NULL, s->msi->name);
s->src_msi = NULL;
}
if(s->next_status != AUCODEC_EXIT)
msi_destroy(s->msi);
msi_put(s->msi);
}
static int32_t wave_encode_msi_action(struct msi *msi, uint32_t cmd_id, uint32_t param1, uint32_t param2)
{
int32_t ret = RET_OK;
struct wave_encode_struct *wave_encode_s = (struct wave_encode_struct*)(msi->priv);
switch(cmd_id) {
case MSI_CMD_AUCODER:
{
ret = RET_ERR;
if(wave_encode_s) {
uint32_t cmd_self = (uint32_t)param1;
switch(cmd_self) {
case MSI_AUCODER_PAUSE:
{
if(wave_encode_s->current_status == AUCODEC_RUN) {
wave_encode_s->next_status = AUCODEC_PAUSE;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_CONTINUE:
{
if(wave_encode_s->current_status == AUCODEC_PAUSE) {
wave_encode_s->next_status = AUCODEC_RUN;
}
ret = RET_OK;
break;
}
case MSI_AUCODER_GET_STATUS:
{
*((uint32_t*)param2) = (uint32_t)(wave_encode_s->current_status);
ret = RET_OK;
break;
}
case MSI_AUCODER_SET_SRCMSI:
{
if(wave_encode_s->src_msi) {
msi_del_output(wave_encode_s->src_msi, NULL, msi->name);
}
wave_encode_s->src_msi = NULL;
ret = msi_add_output((struct msi*)param2, NULL, msi->name);
if(ret == RET_OK) {
wave_encode_s->src_msi = (struct msi*)param2;
}
break;
}
case MSI_AUCODER_DEINIT:
{
msi_destroy(msi);
ret = RET_OK;
break;
}
default:
break;
}
}
break;
}
case MSI_CMD_TRANS_FB:
{
ret = RET_ERR;
struct framebuff *frame_buf = (struct framebuff *)param1;
if(frame_buf->mtype == F_AUDIO) {
ret = RET_OK;
}
break;
}
case MSI_CMD_PRE_DESTROY:
{
if(wave_encode_s && wave_encode_s->task_hdl) {
wave_encode_s->next_status = AUCODEC_EXIT;
}
break;
}
case MSI_CMD_POST_DESTROY:
{
if(wave_encode_s) {
if(wave_encode_s->task_hdl) {
os_event_wait(&wave_encode_s->event, coder_exit_event, NULL, OS_EVENT_WMODE_OR | OS_EVENT_WMODE_CLEAR, osWaitForever);
}
if(wave_encode_s->event.hdl) {
os_event_del(&wave_encode_s->event);
}
if(wave_encode_s->wave_fp) {
osal_fclose(wave_encode_s->wave_fp);
wave_encode_s->wave_fp = NULL;
}
WAVE_CODE_FREE(wave_encode_s);
wave_encode_s = NULL;
}
break;
}
default:
break;
}
return ret;
}
struct msi *wave_encode_init(char *filename, uint32_t samplerate, AUENC_INIT *auenc_init)
{
#if AUDIO_EN
uint8_t msi_isnew = 0;
struct msi *msi = msi_new("R_WAVE_ENCODE", MAX_WAVE_ENCODE_RXBUF, &msi_isnew);
if(!msi) {
WAVE_INFO("create wave encode msi fail!\r\n");
return NULL;
}
else if(!msi_isnew) {
WAVE_INFO("wave encode msi has been create!\r\n");
goto wave_encode_init_err;
}
struct wave_encode_struct *wave_encode_s = (struct wave_encode_struct*)WAVE_CODE_ZALLOC(sizeof(struct wave_encode_struct));
if(!wave_encode_s) {
WAVE_INFO("wave_encode_s malloc fail!\r\n");
goto wave_encode_init_err;
}
msi->priv = wave_encode_s;
msi->action = (msi_action)wave_encode_msi_action;
if(os_event_init(&wave_encode_s->event) != RET_OK) {
WAVE_INFO("create wave encode event fail!\r\n");
goto wave_encode_init_err;
}
if(filename) {
wave_encode_s->wave_fp = osal_fopen((const char*)filename, "wb+");
if(wave_encode_s->wave_fp == NULL) {
WAVE_INFO("open wave record file %s fail!\r\n", filename);
goto wave_encode_init_err;
}
}
else {
WAVE_INFO("wave record filename is null!\r\n");
goto wave_encode_init_err;
}
os_memcpy(&(wave_encode_s->wave_head), wav_header, sizeof(TYPE_WAVE_HEAD));
osal_fseek(wave_encode_s->wave_fp, sizeof(TYPE_WAVE_HEAD));
if(auenc_init->src_msi && (msi_add_output(auenc_init->src_msi, NULL, msi->name) != RET_OK)) {
goto wave_encode_init_err;
}
wave_encode_s->msi = msi;
wave_encode_s->src_msi = auenc_init->src_msi;
wave_encode_s->samplerate = samplerate;
wave_encode_s->destroy_self = auenc_init->destroy_self;
wave_encode_s->next_status = AUCODEC_RUN;
wave_encode_s->current_status = AUCODEC_RUN;
wave_encode_s->task_hdl = os_task_create("wave_encode_thread", wave_encode_thread, (void*)wave_encode_s, OS_TASK_PRIORITY_NORMAL, 0, NULL, 1024);
if(wave_encode_s->task_hdl == NULL) {
WAVE_INFO("create wave encode task fail!\r\n");
goto wave_encode_init_err;
}
return msi;
wave_encode_init_err:
msi_destroy(msi);
#endif
return NULL;
}