• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Делюсь опытом Запись аудио с микрофона

nikolz

Well-known member
да мне не только мои 12 гонять, мне надо будет нормальные качественные данные проигрывать 16/44. микрофон лишь часть задумки и для него хватит и 12
у Вас какой динамический диапазон системы через которую Вы будете выводить этот звук?
 

unreg

Member
Записал 12Bit, 16KHz качество лучше на субъекивный взгляд. Забавно, что файл может проиграть старенький винамп, а плеер из 10-ки говорит нечитаемый формат. Я не знаю что такое динамический диапазон o_O, собраюсь выводить звук на активные колонки через линейный выход
 

unreg

Member
nikolz, а не поделитесь какой сэмплрэйт на запись можно выжать? с тем кодом который я привел, наверное, 16К это потолок. Если переложить опрос ацп и запись в файл на 2-й процессор, то наверное можно и 44К вытянуть? Вообще, таки задачи наверное есп и не должно решать, просто интересно
 

nikolz

Well-known member
У вас не правильно написан колбек для таймера
надо из него вынести все что не изменяется (настройка канала числа битов) перенести в инициализацию
тогда будет быстрее.
----------------------------
вот тут посмотрите:
ADC Sample rate - ESP32 Forum
говорится
ADC1: около 105 000 образцов в секунду (9,5 МКС на образец)
ADC2: около 87 000 проб в секунду (11,5 МКС на пробу)
вот какая-то библиотека для быстрого ввода (не разбирался что это)
terryjmyers/ESP32analogReadNonBlocking
 

unreg

Member
nikolz, раз уж мы тут опытом делимся, не покажете оптимизацию моего кода? Желательно используя arduino core для новичков! :)
 

nikolz

Well-known member
nikolz, раз уж мы тут опытом делимся, не покажете оптимизацию моего кода? Желательно используя arduino core для новичков! :)
в вашем коде принимаете очередной отсчет здесь:
  1. void IRAM_ATTR onTimer() {

  2. portENTER_CRITICAL_ISR(&timerMux);
  3. uint16_t sample = adc1_get_raw(ADC1_CHANNEL_0);
  4. uint8_t value = map(sample, 0, 4095, 0, 255);
  5. audioBuffer[bufferPointer] = value;
  6. bufferPointer++;
  7. if (bufferPointer == AUDIO_BUFFER_MAX)
  8. {
  9. memcpy(audioBufferTmp, audioBuffer, AUDIO_BUFFER_MAX);
  10. bufferPointer = 0;
  11. audio_buffer_ready = true;
  12. }
  13. portEXIT_CRITICAL_ISR(&timerMux);
  14. }
для максимальной скорости надо убрать все преобразования оставить лишь запись в буфер
а преобразования сделать после заполнения буфера.
т е должно остаться типа так:
  1. void IRAM_ATTR onTimer() {
  2. portENTER_CRITICAL_ISR(&timerMux);
  3. audioBuffer[bufferPointer++] = adc1_get_raw(ADC1_CHANNEL_0); //буфер сделать 16 бит
  4. portEXIT_CRITICAL_ISR(&timerMux);
  5. }
все остальное выносите в задачу
кроме того не надо переписывать из audioBuffer в audioBufferTmp Это лишнее
можно сделать два буфера и переключать их по очереди либо все писать в один.
тут надо подробнее смотреть весь алгоритм обработки.
 

unreg

Member
Спасибо! Сделал через 2 буфера и избавился от memcpy. Повысил частоту до 240 и заменил adc_get_raw на analogRead. Интересно, что adc_get_raw проигрывает anaologRead 20 мкс. (на 240MHz имеем 30 и 10 соответственно). Сейчас пишу 16 бит 44100KHz понятно что это чисто эксперимент побаловаться, микрофону такое нафиг не надо.
 
Где результат вашей работы?
Вот мой)
ESP8266 управляется AT командами.
Есть примеры для разных частот дискретизации(8,16,36,48 kHz), что очень интересно получается послушать. И применен кодек G711 чего и Вам рекомендую.
 

unreg

Member
Где результат вашей работы?
Вот мой)...
Вы того, этого ссылку на проект давайте... Ужеж цельных 3 дня прошло, а ее все нет ;)
На самом деле мне сложно объяснения на слух воспринимать, лучше почитать, да схемы посмотреть. Материал, конечно, не так просто готовить.
А так, конечно, здорово получилось. Сейчас у меня схема разобрана, на выходных соберу запишу в максимально возможном качестве, сброшу сюда файлик. Если не против, было бы интересно сравнить вашу запись и мою, не по слуху, а вот этими графиками в которых я нихрена не понимаю, а вы, похоже разбираетесь где там шум, а где нет. Хороший канал, спасибо! :)
 

unreg

Member
PS вот может синусоиду записать а? в обход MAX-а? И посмотреть аудио развертку? Что бы исключить внешние факторы и проверить чисто работу ацп, ну и кода. Это я случайно щас подумал, может ерунду горожу.
PPS Модераторы, что, блин, что за лимит времени еще?
 
Ссылка в описании к видео.
Прикрепил файл там две записи. Одна оригинал, вторая просто убрал шумы в программе, так как я это обычно делаю при обработке звука для своих видео.
 

Вложения

  • 452.9 KB Просмотры: 26

unreg

Member
BORISBRITWA, вот что у меня получается. 44100 KHz 16 bit без подавления шума. 16 bit не настоящие, поэтому запись нормализована. Настройка ADC atten = ADC_ATTEN_11db. Уровень шума заметно выше чем у вас, не пойму с чем связано, возможно, если подключить через делитель и настроить adc на 2.2v , то будет лучше, возможно попробую в будущем. (одна запись с шумом, вторая очищена)
 

Вложения

nikolz

Well-known member
Ссылка в описании к видео.
Прикрепил файл там две записи. Одна оригинал, вторая просто убрал шумы в программе, так как я это обычно делаю при обработке звука для своих видео.
поясните зачем STM прикручивать.
Чем это лучше, если сделать на ESP без STM.
ESP8266 может обеспечить ввод сигнала с микрофона с частотой дискретизации до 600 кГц в буфер до 50 Кбайт или вывод в реале через WiFi
Что дополнительно дает STM?
 

nikolz

Well-known member
более того, если Вы используете ESP в режиме AT команд
то лучше взять модуль BLE в режиме AT c STM
тогда и скорость выше и жрет меньше
 

unreg

Member
Присоединяюсь к nikolz. Тоже не понял смысл конструкции, может ацп на stm чем-то лучше? И до кучи спрошу. на esp опрос адц можно cделать через DMA?
 

nikolz

Well-known member
если не затруднит - что это значит и где про это посмотреть? пауз вроде нет никаких
пауза - это сигнал ниже определенного порога
так как данные вводятся не по DMA то каждый отсчет АЦП можно обработать процессором
в простейшем случай делается так
вводится значение сравнивается с порогом если меньше то повторяем
когда порог превышается то вводим данные в массив
после заполнения массива
смотрим в обратную сторону и убираем значения меньше порога
в массиве остается сигнал без паузы вначале и в конце
примерно так
подробнее можно почитать в книжках по цифровой обработке звука.
 
Сверху Снизу