分享一个国产板子(JL)的简单录音播放----比较拙劣 欢迎各位大佬指点~~~

------------------------------基于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(&timestamp, &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

1 个赞

嘶~ 你这用md包起来呗

1 个赞

够硬核。不过我建议你把代码放在github仓库里。这里留一下仓库链接,摘录部分说一下实现原理和解读更好。

1 个赞

啊哈哈哈 我刚才还嫌弃你设置36000的帖子字数太少了哈哈哈

1 个赞

下次一定 :melting_face:

1 个赞

代码托管、阅读还是github专业啊

1 个赞

github用得少 我平时用gitee 找找链接去

1 个赞

温馨提示,本站支持 markdown,贴代码你这排版没法看

1 个赞