Breve introducción a los conceptos básicos de audio y la guía de inicio de Esp-sr

Este blog primero describe brevemente los conceptos básicos del audio y luego ayuda a los lectores a comenzar con el SDK de esp-sr.

1 Conceptos básicos de audio

1.1 La naturaleza del sonido

La esencia del sonido es el fenómeno de la propagación de ondas en el medio, y la esencia de la onda de sonido es una onda, una cantidad física. Los dos son diferentes El sonido es una abstracción, un fenómeno de propagación de ondas de sonido, y la onda de sonido es una cantidad física.

1.2 Tres elementos del sonido

  • Volumen: El tamaño del sonido (comúnmente conocido como volumen) que las personas perciben subjetivamente, que está determinado por la amplitud y la distancia entre la persona y la fuente de sonido.
  • Tono: La diferencia de frecuencia determina el tono del sonido (agudos, graves). Cuanto mayor sea la frecuencia, mayor será el tono (la unidad de frecuencia es Hz, Hertz). El rango de audición humana es de 20-20000 Hz. Por debajo de 20 Hz se llama infrasonido, por encima de 20000 Hz se llama ultrasónico).
  • Timbre: Debido a las características de los diferentes objetos y materiales, el sonido tiene diferentes características.El timbre en sí mismo es algo abstracto, pero la forma de onda es esta interpretación abstracta e intuitiva. Las formas de onda varían de un tono a otro, y los diferentes tonos se pueden distinguir por sus formas de onda.

imagen

1.3 Varios conceptos básicos del audio digital

1.3.1 Muestreo

El llamado muestreo consiste en digitalizar la señal solo en el eje del tiempo.

  • Según la ley de Nyquist (también conocida como ley de muestreo), el muestreo se realiza al doble de la frecuencia más alta del sonido. El rango de frecuencia (tono) del oído humano es de 20 Hz a 20 KHz. Así que al menos más de 40 kHz. La frecuencia de muestreo suele ser de 44,1 kHz, lo que garantiza que también se puedan digitalizar sonidos de hasta 20 kHz. 44,1 kHz significa 44100 muestras por segundo.

Espressif AI Voice utiliza una frecuencia de muestreo de 16 kHz. La mitad de la frecuencia de muestreo de 16 kHz corresponde al límite superior de la banda de frecuencia de uso común del habla humana, que es de aproximadamente 8 kHz. Además, la frecuencia de muestreo de 44,1 kHz es otra frecuencia de muestreo de uso común La frecuencia de muestreo de 44,1 kHz Porque en el mismo período de tiempo, cuanto mayor sea la frecuencia de muestreo, mayor será la cantidad de datos, por lo que: por lo general, el audio de mensajería instantánea utilizará una frecuencia de muestreo de 16 kHz o incluso menor para garantizar la puntualidad de la transmisión de la señal, pero también afectar la calidad del audio Provocar ciertas pérdidas (como un sonido opaco); al grabar recursos de audio que se enfocan en sonido de alta calidad, se utilizará una frecuencia de muestreo de 44,1 kHz o incluso 48 kHz para garantizar una alta fidelidad de la señal de reproducción a costa de más almacenamiento de datos.

imagen
Por lo tanto, esta parte incluye principalmente los siguientes tres parámetros:

  • Tasa de bits: La tasa de bits es el número de bits transmitidos por segundo. Las unidades son bits (bps bits por segundo).
  • Muestreo: El muestreo consiste en convertir una señal de tiempo continuo en una señal digital discreta.
  • Tasa de muestreo: La tasa de muestreo es cuántas muestras se toman por segundo.

1.3.2 Cuantización

La cuantificación se refiere a la digitalización de una señal en el eje de magnitud. Si una muestra está representada por una señal binaria de 16 bits, el rango representado por una muestra es [-32768, 32767].

Espressif AI Voice utiliza cuantificación de 16 bits.

1.3.3 Número de canales

El número de canales es el número de canales de sonido, y los más comunes son mono, binaural y estéreo.

  • El sonido monofónico solo puede ser producido por un altavoz, o puede procesarse en dos altavoces para emitir el mismo sonido del canal. Al reproducir información monofónica a través de dos altavoces, podemos sentir claramente que el sonido proviene de dos altavoces. Es imposible determinar la ubicación específica de la fuente de sonido si se transmite a nuestros oídos entre los dos altavoces.

  • Binaural significa que hay dos canales de sonido. El principio es que cuando las personas escuchan el sonido, pueden juzgar la posición específica de la fuente de sonido según la diferencia de fase entre el oído izquierdo y el oído derecho. El sonido se dividió en dos canales separados durante la grabación, lo que resultó en una gran localización del sonido.

1.3.4 Cálculo del tamaño del audio

Por ejemplo: Para grabar una pieza de audio con un tiempo de 1 s, una frecuencia de muestreo de 16000 HZ, un tamaño de muestreo de 16 y un número de canal de 2, el espacio ocupado es: 16000 * 16 * 2 * 1 s= 500k

2 front-end acústico (audio front-end, AFE)

Se puede utilizar un conjunto de marcos de algoritmos Espressif AFE para el procesamiento frontal acústico basado en los potentes SoC ESP32 y ESP32-S3, lo que permite a los usuarios obtener datos de audio estables y de alta calidad, a fin de crear productos de voz inteligentes con excelente rendimiento y rendimiento de alto costo.

2.1 Cancelación de eco acústico (AEC)

El algoritmo de cancelación de eco acústico utiliza un filtrado adaptativo para eliminar los ecos cuando se recibe audio desde un micrófono. Este algoritmo es adecuado para escenarios como dispositivos de voz que reproducen audio a través de altavoces.

El algoritmo admite como máximo el procesamiento de micrófono dual, lo que puede eliminar de manera efectiva el sonido de reproducción automática en la señal de entrada del micrófono. De esta forma, las aplicaciones como el reconocimiento de voz pueden funcionar bien bajo la condición de reproducir música por sí mismo.

2.2 Separación ciega en fuente (BSS)

El algoritmo de separación de fuente ciega utiliza múltiples micrófonos para detectar la dirección del audio entrante y enfatiza la entrada de audio desde una dirección determinada. Este algoritmo mejora la calidad del sonido de la fuente de audio deseada en entornos ruidosos.

2.3 Supresión de ruido (NS)

El algoritmo de supresión de ruido es compatible con el procesamiento de señales de audio de un solo canal, lo que puede eliminar eficazmente los sonidos no humanos inútiles (como aspiradoras o acondicionadores de aire), mejorando así la señal de audio que se procesará.

3 escenarios compatibles con Espressif AFE

Las funciones de Espressif AFE están dirigidas a los siguientes dos escenarios diferentes:

  1. escena de reconocimiento de voz

  2. escena de llamada de voz

3.1 Escenario de reconocimiento de voz

Pasos del modelo:

  1. entrada de audio

  2. AEC para cancelación de eco (elimina su propio anuncio de audio, que requiere un canal de eco)

    • Devolución de llamada dura: lea directamente los datos escritos en el altavoz a través de IIS (puede compartir un IIS con el micrófono)
    • Devolución de llamada suave: datos de copia de software escritos en el altavoz (aún no compatible, en espera de desarrollo)
  3. BSS/NS

    • El algoritmo BSS (Blind Source Separation) admite el procesamiento de doble canal , que puede separar ciegamente la fuente de sonido objetivo de otros sonidos que interfieren, extrayendo así señales de audio útiles y asegurando la calidad del habla posterior.
    • El algoritmo NS (supresión de ruido) admite el procesamiento de un solo canal , que puede suprimir el ruido de la voz no humana en el audio de un solo canal, especialmente para el ruido de estado estable, y tiene un buen efecto de supresión.
    • El algoritmo a utilizar depende del número de micrófonos configurados.
  4. QUÉ

    • El algoritmo VAD (Detección de actividad de voz) admite la salida en tiempo real del estado de actividad de voz del cuadro actual
  5. WakeNet

    palabra de despertar

El diagrama de flujo correspondiente es el siguiente:
Por favor agregue una descripción de la imagen

3.2 Escenario de llamada de voz

Pasos del modelo:

  1. entrada de audio
  2. AEC para cancelación de eco (elimina su propio anuncio de audio, que requiere un canal de eco)
    • Devolución de llamada dura: lea directamente los datos escritos en el altavoz a través de IIS (puede compartir un IIS con el micrófono)
    • Devolución de llamada suave: datos de copia de software escritos en el altavoz (aún no compatible, en espera de desarrollo)
  3. BSS/NS
    • El algoritmo BSS (Blind Source Separation) admite el procesamiento de doble canal , que puede separar ciegamente la fuente de sonido objetivo de otros sonidos que interfieren, extrayendo así señales de audio útiles y asegurando la calidad del habla posterior.
    • El algoritmo NS (supresión de ruido) admite el procesamiento de un solo canal , que puede suprimir el ruido de la voz no humana en el audio de un solo canal, especialmente para el ruido de estado estable, y tiene un buen efecto de supresión.
    • El algoritmo a utilizar depende del número de micrófonos configurados.
  4. MISO
    • El algoritmo MISO (Multi Input Single Output) admite entrada de dos canales y salida de un solo canal. Se utiliza para seleccionar una salida de audio con una alta relación señal-ruido en un escenario de micrófono dual sin activación habilitada.
  5. CAG
    • AGC (Control automático de ganancia) ajusta dinámicamente la amplitud del audio de salida. Cuando se ingresa una señal débil, la amplitud de salida se amplifica; cuando la señal de entrada alcanza cierta fuerza, la amplitud de salida se comprime.

El diagrama de flujo correspondiente es el siguiente:
Por favor agregue una descripción de la imagen

3.3 Referencia del código de configuración

#define AFE_CONFIG_DEFAULT() {
      
       \
    .aec_init = true, \                      	     	//AEC 算法是否使能
    .se_init = true, \									//BSS/NS 算法是否使能
    .vad_init = true, \									//VAD 是否使能 ( 仅可在语音识别场景中使用 )
    .wakenet_init = true, \								//唤醒是否使能.
    .voice_communication_init = false, \				//语音通话是否使能。与 wakenet_init 不能同时使能.
    .voice_communication_agc_init = false, \        	//语音通话中AGC是否使能
    .voice_communication_agc_gain = 15, \               //AGC的增益值,单位为dB
    .vad_mode = VAD_MODE_3, \                      	    //VAD 检测的操作模式,越大越激进
    .wakenet_model_name = NULL, \                       //选择唤醒词模型
    .wakenet_mode = DET_MODE_2CH_90, \              	//唤醒的模式。对应为多少通道的唤醒,根据mic通道的数量选择
    .afe_mode = SR_MODE_LOW_COST, \						//SR_MODE_LOW_COST: 量化版本,占用资源较少。 
        												//SR_MODE_HIGH_PERF: 非量化版本,占用资源较多。
    .afe_perferred_core = 0, \                      	//AFE 内部 BSS/NS/MISO 算法,运行在哪个 CPU 核
    .afe_perferred_priority = 5, \                  	//AFE 内部 BSS/NS/MISO 算法,运行的task优先级。
    .afe_ringbuf_size = 50, \                       	//内部 ringbuf 大小的配置
    .memory_alloc_mode = AFE_MEMORY_ALLOC_MORE_PSRAM, \	//绝大部分从外部psram分配
    .agc_mode = AFE_MN_PEAK_AGC_MODE_2, \               //线性放大喂给后续multinet的音频,峰值处为 -4dB。
    .pcm_config.total_ch_num = 3, \                     //total_ch_num = mic_num + ref_num
    .pcm_config.mic_num = 2, \							//音频的麦克风通道数。目前仅支持配置为 1 或 2。
    .pcm_config.ref_num = 1, \                          //音频的参考回路通道数,目前仅支持配置为 0 或 1。
}

4 modelo de voz de IA

4.1 WakeNet

4.1.1 Seleccionar modelo a través de menuconfig

wn9_hiesp (el último wn9 es la cuantificación predeterminada de 8 bits): versión 9, la palabra de activación es hola, especialmente

Por favor agregue una descripción de la imagen

4.2 multired

4.2.1 Seleccionar modelo a través de menuconfig

mn4q8_cn: Versión 4, cuantificación de 8 bits, palabras de comando en chino
Por favor agregue una descripción de la imagen

4.3 Agregar palabras de comando

4.3.1 Agregar palabras de comando a través de menuconfig

  • Agregue pinyin directamente a las palabras de comando chinas: encienda el aire acondicionado (da kai kong tiao) y también admita varias oraciones para admitir la misma ID DE COMANDO, velocidad máxima del viento/velocidad máxima del viento

    Agregue palabras de comando del dialecto: agregue la pronunciación correspondiente
    Por favor agregue una descripción de la imagen

  • Las palabras de comando en inglés deben agregar los fonemas correspondientes, que se generan a través de scripts de python
    Por favor agregue una descripción de la imagen

4.3.2 Agregar dinámicamente palabras de comando en el código

esp_mn_commands_add(i, token);

Agregue dinámicamente palabras de comando llamando a api.

rendimiento del algoritmo

Consume solo alrededor del 20 % de la CPU, 30 KB de SRAM y 500 KB de PSRAM

5 diseño de micrófono

5.1 Recomendación de rendimiento del micrófono

  1. Tipo de micrófono: micrófono MEMS omnidireccional.

  2. Sensibilidad:

    • Bajo una presión de sonido de 1 Pa, la sensibilidad analógica no debe ser inferior a -38 dBV y la sensibilidad digital no debe ser inferior a -26 dB.
    • La tolerancia se controla en ±2 dB, se recomienda ±1 dB para arreglos Mike
  3. SNR

    La relación señal-ruido no es inferior a 62 dB, y se recomienda >64 dB:

    Cuanto mayor sea la relación señal-ruido, mayor será la fidelidad del sonido

    • Respuesta de frecuencia: la fluctuación de la respuesta de frecuencia en el rango de 50 ~ 16 kHz está dentro de ± 3 dB
    • Relación de rechazo de la fuente de alimentación (PSRR): n >55 dB (MEMS MIC)

6 Sugerencias de Diseño Estructural

  1. Se recomienda que el diámetro o ancho del orificio del micrófono sea superior a 1 mm, el tubo captador debe ser lo más corto posible y la cavidad debe ser lo más pequeña posible para garantizar que la frecuencia de resonancia del micrófono y los componentes estructurales esté por encima 9 KHz.

  2. La relación entre la profundidad y el diámetro del orificio de captación es inferior a 2:1 y se recomienda que el grosor de la carcasa sea de 1 mm. Si la carcasa es demasiado gruesa, es necesario aumentar el área del orificio.

  3. Los orificios del bastidor deben protegerse con redes a prueba de polvo.

  4. Se debe agregar una funda de silicona o espuma entre el micrófono y la carcasa del dispositivo para sellar y proteger contra golpes, y se requiere un diseño de ajuste de interferencia para garantizar la hermeticidad del micrófono.

  5. El orificio del micrófono no se puede bloquear, y el orificio inferior del micrófono debe elevarse en la estructura para evitar que la mesa bloquee el orificio del micrófono.

  6. El micrófono debe colocarse lejos de altavoces y otros objetos que generen ruido o vibraciones, y debe aislarse y protegerse de la cavidad del altavoz mediante almohadillas de goma.

Explicación de 7 códigos (CN_SPEECH_COMMANDS_RECOGNITION)

7.1 Archivos de encabezado

#include "esp_wn_iface.h"                   //唤醒词模型的一系列API
#include "esp_wn_models.h"					//根据输入的模型名称得到具体的唤醒词模型
#include "esp_afe_sr_iface.h"				//语音识别的音频前端算法的一系列API
#include "esp_afe_sr_models.h"              //语音前端模型的声明
#include "esp_mn_iface.h"                   //命令词模型的一系列API
#include "esp_mn_models.h"                  //命令词模型的声明
#include "esp_board_init.h"                 //开发板硬件初始化
#include "driver/i2s.h"                     //i2s 驱动
#include "speech_commands_action.h"         //根据识别到的 command 进行语音播报/闪烁 LED
#include "model_path.h"                     //从 spiffs 文件管理中返回模型路径等 API

7.2 aplicación_principal

void app_main()
{
    
    
    models = esp_srmodel_init("model");                                //spiffs 中的所有可用模型或  model 默认是从`flash`读
    ESP_ERROR_CHECK(esp_board_init(AUDIO_HAL_08K_SAMPLES, 1, 16));     //Special config for dev board   
    // ESP_ERROR_CHECK(esp_sdcard_init("/sdcard", 10));                //初始化 SD card
#if defined CONFIG_ESP32_KORVO_V1_1_BOARD
    led_init();                                                        //LED 初始化
#endif

    afe_handle = &ESP_AFE_SR_HANDLE;                                   
    afe_config_t afe_config = AFE_CONFIG_DEFAULT();					   //音频前端的配置项

    afe_config.wakenet_model_name = esp_srmodel_filter(models, ESP_WN_PREFIX, NULL);;  //从有所可用的模型中找到唤醒词模型的名字
#if defined CONFIG_ESP32_S3_BOX_BOARD || defined CONFIG_ESP32_S3_EYE_BOARD
    afe_config.aec_init = false;
#endif
    //afe_config.aec_init = false;                                       //关闭 AEC
    //afe_config.se_init = false;                                        //关闭 SE
    //afe_config.vad_init = false;                                       //关闭VAD
    //afe_config.pcm_config.total_ch_num = 2;                            //设置为单麦单回采
    //afe_config.pcm_config.mic_num = 1;                                 //麦克风通道一
    esp_afe_sr_data_t *afe_data = afe_handle->create_from_config(&afe_config);

    xTaskCreatePinnedToCore(&feed_Task, "feed", 4 * 1024, (void*)afe_data, 5, NULL, 0);        //feed 从 i2s 拿到音频数据
    xTaskCreatePinnedToCore(&detect_Task, "detect", 8 * 1024, (void*)afe_data, 5, NULL, 1);    //将音频数据喂给模型获取检测结果

#if defined  CONFIG_ESP32_S3_KORVO_1_V4_0_BOARD || defined CONFIG_ESP32_KORVO_V1_1_BOARD
    xTaskCreatePinnedToCore(&led_Task, "led", 2 * 1024, NULL, 5, NULL, 0);                     //开启LED
#endif
#if defined  CONFIG_ESP32_S3_KORVO_1_V4_0_BOARD || CONFIG_ESP32_S3_KORVO_2_V3_0_BOARD || CONFIG_ESP32_KORVO_V1_1_BOARD
    xTaskCreatePinnedToCore(&play_music, "play", 2 * 1024, NULL, 5, NULL, 1);                  //开启语音播报
#endif
}

7.2 Operación de alimentación

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();         //3;
    int16_t *i2s_buff = malloc(audio_chunksize * sizeof(int16_t) * feed_channel);
    assert(i2s_buff);
    size_t bytes_read;

    while (1) {
    
    
        //第一种方式 
        //audio_chunksize:音频时间 512->32ms 256->16ms
        //int16_t:16位量化
        //feed_channel:两麦克风通道数据一回采通道数据
        esp_get_feed_data(i2s_buff, audio_chunksize * sizeof(int16_t) * feed_channel);
        //第二种方式
        i2s_read(I2S_NUM_1, i2s_buff, audio_chunksize * sizeof(int16_t) * feed_channel, &bytes_read, portMAX_DELAY);
        afe_handle->feed(afe_data, i2s_buff);
    }
    afe_handle->destroy(afe_data);
    vTaskDelete(NULL);
}

7.3 operación de detección

void detect_Task(void *arg)
{
    
    
	esp_afe_sr_data_t *afe_data = arg;
    int afe_chunksize = afe_handle->get_fetch_chunksize(afe_data);
    int nch = afe_handle->get_channel_num(afe_data);
    char *mn_name = esp_srmodel_filter(models, ESP_MN_PREFIX, ESP_MN_CHINESE);       //从模型队列中获取命令词模型名字
    printf("multinet:%s\n", mn_name);
    esp_mn_iface_t *multinet = esp_mn_handle_from_name(mn_name);                     //获取命令词模型
    model_iface_data_t *model_data = multinet->create(mn_name, 5760);                //创建
    esp_mn_commands_update_from_sdkconfig(multinet, model_data); 					 // Add speech commands from sdkconfig
    int mu_chunksize = multinet->get_samp_chunksize(model_data);
    int chunk_num = multinet->get_samp_chunknum(model_data);
    assert(mu_chunksize == afe_chunksize);
    printf("------------detect start------------\n");
    // FILE *fp = fopen("/sdcard/out1", "w");
    // if (fp == NULL) printf("can not open file\n");
    while (1) {
    
    
        afe_fetch_result_t* res = afe_handle->fetch(afe_data);                       //获得AEF的处理结果
        if (!res || res->ret_value == ESP_FAIL) {
    
    
            printf("fetch error!\n");
            break;
        }
#if CONFIG_IDF_TARGET_ESP32
        if (res->wakeup_state == WAKENET_DETECTED) {
    
                                    
            printf("wakeword detected\n");
            play_voice = -1;
            detect_flag = 1;
            afe_handle->disable_wakenet(afe_data);
            printf("-----------listening-----------\n");
        }
#elif CONFIG_IDF_TARGET_ESP32S3
        if (res->wakeup_state == WAKENET_DETECTED) {
    
                              
            printf("WAKEWORD DETECTED\n");                                           //如果被唤醒将唤醒标志置位True
        } else if (res->wakeup_state == WAKENET_CHANNEL_VERIFIED) {
    
    
            play_voice = -1;
            detect_flag = 1;
            printf("AFE_FETCH_CHANNEL_VERIFIED, channel index: %d\n", res->trigger_channel_id);
        }
#endif

        if (detect_flag == 1) {
    
    
            esp_mn_state_t mn_state = multinet->detect(model_data, res->data);       //将AFE处理后的音频数据给命令词模型

            if (mn_state == ESP_MN_STATE_DETECTING) {
    
    
                continue;
            }

            if (mn_state == ESP_MN_STATE_DETECTED) {
    
    
                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, prob: %f\n", 
                    i+1, mn_result->command_id[i], mn_result->phrase_id[i], mn_result->prob[i]);
                }
                printf("\n-----------listening-----------\n");
            }

            if (mn_state == ESP_MN_STATE_TIMEOUT) {
    
                                     //超时关闭
                afe_handle->enable_wakenet(afe_data);
                detect_flag = 0;
                printf("\n-----------awaits to be waken up-----------\n");
                continue;
            }
        }
    }
    afe_handle->destroy(afe_data);
    vTaskDelete(NULL);
}

8 Referencia de Github relacionada con Espressif AI

Supongo que te gusta

Origin blog.csdn.net/Marchtwentytwo/article/details/129370026
Recomendado
Clasificación