В этой статье я хочу рассказать о том, как можно распознавать речь на микроконтроллере, используя отладочную плату STM32F4-Discovery. Поскольку распознавание речи — достаточно сложная задача даже для компьютера, то в данном случае оно проводится при помощи сервиса Google. Распознавание речи таким способом может пригодится в разных задачах, например в одном из устройств «умного дома».
Отладочная плата STM32F4-Discovery заметно отличается от нередко упоминаемой в статьях отладочной платы STM32-Discovery. На ней установлен микроконтроллер STM32F407VGT6, использующий архитектуру Cortex-M4F, имеющий 1 MB Flash и 192 KB RAM. Контроллер способен работать с тактовой частотой 168 МГц.
На отладочной плате установлен аудио-ЦАП со встроенным усилителем (его выход соединен с разъемом для наушников) и цифровой MEMS-микрофон, благодаря чему на базе STM32F4-Discovery можно легко изготовить устройство, работающее со звуком.
Распознавание голоса с использованием Google Voice Search описано здесь: Статья.
Для того, чтобы распознать какую-либо сказанную фразу с использованием микроконтроллера, нужно выполнить ряд действий:
• Записать звук в память контроллера.
• Произвести кодирование звука.
• Установить соединение с сервером Google.
• Отправить на сервер POST-запрос и закодированные аудиоданные.
• Принять ответ от сервера.
Запись голоса
Поскольку на плате уже есть цифровой микрофон, записывать звук будем с его помощью. В данном случае это PDM-микрофон. Он имеет только два сигнальных вывода — тактирование и данные. При наличии сигнала тактирования, на выходе данных микрофона появляется сигнал, закодированный при помощи PDM модуляции (подробнее о ней рассказано в Википедии: Pulse-density modulation). На STM32F4-Discovery микрофон соединен с SPI/I2S — для приема данных с микрофона достаточно сконфигурировать I2S на прием данных, и по прерыванию от I2S считывать из регистра полученные данные. Эти данные сохраняются в память контроллера, и после того, как будет записано достаточное количество данных, производится их фильтрация, результатом которой являются несколько семплов аудиоданных.
Работа с микрофоном описана в документе AN3998 от ST — там объясняется принцип действия микрофона, особенности его подключения и описывается работа с функцией фильтрации.
На сайте ST среди различных примеров для платы есть пример работы со звуком, вот только он достаточно навороченный — в примере показано, как воспроизводить звук из памяти контролера и с подключенной к плате USB-флешки. Так же демонстрируется запись звука на флешку. Код для воспроизведения и записи звука я брал именно оттуда. Вот только в этом коде оказалось немало ошибок и недоделок — вероятно, пример писали в спешке.
Кодирование записанного звука
Описания работы с сервисом распознавания голоса уже не раз приводились в интернете. Во всех случаях авторы используют аудиокодек FLAC, так как в Google используют нестандартное кодирование Speex данных.
Это видно из кода браузера Chromium: Код, отвечающий за запись звука.
В описании POST запроса указывается, что тип данных — «audio/x-speex-with-header-byte».
Вот только на STM32 не удастся закодировать данные в формат FLAC — нет таких библиотек. А вот код Speex портирован на STM32, поэтому для кодирования я использовал именно этот кодек. Из кода Chromium довольно легко понять, в чем заключается модификация кодека — перед началом каждого фрейма закодированных аудиоданных вставляется дополнительный байт, равный длине фрейма в байтах.
Запись и кодирование звука идут одновременно — с использованием двойной буферизации: в то время, пока в один из буферов записываются 160 семплов аудиоданных, данные из другого буфера кодируются в формат Speex. Закодированные данные сохраняются в памяти контроллера. Запись идет в течении 2 секунд, в результате чего формируются 2100 байт закодированных аудиоданных. Частота дискретизации — 8 кГц.
Связь с сервером Google
Для соединения с интернетом используется отладочная плата с WIFI модулем — RN-XV. На ней установлен WIFI-модуль RN-171 (снизу платы), антенна, 3 сетодиода и штыревые разъемы. Связь с модулем идет через UART, так что для работы с ним достаточно 4 проводов. Стоимость платы в sparkfun, откуда я его заказывал — 35$. Сам WIFI — модуль стоит 30$. Подробнее о модуле можно прочитать на сайте sparkfun: RN-XV WiFly Module.
Для того того, чтобы передать данные на сервер, нужно подключится к нему по протоколу TCP, а затем передать запрос такого вида:
POST http://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ru-RU HTTP/1.1@#Content-type: audio/x-speex-with-header-byte; rate=8000@#Connection: close@#Content-length: 2100@#@#
Символы @# программа заменяет на CRLF. После передачи запроса нужно отправить на сервер 2100 байт закодированных аудиоданных. Получив все данные, сервер производит распознавание речи, и передает распознанную строку вместе с дополнительной информацией, после чего соединение с сервером закрывается.
После того, как ответ сервера принят, программа выделяет из него распознанную строку и выводит ее через другой UART микроконтроллера. Данные из этого UART передаются на компьютер в терминал, в окне которого и появляется распознанная фраза. После этого контролер готов в запуску записи новой фразы.
Запись запускается нажатием кнопки на STM32F4-Discovery — к сожалению, мне не удалось реализовать запуск распознавания при появлении голоса — первые звуки фразы не успевают записаться, и первое слово в фразе распознается неверно.
Получившаяся конструкция выглядит так:
А вот как она работает:
Программа написана в IAR.
Программа позволяет воспроизводить записанную фразу, перед тем как отправить ее на сервер. Для этого достаточно раскомментировать некоторые строки в функции main.
В приложенном архиве несколько проектов:
my_audio_test — записывает и сразу же воспроизводит звук с микрофона.
speex_out — воспроизводит звук в формате Speex, хранящийся в Flash памяти контроллера.
speex_rec — записывает и кодирует звук при помощи Speex в течение 2 секунд, после чего воспроизводит запись.
speech_wifi — сам проект распознавания речи, единственный проект, использующий WIFI.
Автор: iliasam