完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
目前我在基于ESP-SkaiNet的sample,开发语音助手。当提示词唤醒后对用户输入的 语音保存和处理。
我想请教一下,当我通过afe_handle->fetch,res->data获得的音频数据是什么格式?PCM吗?获取的音频数据如何播放出来? void feed_Task(void *arg) { esp_afe_sr_data_t *afe_data = arg; int audio_chunksize = afe_handle->get_feed_chunksize(afe_data); int nch = afe_handle->get_channel_num(afe_data); int feed_channel = esp_get_feed_channel(); assert(nch <= feed_channel); int16_t *i2s_buff = malloc(audio_chunksize * sizeof(int16_t) * feed_channel); assert(i2s_buff); while (task_flag) { esp_get_feed_data(false, i2s_buff, audio_chunksize * sizeof(int16_t) * feed_channel); afe_handle->feed(afe_data, i2s_buff); } if (i2s_buff) { free(i2s_buff); i2s_buff = NULL; } vTaskDelete(NULL); } int16_t *buff; int buff_index; int buff_total; int afe_chunksize; void detect_Task(void *arg) { esp_afe_sr_data_t *afe_data = arg; int afe_chunksize = afe_handle->get_fetch_chunksize(afe_data); char *mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ESP_MN_CHINESE); printf("multinet:%sn", mn_name); esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name); model_iface_data_t *model_data = multinet->create(mn_name, 6000); esp_mn_commands_update_from_sdkconfig(multinet, model_data); // Add speech commands from sdkconfig int mu_chunksize = multinet->get_samp_chunksize(model_data); assert(mu_chunksize == afe_chunksize); //print active speech commands multinet->print_active_speech_commands(model_data); printf("------------detect start------------n"); while (task_flag) { afe_fetch_result_t* res = afe_handle->fetch(afe_data); if (!res || res->ret_value == ESP_FAIL) { printf("fetch error!n"); break; } if (res->wakeup_state == WAKENET_DETECTED) { printf("WAKEWORD DETECTEDn"); multinet->clean(model_data); // clean all status of multinet afe_chunksize = afe_handle->get_fetch_chunksize(afe_data); buff = malloc(1024 * afe_chunksize * sizeof(int16_t)); buff_index = 0; buff_total = 0; assert(buff); } else if (res->wakeup_state == WAKENET_CHANNEL_VERIFIED) { printf("WAKENET_CHANNEL_VERIFIEDn"); play_voice = -1; detect_flag = 1; printf("AFE_FETCH_CHANNEL_VERIFIED, channel index: %dn", res->trigger_channel_id); } if (detect_flag == 1) { if (res->vad_state == AFE_VAD_SPEECH) { if (res res->ret_value != ESP_FAIL) { memcpy(buff + buff_index, res->data, afe_chunksize * 1 * sizeof(int16_t)); buff_index += afe_chunksize * 1 * sizeof(int16_t); } } esp_mn_state_t mn_state = multinet->detect(model_data, res->data); if (mn_state == ESP_MN_STATE_DETECTING) { continue; } if (mn_state == ESP_MN_STATE_DETECTED) { printf("Detectedn"); esp_mn_results_t *mn_result = multinet->get_results(model_data); for (int i = 0; i < mn_result->num; i++) { printf("TOP %d, command_id: %d, phrase_id: %d, string:%s prob: %fn", i+1, mn_result->command_id[i], mn_result->phrase_id[i], mn_result->string, mn_result->prob[i]); } printf("n-----------listening-----------n"); } if (mn_state == ESP_MN_STATE_TIMEOUT) { printf("n-----------playing user speeking-----------n"); printf("length %dn", buff_index); wake_up_action(); play_audio_voice(buff, buff_index); esp_mn_results_t *mn_result = multinet->get_results(model_data); printf("timeout, string:%sn", mn_result->string); afe_handle->enable_wakenet(afe_data); detect_flag = 0; free(buff); printf("n-----------awaits to be waken up-----------n"); continue; } } } if (model_data) { multinet->destroy(model_data); model_data = NULL; } printf("detect exitn"); vTaskDelete(NULL); } |
|
相关推荐
1个回答
|
|
首先,我们需要了解afe_handle->fetch()方法的作用。这个方法用于从音频前端(AFE)获取音频数据。在ESP-SkaiNet中,AFE负责处理音频输入,如麦克风信号的采集、预处理等。
根据您的代码片段,我们可以分析以下几个步骤: 1. 获取音频数据的通道数和块大小: - `int audio_chunksize = afe_handle->get_feed_chunksize(afe_data);`:获取音频数据的块大小。 - `int nch = afe_handle->get_channel_num(afe_data);`:获取音频数据的通道数。 2. 获取音频数据的格式: - 通常情况下,AFE处理后的音频数据以PCM(脉冲编码调制)格式存储。PCM是一种未压缩的音频格式,通常用于存储原始音频数据。 3. 播放音频数据: - 要播放音频数据,您需要将PCM数据发送到音频输出设备,如扬声器或耳机。在ESP-SkaiNet中,您可以使用音频播放库(如ESP32-A2DP)来实现音频播放。 以下是一个简单的示例,展示如何使用ESP32-A2DP库播放PCM音频数据: ```c #include #include #include #define I2S_NUM I2S_NUM_0 #define I2S_SAMPLE_RATE 44100 #define I2S_CHANNEL_NUM 2 static const char *TAG = "A2DP_SINK"; void feed_Task(void *arg) { esp_afe_sr_data_t *afe_data = arg; int audio_chunksize = afe_handle->get_feed_chunksize(afe_data); int nch = afe_handle->get_channel_num(afe_data); int feed_channel = esp_get_feed_channel(); // 初始化I2S i2s_config_t i2s_config = { .mode = I2S_MODE_MASTER | I2S_MODE_TX | I2S_MODE_DAC_BUILT_IN, .sample_rate = I2S_SAMPLE_RATE, .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, .communication_format = I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB, .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, .dma_buf_count = 8, .dma_buf_len = 1024 }; i2s_driver_install(I2S_NUM, &i2s_config, 0, NULL); // 初始化A2DP esp_a2d_sink_cfg_t a2d_sink_cfg = { .codec_fmt = ESP_A2D_Codectype_SBC, .BitsPerSample = 16, .ChannelNum = I2S_CHANNEL_NUM, .SampleRate = I2S_SAMPLE_RATE }; esp_a2d_sink_register(&a2d_sink_cfg); // 获取音频数据并播放 while (1) { esp_err_t ret; size_t bytes_written; size_t chunk_size = audio_chunksize * nch * 2; // 2 bytes per sample uint8_t *buffer = malloc(chunk_size); if (buffer == NULL) { ESP_LOGE(TAG, "Failed to allocate memory for audio buffer"); break; } ret = afe_handle->fetch(afe_data, buffer, chunk_size); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to fetch audio data"); free(buffer); break; } ret = i2s_write_bytes(I2S_NUM, buffer, chunk_size, &bytes_written, portMAX_DELAY); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to write audio data to I2S"); } free(buffer); } // 卸载I2S驱动 i2s_driver_uninstall(I2S_NUM); esp_a2d_sink_unregister(); } void app_main() { // 初始化AFE afe_handle = afe_init(...); // 创建任务 xTaskCreate(feed_Task, "feed_Task", 4096, afe_handle, 1, NULL); } ``` 在这个示例中,我们首先初始化I2S和A2DP,然后通过afe_handle->fetch()方法获取音频数据,并使用i2s_write_bytes()方法将数据发送到I2S。这样,音频数据就可以通过扬声器播放出来。 |
|
|
|
只有小组成员才能发言,加入小组>>
733 浏览 1 评论
552浏览 6评论
461浏览 5评论
有没有办法在不使用混杂模式的情况下实现Wifi驱动程序接收缓冲区访问中断呢?
445浏览 5评论
446浏览 4评论
417浏览 4评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-24 16:25 , Processed in 0.793794 second(s), Total 81, Slave 64 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号