MXC-A36_2024.04.18/fr3092_mcu/components/modules/audio/voice_recognize.c

123 lines
4.0 KiB
C
Raw Normal View History

2024-04-17 19:45:26 +08:00
#include <assert.h>
#include "audio_scene.h"
#include "audio_rpmsg.h"
#include "dsp.h"
#include "dsp_mem.h"
#include "FreeRTOS.h"
#define VOICE_RECOGNIZE_PCM_BUFFER_MAX_SIZE 128
static void voice_recognize_launch(int16_t *mic_pcm, uint32_t samples)
{
struct rpmsg_sync_msg_voice_recognize_launch_t sync_msg;
if (((uint32_t)mic_pcm >= DSP_DRAM_MCU_BASE_ADDR) && ((uint32_t)mic_pcm < (DSP_DRAM_MCU_BASE_ADDR+DSP_DRAM_SIZE))) {
mic_pcm = (void *)MCU_SRAM_2_DSP_DRAM(mic_pcm);
}
sync_msg.mic_pcm = mic_pcm;
sync_msg.samples = samples;
rpmsg_sync_invoke(rpmsg_get_remote_instance(), RPMSG_SYNC_FUNC_VOICE_RECOGNIZE_LAUNCH, (void *)&sync_msg, NULL);
}
static void hw_receive_adc_pcm_cb(uint32_t samples)
{
audio_scene_evt_t *evt = (void *)pvPortMalloc(sizeof(audio_scene_evt_t));
if (evt) {
evt->type = AUDIO_SCENE_EVT_TYPE_ADC_NEW_SAMPLES;
evt->p.adc_new_samples = samples;
audio_scene_send_event(evt);
}
}
static void voice_recognize_init(void)
{
voice_recognize_env_t *env;
audio_scene_param_voice_recognize_t *param;
env = &audio_scene_env.env.voice_recognize;
param = &audio_scene_env.scene->param.voice_recognize;
/* initialize audio hardware */
env->audio_hw = audio_hw_create(param->hw_type,
NULL,
param->hw_base_addr,
AUDIO_HW_DIR_IN,
param->sample_rate,
AUDIO_CHANNELS_MONO);
env->audio_hw_output = audio_hw_output_add(env->audio_hw, hw_receive_adc_pcm_cb);
/* allocate PCM buffer to save MIC data */
env->pcm = dsp_mem_alloc(sizeof(int16_t) * VOICE_RECOGNIZE_PCM_BUFFER_MAX_SIZE);
/* TODO, notice DSP to prepare for voice recognization */
}
void voice_recognize_destroy(void)
{
if (audio_scene_env.scene
&& (audio_scene_env.scene->type == AUDIO_SCENE_TYPE_VOICE_RECOGNIZE)) {
voice_recognize_env_t *env = &audio_scene_env.env.voice_recognize;
/* release audio hardware */
audio_hw_destroy(env->audio_hw);
/* release pcm buffer */
dsp_mem_free(env->pcm);
/* TODO, notice DSP to release resources for voice recognization */
}
}
void voice_recognize_task(void *arg)
{
audio_scene_t *scene = audio_scene_env.scene;
audio_scene_evt_t *evt;
bool exit = false;
if (scene == NULL) {
return;
}
/* initialize necessary audio decoder and hardware */
voice_recognize_init();
while (exit == false) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
GLOBAL_INT_DISABLE();
evt = (void *)co_list_pop_front(&audio_scene_env.evt_list);
GLOBAL_INT_RESTORE();
if (evt) {
switch (evt->type) {
case AUDIO_SCENE_EVT_TYPE_ADC_NEW_SAMPLES:
{
voice_recognize_env_t *voice_recognize = &audio_scene_env.env.voice_recognize;
uint32_t adc_samples = evt->p.adc_new_samples;
/* save adc data into framebuffer */
while ( adc_samples ) {
uint32_t samples = adc_samples > VOICE_RECOGNIZE_PCM_BUFFER_MAX_SIZE ? VOICE_RECOGNIZE_PCM_BUFFER_MAX_SIZE : adc_samples;
audio_hw_read_pcm(voice_recognize->audio_hw_output, &voice_recognize->pcm[0], samples, AUDIO_CHANNELS_MONO);
voice_recognize_launch(&voice_recognize->pcm[0], samples);
adc_samples -= samples;
}
}
break;
case AUDIO_SCENE_EVT_TYPE_DESTROY:
exit = true;
break;
default:
assert(0);
break;
}
vPortFree(evt);
}
}
audio_scene_task_destroy();
}