Este projeto demonstra a síntese de fala no ESP32. Ele executa a síntese localmente usando a biblioteca CMU Flite, em vez de descarregar essa tarefa para os fornecedores de nuvem.
Para este projeto, o Flite 2.2 (Commit Hash E9880474) foi portado para a estrutura ESP-IDF 3.2.2 e agora é um conjunto de componentes reutilizáveis que podem ser encontrados no diretório "componentes".
A voz cmu_us_kal é fornecida como exemplo. Outras vozes predefinidas que vêm com Flite são grandes demais para se encaixar no flash. Novas vozes podem ser adicionadas como componentes separados, desde que se encaixem no flash.
O exemplo executa um servidor HTTP simples que recebe solicitações de texto para obter o texto a serem sintetizadas. O programa sintetiza o texto e envia os dados do PCM sobre I2s. No lado do recebimento do I2S, usei o chip PCM5102, mas qualquer outro chip pode funcionar. Além disso, pode ser possível rotear I2s para um DAC de 8 bits do ESP32.
Primeiro, configure usando make menuconfig . Você precisa definir seu SSID e senha Wi-Fi, bem como os pinos para usar para i2s. Testei com BCK = 26, WS = 25 e dados = 22.
Como o arquivo WAV produzido é armazenado como uma matriz de valores de PCM alocados na pilha, o espaço de heap suficiente deve estar disponível. O espaço necessário depende do comprimento do texto sintetizado. Portanto, é recomendável usar o modelo Wrover de ESP32 que possui 4 MB de PSARAM. O PSRAM deve ser ativado no Menuconfig. Está um pouco escondido nos menus: configuração de componentes -> Esp32 específico -> Suporte para RAM externa e conectada SPI -> Config SPI RAM. Uma vez ativado, ele será adicionado ao pool de alocação de heap.
Para enviar o texto para o ESP32 para sintetizar, é necessário enviar uma solicitação de Get /say com um parâmetro de consulta s . Isso pode ser feito com uma navegação na web. Navegue para http://<ip of esp device>/say?s=This is an example text . A sequência de consultas é limitada a aproximadamente 256 caracteres, mas essa é uma limitação artificial do programa de exemplo e a biblioteca Flite pode sintetizar textos muito mais longos de uma só vez.
Os dados sintetizados são transmitidos em pedaços, portanto, a reprodução pode começar antes de Flite terminar o processamento de todo o texto. Isso reduz o atraso para textos mais longos e dá uma sensação em tempo real. Essa é uma das vantagens de usar o Flite, em vez de usar serviços em nuvem e baixar os dados sintetizados via Wi-Fi.
Copie os componentes em seu projeto.
Verifique se o seu aplicativo Partiton possui pelo menos 2 MB.
factory, app, factory, 0x10000, 0x2F0000,
Configure com make menuconfig .
Em seguida, use o seguinte código:
cst_voice *register_cmu_us_kal(const char *voxdir);
int i2s_stream_chunk(const cst_wave *w, int start, int size,
int last, cst_audio_streaming_info *asi)
{
// write here code that processes the wav chunk. For example send it to
// I2S, drive a DAC or send it via Wi-Fi/Bluetooth/Serial to another
// device.
}
...
/* Initialization code */
flite_init();
cst_voice *v = register_cmu_us_kal(NULL);
cst_audio_streaming_info *asi =
cst_alloc(struct cst_audio_streaming_info_struct,1);
asi->min_buffsize = 256;
asi->asc = i2s_stream_chunk;
asi->userdata = NULL;
feat_set(v->features,"streaming_info",audio_streaming_info_val(asi));
/* Synthesis Code */
cst_wave * wav = flite_text_to_wave("Replace with your text",v);
delete_wave(wav);
Se você usou o Flite em seu projeto, abra uma solicitação de tração com um link para o projeto e eu o adicionarei aqui.