------------------------------基于freertos-----------------------------------
主函数:
#include “system/includes.h”
#include “app_config.h”
#include “storage_device.h”
#include “generic/log.h”
#include “os/os_api.h”
#include “event/key_event.h”
#include “event/device_event.h”
#include “event/net_event.h”
/*中断列表 */
const struct irq_info irq_info_table = {
//中断号 //优先级0-7 //注册的cpu(0或1)
#ifdef CONFIG_IPMASK_ENABLE
//不可屏蔽中断方法:支持写flash,但中断函数和调用函数和const要全部放在内部ram
{ IRQ_SOFT5_IDX, 6, 0 }, //此中断强制注册到cpu0
{ IRQ_SOFT4_IDX, 6, 1 }, //此中断强制注册到cpu1
#if 0 //如下,SPI1使用不可屏蔽中断设置,优先级固定7
{ IRQ_SPI1_IDX, 7, 1 },//中断强制注册到cpu0/1
#endif
#endif
#if CPU_CORE_NUM == 1
{ IRQ_SOFT5_IDX, 7, 0 }, //此中断强制注册到cpu0
{ IRQ_SOFT4_IDX, 7, 1 }, //此中断强制注册到cpu1
{ -2, -2, -2 },//如果加入了该行, 那么只有该行之前的中断注册到对应核, 其他所有中断强制注册到CPU0
#endif
{ -1, -1, -1 },
};
/创建使用 os_task_create_static 或者task_create 接口的 静态任务堆栈/
#define SYS_TIMER_STK_SIZE 512
#define SYS_TIMER_Q_SIZE 128
static u8 sys_timer_tcb_stk_q[sizeof(StaticTask_t) + SYS_TIMER_STK_SIZE * 4 + sizeof(struct task_queue) + SYS_TIMER_Q_SIZE] ALIGNE(4);
#define SYSTIMER_STK_SIZE 256
static u8 systimer_tcb_stk_q[sizeof(StaticTask_t) + SYSTIMER_STK_SIZE * 4] ALIGNE(4);
#define SYS_EVENT_STK_SIZE 512
static u8 sys_event_tcb_stk_q[sizeof(StaticTask_t) + SYS_EVENT_STK_SIZE * 4] ALIGNE(4);
#define APP_CORE_STK_SIZE 1024
#define APP_CORE_Q_SIZE 256
static u8 app_core_tcb_stk_q[sizeof(StaticTask_t) + APP_CORE_STK_SIZE * 4 + sizeof(struct task_queue) + APP_CORE_Q_SIZE] ALIGNE(4);
/创建使用 thread_fork 接口的 静态任务堆栈/
#define WIFI_TASKLET_STK_SIZE 1024
static u8 wifi_tasklet_tcb_stk_q[sizeof(struct thread_parm) + WIFI_TASKLET_STK_SIZE * 4] ALIGNE(4);
#define WIFI_CMDQ_STK_SIZE 300
static u8 wifi_cmdq_tcb_stk_q[sizeof(struct thread_parm) + WIFI_CMDQ_STK_SIZE * 4] ALIGNE(4);
#define WIFI_MLME_STK_SIZE 700
static u8 wifi_mlme_tcb_stk_q[sizeof(struct thread_parm) + WIFI_MLME_STK_SIZE * 4] ALIGNE(4);
#define WIFI_RX_STK_SIZE 256
static u8 wifi_rx_tcb_stk_q[sizeof(struct thread_parm) + WIFI_RX_STK_SIZE * 4] ALIGNE(4);
/*任务列表 */
const struct task_info task_info_table = {
{“app_core”, 15, APP_CORE_STK_SIZE, APP_CORE_Q_SIZE, app_core_tcb_stk_q },
{“sys_event”, 29, SYS_EVENT_STK_SIZE, 0, sys_event_tcb_stk_q },
{“systimer”, 14, SYSTIMER_STK_SIZE, 0, systimer_tcb_stk_q },
{“sys_timer”, 9, SYS_TIMER_STK_SIZE, SYS_TIMER_Q_SIZE, sys_timer_tcb_stk_q },
{“audio_server”, 16, 512, 64 },
{“audio_mix”, 28, 512, 0 },
{“audio_encoder”, 12, 384, 64 },
{“speex_encoder”, 13, 512, 0 },
{“mp3_encoder”, 13, 768, 0 },
{“jla_encoder”, 13, 768, 0 },
{“aac_encoder”, 13, 768, 0 },
{“opus_encoder”, 13, 1536, 0 },
{“ogg_encoder”, 13, 1536, 0 },
{“vir_dev_task”, 13, 256, 0 },
{“amr_encoder”, 13, 1024, 0 },
{“cvsd_encoder”, 13, 512, 0 },
{“vad_encoder”, 14, 768, 0 },
{“aec_encoder”, 13, 1024, 0 },
{“dns_encoder”, 13, 512, 0 },
{“msbc_encoder”, 13, 256, 0 },
{“sbc_encoder”, 13, 512, 0 },
{“adpcm_encoder”, 13, 512, 0 },
{“echo_deal”, 11, 1024, 32 },
#if CPU_CORE_NUM > 1
{“#C0usb_msd0”, 1, 512, 128 },
#else
{“usb_msd0”, 1, 512, 128 },
#endif
{“usb_msd1”, 1, 512, 128 },
{“uac_sync”, 20, 512, 0 },
{“uac_record0”, 26, 768, 0 },
{“uac_record1”, 26, 768, 0 },
{“uac_play0”, 26, 768, 32 },
{“uac_play1”, 26, 768, 32 },
{"tcpip_thread", 16, 800, 0 },
#ifdef CONFIG_WIFI_ENABLE
{“tasklet”, 10, WIFI_TASKLET_STK_SIZE, 0, wifi_tasklet_tcb_stk_q },//通过调节任务优先级平衡WIFI收发占据总CPU的比重
{“RtmpMlmeTask”, 17, WIFI_MLME_STK_SIZE, 0, wifi_mlme_tcb_stk_q },
{“RtmpCmdQTask”, 17, WIFI_CMDQ_STK_SIZE, 0, wifi_cmdq_tcb_stk_q },
{“wl_rx_irq_thread”, 5, WIFI_RX_STK_SIZE, 0, wifi_rx_tcb_stk_q },
#endif
{0, 0},
};
extern int audio_demo_mode_switch(void);
static int main_key_event_handler(struct key_event *key)
{
switch (key->action) {
case KEY_EVENT_CLICK:
switch (key->value) {
case KEY_MODE:
audio_demo_mode_switch();
break;
default:
return false;
}
break;
case KEY_EVENT_LONG:
break;
default:
return false;
}
return true;
}
static int main_dev_event_handler(struct device_event *event)
{
switch (event->event) {
case DEVICE_EVENT_IN:
break;
case DEVICE_EVENT_OUT:
break;
case DEVICE_EVENT_CHANGE:
break;
}
return 0;
}
#ifdef CONFIG_NET_ENABLE
static int main_net_event_hander(struct net_event *event)
{
switch (event->event) {
case NET_EVENT_CMD:
break;
case NET_EVENT_DATA:
break;
}
return false;
}
#endif
/*
- 默认的系统事件处理函数
- 当所有活动的app的事件处理函数都返回false时此函数会被调用
*/
void app_default_event_handler(struct sys_event *event)
{
switch (event->type) {
case SYS_KEY_EVENT:
main_key_event_handler((struct key_event *)event->payload);
break;
case SYS_TOUCH_EVENT:
break;
case SYS_DEVICE_EVENT:
main_dev_event_handler((struct device_event *)event->payload);
break;
#ifdef CONFIG_NET_ENABLE
case SYS_NET_EVENT:
main_net_event_hander((struct net_event *)event->payload);
break;
#endif
default:
ASSERT(0, “unknow event type: %s\n”, func);
break;
}
}
/应用程序主函数/
void app_main()
{
puts(“------------- demo_audio app main-------------\n”);
audio_demo_mode_switch();
}
/-------- 模式切换mode.c函数 ---------/
#include “server/audio_server.h”
#include “server/server_core.h”
#include “app_config.h”
#include “syscfg/syscfg_id.h”
#include “system/app_core.h”
#include “event/key_event.h”
#include “fs/fs.h”
struct audio_app_t {
const char *tone_file_name;
const char *app_name;
};
static const struct audio_app_t audio_app_table = {
#ifdef CONFIG_LOCAL_MUSIC_MODE_ENABLE
{“FlashMusic.mp3”, “local_music”},
#endif
#ifdef CONFIG_NET_MUSIC_MODE_ENABLE
{“NetMusic.mp3”, “net_music” },
#endif
#ifdef CONFIG_RECORDER_MODE_ENABLE
{“Recorder.mp3”, “recorder”},
#endif
#ifdef CONFIG_ASR_ALGORITHM_ENABLE
{“AiSpeaker.mp3”, “ai_speaker”},
#endif
};
static u8 mode_index = 0;
static void dec_server_event_handler(void *priv, int argc, int *argv)
{
union audio_req r = {0};
switch (argv[0]) {
case AUDIO_SERVER_EVENT_ERR:
log_i("tone: AUDIO_SERVER_EVENT_ERR\n");
case AUDIO_SERVER_EVENT_END:
log_i("tone: AUDIO_SERVER_EVENT_END\n");
r.dec.cmd = AUDIO_DEC_STOP;
server_request(priv, AUDIO_REQ_DEC, &r);
server_close(priv); //priv是server_register_event_handler_to_task的priv参数
fclose((FILE *)argv[1]); //argv[1]是解码开始时传递进去的文件句柄
key_event_enable();
//等提示音播完了再切换模式
struct intent it;
init_intent(&it);
it.name = audio_app_table[mode_index++].app_name;
start_app(&it);
break;
case AUDIO_SERVER_EVENT_CURR_TIME:
log_i("play_time: %d\n", argv[1]);
break;
default:
break;
}
}
//播放提示音
static int app_play_tone_file(const char *path)
{
int err = 0;
union audio_req req = {0};
printf("play tone file : %s\n", path);
printf("进行提示音打开操作!!!!\n");
FILE *file = fopen(path, "r");
if (!file) {
return -1;
}
void *dec_server = server_open("audio_server", "dec");
if (!dec_server) {
goto __err;
}
server_register_event_handler_to_task(dec_server, dec_server, dec_server_event_handler, "app_core");
req.dec.cmd = AUDIO_DEC_OPEN;
req.dec.volume = 50;
req.dec.output_buf_len = 4 * 1024;
req.dec.file = file;
req.dec.sample_source = "dac";
syscfg_read(CFG_MUSIC_VOL, &req.dec.volume, sizeof(req.dec.volume));
err = server_request(dec_server, AUDIO_REQ_DEC, &req);
if (err) {
goto __err;
}
req.dec.cmd = AUDIO_DEC_START;
err = server_request(dec_server, AUDIO_REQ_DEC, &req);
if (err) {
goto __err;
}
key_event_disable();
return 0;
__err:
if (dec_server) {
server_close(dec_server);
}
if (file) {
fclose(file);
}
return err;
}
int audio_demo_mode_switch(void)
{
if (mode_index >= ARRAY_SIZE(audio_app_table)) {
mode_index = 0;
}
struct intent it;
if (get_current_app()) {
init_intent(&it);
it.name = audio_app_table[mode_index].app_name;
it.action = ACTION_STOP; //退出当前模式
start_app(&it);
}
char path[64];
sprintf(path, "%s%s", CONFIG_VOICE_PROMPT_FILE_PATH, audio_app_table[mode_index].tone_file_name);
return app_play_tone_file(path);
}
/------------- 录音实现recorder.c ---------------/
#include “server/audio_server.h”
#include “server/server_core.h”
#include “system/app_core.h”
#include “generic/circular_buf.h”
#include “os/os_api.h”
#include “app_config.h”
#include “syscfg/syscfg_id.h”
#include “event/key_event.h”
#include “storage_device.h”
#include “fs/fs.h”
#include <time.h>
#include “system/timer.h”
#include “media/spectrum/SpectrumShow_api.h”
#include <errno.h>
#ifdef CONFIG_RECORDER_MODE_ENABLE
#define CONFIG_STORE_VOLUME
#define VOLUME_STEP 20
#define GAIN_STEP 5
#define MIN_VOLUME_VALUE 5
#define MAX_VOLUME_VALUE 10000
#define INIT_VOLUME_VALUE 50
struct recorder_hdl {
FILE *fp;
struct server *enc_server;
struct server *dec_server;
void *cache_buf;
cbuffer_t save_cbuf;
OS_SEM w_sem;
OS_SEM r_sem;
volatile u8 run_flag;
u8 volume;
u8 gain;
u8 channel;
u8 direct;
const char *sample_source;
int sample_rate;
#ifdef CONFIG_SPECTRUM_FFT_EFFECT_ENABLE//—频谱计算
void *work_buf;
s16 *out_buf;
u32 out_buf_size;
u32 offset;
u16 show_timer_id;
#endif
};
static struct recorder_hdl recorder_handler;
#define __this (&recorder_handler)
//AUDIO ADC支持的采样率
static const u16 sample_rate_table = {
8000,
11025,
12000,
16000,
22050,
24000,
32000,
44100,
48000,
};
#ifdef CONFIG_SPECTRUM_FFT_EFFECT_ENABLE
static void recorder_spectrum_fft_show(void *p)
{
if (__this->work_buf) {
short *db_data = getSpectrumValue(__this->work_buf);
int num = getSpectrumNum(__this->work_buf);
if (db_data && num > 0) {
for (int i = 0; i < num; i++) {
//输出db_num个 db值
printf(“db_data db[%d] %d\n”, i, db_data[i]);
}
}
}
}
#endif
//编码器输出PCM数据KEY_VOLUME_INC
static int recorder_vfs_fwrite(void *file, void *data, u32 len)
{
cbuffer_t *cbuf = (cbuffer_t *)file;
if (0 == cbuf_write(cbuf, data, len)) {
//上层buf写不进去时清空一下,避免出现声音滞后的情况
cbuf_clear(cbuf);
}
os_sem_set(&__this->r_sem, 0);
os_sem_post(&__this->r_sem);
#ifdef CONFIG_SPECTRUM_FFT_EFFECT_ENABLE
u32 in_remain = len, tlen = 0;
while (in_remain) {
if (__this->offset < __this->out_buf_size) {
tlen = __this->out_buf_size - __this->offset;
if (tlen > in_remain) {
tlen = in_remain;
}
memcpy((u8 *)__this->out_buf + __this->offset, (u8 *)data + (len - in_remain), tlen);
__this->offset += tlen;
in_remain -= tlen;
if (in_remain && (__this->offset != __this->out_buf_size)) {
continue;
}
}
if (__this->offset == __this->out_buf_size) {
__this->offset = 0;
SpectrumShowRun(__this->work_buf, __this->out_buf, 512);
}
}
#endif
//此回调返回0录音就会自动停止
return len;
}
//解码器读取PCM数据
static int recorder_vfs_fread(void *file, void *data, u32 len)
{
cbuffer_t *cbuf = (cbuffer_t *)file;
u32 rlen;
do {
rlen = cbuf_get_data_size(cbuf);
rlen = rlen > len ? len : rlen;
if (cbuf_read(cbuf, data, rlen) > 0) {
len = rlen;
break;
}
//此处等待信号量是为了防止解码器因为读不到数而一直空转
os_sem_pend(&__this->r_sem, 0);
if (!__this->run_flag) {
return 0;
}
} while (__this->run_flag);
//返回成功读取的字节数
return len;
}
static int recorder_vfs_fclose(void *file)
{
return 0;
}
static int recorder_vfs_flen(void *file)
{
return 0;
}
static const struct audio_vfs_ops recorder_vfs_ops = {
.fwrite = recorder_vfs_fwrite,
.fread = recorder_vfs_fread,
.fclose = recorder_vfs_fclose,
.flen = recorder_vfs_flen,
};
static int recorder_close(void)
{
union audio_req req = {0};
if (!__this->run_flag) {
return 0;
}
log_d("----------recorder close----------\n");
__this->run_flag = 0;
os_sem_post(&__this->w_sem);
os_sem_post(&__this->r_sem);
if (__this->enc_server) {
req.enc.cmd = AUDIO_ENC_CLOSE;
server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
}
if (__this->dec_server) {
req.dec.cmd = AUDIO_DEC_STOP;
server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
}
if (__this->cache_buf) {
free(__this->cache_buf);
__this->cache_buf = NULL;
}
if (__this->fp) {
fclose(__this->fp);
__this->fp = NULL;
}
#ifdef CONFIG_SPECTRUM_FFT_EFFECT_ENABLE
if (__this->work_buf) {
free(__this->work_buf);
__this->work_buf = NULL;
}
if (__this->out_buf) {
free(__this->out_buf);
__this->out_buf = NULL;
}
if (__this->show_timer_id) {
sys_timeout_del(__this->show_timer_id);
__this->show_timer_id = 0;
}
#endif
return 0;
}
static void enc_server_event_handler(void *priv, int argc, int *argv)
{
switch (argv[0]) {
case AUDIO_SERVER_EVENT_ERR:
case AUDIO_SERVER_EVENT_END:
recorder_close();
break;
case AUDIO_SERVER_EVENT_SPEAK_START:
log_i(“speak start ! \n”);
break;
case AUDIO_SERVER_EVENT_SPEAK_STOP:
log_i(“speak stop ! \n”);
break;
default:
break;
}
}
//将MIC的数字信号采集后推到DAC播放
//注意:如果需要播放两路MIC,DAC分别对应的是DACL和DACR,要留意芯片封装是否有DACR引脚出来,
// 而且要使能DAC的双通道输出,DAC如果采用差分输出方式也只会听到第一路MIC的声音
static int recorder_play_to_dac(int sample_rate, u8 channel)
{
int err;
union audio_req req = {0};
log_d("----------recorder_play_to_dac----------\n");
if (channel > 2) {
channel = 2;
}
__this->cache_buf = malloc(sample_rate * channel); //上层缓冲buf缓冲0.5秒的数据,缓冲太大听感上会有延迟
if (__this->cache_buf == NULL) {
return -1;
}
cbuf_init(&__this->save_cbuf, __this->cache_buf, sample_rate * channel);
os_sem_create(&__this->w_sem, 0);
os_sem_create(&__this->r_sem, 0);
__this->run_flag = 1;
/****************打开解码DAC器*******************/
req.dec.cmd = AUDIO_DEC_OPEN;
req.dec.volume = __this->volume;
req.dec.output_buf_len = 4 * 1024;
req.dec.channel = channel;
req.dec.sample_rate = sample_rate;
req.dec.vfs_ops = &recorder_vfs_ops;
req.dec.dec_type = "pcm";
req.dec.sample_source = CONFIG_AUDIO_DEC_PLAY_SOURCE;
req.dec.file = (FILE *)&__this->save_cbuf;
/* req.dec.attr = AUDIO_ATTR_LR_ADD; */ //左右声道数据合在一起,封装只有DACL但需要测试两个MIC时可以打开此功能
err = server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
if (err) {
goto __err;
}
req.dec.cmd = AUDIO_DEC_START;
req.dec.attr = AUDIO_ATTR_NO_WAIT_READY;
server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
#ifdef CONFIG_SPECTRUM_FFT_EFFECT_ENABLE
__this->work_buf = zalloc(getSpectrumShowBuf());
if (!__this->work_buf) {
goto __err1;
}
__this->offset = 0;
__this->out_buf_size = 512 * 2 * channel;
__this->out_buf = zalloc(__this->out_buf_size);
if (!__this->out_buf) {
free(__this->work_buf);
__this->work_buf = NULL;
goto __err1;
}
SpectrumShowInit(__this->work_buf, 0.9, 0.9,
sample_rate, channel, channel > 1 ? 2 : 0, JL_FFT_BASE);
__this->show_timer_id = sys_timer_add(NULL, recorder_spectrum_fft_show, 1000);
#endif
/****************打开编码器*******************/
memset(&req, 0, sizeof(union audio_req));
//BIT(x)用来区分上层需要获取哪个通道的数据
if (channel == 2) {
req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L) | BIT(CONFIG_AUDIO_ADC_CHANNEL_R);
} else {
req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L);
}
req.enc.frame_size = sample_rate / 100 * 4 * channel; //收集够多少字节PCM数据就回调一次fwrite
req.enc.output_buf_len = req.enc.frame_size * 3; //底层缓冲buf至少设成3倍frame_size
req.enc.cmd = AUDIO_ENC_OPEN;
req.enc.channel = channel;
req.enc.volume = __this->gain;
req.enc.sample_rate = sample_rate;
req.enc.format = "pcm";
req.enc.sample_source = __this->sample_source;
req.enc.vfs_ops = &recorder_vfs_ops;
req.enc.file = (FILE *)&__this->save_cbuf;
if (channel == 1 && !strcmp(__this->sample_source, "mic") && (sample_rate == 8000 || sample_rate == 16000)) {
req.enc.use_vad = 1; //打开VAD断句功能
req.enc.dns_enable = 1; //打开降噪功能
req.enc.vad_auto_refresh = 1; //VAD自动刷新
}
err = server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
if (err) {
goto __err1;
}
return 0;
__err1:
req.dec.cmd = AUDIO_DEC_STOP;
server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
__err:
if (__this->cache_buf) {
free(__this->cache_buf);
__this->cache_buf = NULL;
}
__this->run_flag = 0;
return -1;
}
//MIC或者LINEIN模拟直通到DAC,不需要软件参与
static int audio_adc_analog_direct_to_dac(int sample_rate, u8 channel)
{
union audio_req req = {0};
log_d("----------audio_adc_analog_direct_to_dac----------\n");
__this->run_flag = 1;
req.enc.cmd = AUDIO_ENC_OPEN;
req.enc.channel = channel;
req.enc.volume = __this->gain;
req.enc.format = "pcm";
req.enc.sample_source = __this->sample_source;
req.enc.sample_rate = sample_rate;
req.enc.direct2dac = 0;
req.enc.high_gain = 1;
if (channel == 4) {
req.enc.channel_bit_map = 0x0f;
} else if (channel == 2) {
req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L) | BIT(CONFIG_AUDIO_ADC_CHANNEL_R);
} else {
req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L);
}
return server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
}
//录音文件到SD卡
static int recorder_to_file(int sample_rate, u8 channel, const char *format)
{
union audio_req req = {0};
__this->run_flag = 1;//---录音标志
__this->direct = 0;//---录音模式
char time_str[64] = {0};
char file_name[100] = {0};
u8 dir_len = 0;
struct tm timeinfo = {0};
time_t timestamp = time(NULL) + 28800;
localtime_r(×tamp, &timeinfo);
strcpy(time_str, CONFIG_ROOT_PATH"RECORDER/\\U");
dir_len = strlen(time_str);
printf("获取到字符串长度:%d\n",dir_len);
strftime(time_str + dir_len, sizeof(time_str) - dir_len, "%Y-%m-%dT%H-%M-%S.", &timeinfo);
strcat(time_str, format);
printf("最终文件名称 : %s\n", time_str);
memcpy(file_name, time_str, dir_len);
//printf("拷贝目录名后的文件名:%s\n", file_name);
for (u8 i = 0; i < strlen(time_str) - dir_len; ++i) {
file_name[dir_len + i * 2] = time_str[dir_len + i];
}
printf("Format variable: %s\n", format);
//snprintf(file_name, sizeof(file_name), "%s", time_str, format);
printf("拼接后的用于写入的文件名:%s\n", file_name);
req.enc.cmd = AUDIO_ENC_OPEN;
req.enc.channel = channel;
req.enc.volume = __this->gain;
req.enc.frame_size = 8192;
req.enc.output_buf_len = req.enc.frame_size * 10;
req.enc.sample_rate = sample_rate;
req.enc.format = format;
req.enc.sample_source = __this->sample_source;
req.enc.msec = CONFIG_AUDIO_RECORDER_DURATION;
//---写入sd
//---sd卡0代表检测到挂载
printf("SD status: %d\n", storage_device_ready());
//ensure_directory_exists(CONFIG_ROOT_PATH"RECORDER");//---找目录
req.enc.file = __this->fp = fopen(file_name, "w+");
printf("this下的fp = %d\n",__this->fp);
printf("写入的文件名称file name is : %s \n",file_name);
if (__this->fp) {
printf("File opened successfully: %s\n", file_name);
} else {
printf("Failed to open file: %s, errno: %d\n", file_name, errno);
}
/* req.enc.sample_depth = 24; //IIS支持采集24bit深度 */
if (channel == 4) {
req.enc.channel_bit_map = 0x0f;
} else if (channel == 2) {
req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L) | BIT(CONFIG_AUDIO_ADC_CHANNEL_R);
} else {
req.enc.channel_bit_map = BIT(CONFIG_AUDIO_ADC_CHANNEL_L);
}
return server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
}
//—控制录音播放、暂停
static void recorder_play_pause(void)
{
union audio_req req = {0};
req.dec.cmd = AUDIO_DEC_PP;
server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
req.enc.cmd = AUDIO_ENC_PP;
server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
if (__this->cache_buf) {
cbuf_clear(&__this->save_cbuf);
}
}
//调整ADC的模拟增益
static int recorder_enc_gain_change(int step)
{
union audio_req req = {0};
int gain = __this->gain + step;
if (gain < 0) {
gain = 0;
} else if (gain > 100) {
gain = 100;
}
if (gain == __this->gain) {
return -1;
}
__this->gain = gain;
if (!__this->enc_server) {
return -1;
}
log_d("set_enc_gain: %d\n", gain);
req.enc.cmd = AUDIO_ENC_SET_VOLUME;
req.enc.volume = gain;
return server_request(__this->enc_server, AUDIO_REQ_ENC, &req);
}
//调整DAC的数字音量和模拟音量
static int recorder_dec_volume_change(int step)
{
union audio_req req = {0};
int volume = __this->volume + step;
if (volume < MIN_VOLUME_VALUE) {
volume = MIN_VOLUME_VALUE;
} else if (volume > MAX_VOLUME_VALUE) {
volume = MAX_VOLUME_VALUE;
}
if (volume == __this->volume) {
return -1;
}
__this->volume = volume;
if (!__this->dec_server) {
return -1;
}
log_d("set_dec_volume: %d\n", volume);
#ifdef CONFIG_STORE_VOLUME
syscfg_write(CFG_MUSIC_VOL, &__this->volume, sizeof(__this->volume));
#endif
req.dec.cmd = AUDIO_DEC_SET_VOLUME;
req.dec.volume = volume;
return server_request(__this->dec_server, AUDIO_REQ_DEC, &req);
}
static int recorder_mode_init(void)
{
log_i(“recorder_play_main\n”);
memset(__this, 0, sizeof(struct recorder_hdl));
#ifdef CONFIG_STORE_VOLUME
if (syscfg_read(CFG_MUSIC_VOL, &__this->volume, sizeof(__this->volume)) < 0 ||
__this->volume < MIN_VOLUME_VALUE || __this->volume > MAX_VOLUME_VALUE) {
__this->volume = INIT_VOLUME_VALUE;
}
#else
__this->volume = INIT_VOLUME_VALUE;
#endif
if (__this->volume < 0 || __this->volume > MAX_VOLUME_VALUE) {
__this->volume = INIT_VOLUME_VALUE;
}
#if CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_PLNK0
__this->sample_source = “plnk0”;
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_PLNK1
__this->sample_source = “plnk1”;
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_IIS0
__this->sample_source = “iis0”;
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_IIS1
__this->sample_source = “iis1”;
#elif CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_LINEIN
__this->sample_source = “linein”;
#else
__this->sample_source = “mic”;
#endif
__this->channel = CONFIG_AUDIO_RECORDER_CHANNEL;
__this->gain = CONFIG_AUDIO_ADC_GAIN;
__this->sample_rate = CONFIG_AUDIO_RECORDER_SAMPLERATE;
__this->enc_server = server_open("audio_server", "enc");
server_register_event_handler_to_task(__this->enc_server, NULL, enc_server_event_handler, "app_core");
__this->dec_server = server_open("audio_server", "dec");
return recorder_play_to_dac(__this->sample_rate, __this->channel);
}
static void recorder_mode_exit(void)
{
recorder_close();
server_close(__this->dec_server);
__this->dec_server = NULL;
server_close(__this->enc_server);
__this->enc_server = NULL;
}
static int recorder_key_click(struct key_event *key)
{
int ret = true;
switch (key->value) {
case KEY_OK:
#if CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_LINEIN || CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_MIC
if (__this->direct) {
if (__this->run_flag) {
recorder_close();
} else {
audio_adc_analog_direct_to_dac(__this->sample_rate, __this->channel);
}
} else {
recorder_play_pause();
}
#else
recorder_play_pause();
#endif
break;
case KEY_VOLUME_DEC:
log_d(“\n ------KEY_VOLUME_DEC: \n”);
recorder_dec_volume_change(-VOLUME_STEP);
break;
case KEY_VOLUME_INC:
log_d(“\n ------KEY_VOLUME_INC: \n”);
recorder_dec_volume_change(VOLUME_STEP);
break;
default:
ret = false;
break;
}
return ret;
}
static int recorder_key_long(struct key_event *key)
{
printf(“Key event detected: %d\n!!!”, key->value);
switch (key->value) {
#if CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_LINEIN || CONFIG_AUDIO_ENC_SAMPLE_SOURCE == AUDIO_ENC_SAMPLE_SOURCE_MIC
case KEY_OK:
recorder_close();
if (__this->direct) {
recorder_play_to_dac(__this->sample_rate, __this->channel);
} else {
audio_adc_analog_direct_to_dac(__this->sample_rate, __this->channel);
}
__this->direct = !__this->direct;
break;
case KEY_VOLUME_DEC://—录音增益
recorder_enc_gain_change(-GAIN_STEP);
break;
case KEY_VOLUME_INC:
recorder_enc_gain_change(GAIN_STEP);
break;
#endif
case KEY_MODE:
printf(“Storage device ready: %d\n!!!”, storage_device_ready());
if (storage_device_ready()) {
recorder_close();
recorder_to_file(__this->sample_rate, __this->channel, CONFIG_AUDIO_RECORDER_SAVE_FORMAT);
printf("recorder_to_file:success\n!!!!!!!!!!!!!!!!!!!");
}
break;
default:
break;
}
return true;
}
static int recorder_key_event_handler(struct key_event *key)
{
switch (key->action) {
case KEY_EVENT_CLICK:
return recorder_key_click(key);
case KEY_EVENT_LONG:
return recorder_key_long(key);
default:
break;
}
return true;
}
static int recorder_event_handler(struct application *app, struct sys_event *event)
{
switch (event->type) {
case SYS_KEY_EVENT:
return recorder_key_event_handler((struct key_event *)event->payload);
default:
return false;
}
}
static int recorder_state_machine(struct application *app, enum app_state state, struct intent *it)
{
switch (state) {
case APP_STA_CREATE:
break;
case APP_STA_START:
recorder_mode_init();
break;
case APP_STA_PAUSE:
break;
case APP_STA_RESUME:
break;
case APP_STA_STOP:
recorder_mode_exit();
break;
case APP_STA_DESTROY:
break;
}
return 0;
}
static const struct application_operation recorder_ops = {
.state_machine = recorder_state_machine,
.event_handler = recorder_event_handler,
};
REGISTER_APPLICATION(recorder) = {
.name = “recorder”,
.ops = &recorder_ops,
.state = APP_STA_DESTROY,
};
#endif