Скрыть объявление
На нашем форуме недоступен просмотр изображений для неавторизованных пользователей. Если Вы уже зарегистрированы на нашем форуме, то можете войти. Если у Вас еще нет аккаунта, мы будем рады, если Вы к нам присоединитесь. Зарегистрироваться Вы можете здесь.

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

Тема в разделе "ESP32 - все о железе", создана пользователем unreg, 2 май 2019.

  1. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    Ну вот при содействии форумчан удалось таки записать звук с микрофона. ESP32-wrover-b, Микрофон на плате max9814 (OUT подключен к GPIO36 (SENSOR VP)), и microSD-карта class 10 8Гб. Звук пишется довольно качественно для голоса, длина записи может регулироваться конечным размером аудиоданных :rolleyes: не стал заморачиваться с кнопками, цель была не в этом. Формат файла 8 бит, 8КГц.
    Скетч:
    Код (Text):
    1. #include <Arduino.h>
    2. #include <driver/adc.h>
    3.  
    4. #include "FS.h"
    5. #include "SD.h"
    6. #include "SPI.h"
    7.  
    8. #define AUDIO_BUFFER_MAX 51200 //эмпирически выбрал. склеек не слышно. буфер успевает записаться на SD пока другой заполняется новыми аудио данными
    9.  
    10. uint8_t audioBuffer[AUDIO_BUFFER_MAX];
    11.  
    12. uint8_t audioBufferTmp[AUDIO_BUFFER_MAX];
    13.  
    14. uint32_t bufferPointer = 0;
    15.  
    16. bool transmitNow = false;
    17. bool recordStarting = false;
    18.  
    19. hw_timer_t * timer = NULL; // our timer
    20. portMUX_TYPE timerMux = portMUX_INITIALIZER_UNLOCKED;
    21.  
    22. fs::File fContent;
    23.  
    24. int touch_sensor_value = 0;
    25. const int VALUE_THRESHOLD = 70;
    26.  
    27. volatile bool audio_buffer_ready = false;
    28. int interruptCounter = 0;
    29. size_t audio_data_size = 0;
    30.  
    31. byte  header[44] = {};
    32.  
    33. bool startRecording = true;
    34.  
    35. void setup() {
    36.  
    37.     Serial.begin(115200);
    38.     if (!SD.begin()) {
    39.         Serial.println("Card Mount Failed");
    40.         startRecording = false;
    41.         return;
    42.     }
    43.     startRecording = true;
    44.     if (SD.exists("/file.wav"))
    45.         SD.remove("/file.wav");
    46.    
    47.     Serial.println("Ready");
    48.  
    49.     adc1_config_width(ADC_WIDTH_12Bit);
    50.     adc1_config_channel_atten(ADC1_CHANNEL_0, ADC_ATTEN_11db);
    51.  
    52.     fContent = SD.open("/file.wav", FILE_WRITE);
    53.     fContent.write((const byte *)header, sizeof(header));
    54.     Serial.println("Rec started file.wav");
    55.  
    56.     timer = timerBegin(0, 80, true);
    57.     timerAttachInterrupt(timer, &onTimer, true);
    58.     timerAlarmWrite(timer, 125, true);
    59.     timerAlarmEnable(timer);
    60. }
    61.  
    62. void IRAM_ATTR onTimer() {
    63.  
    64.     portENTER_CRITICAL_ISR(&timerMux);
    65.     uint16_t sample = adc1_get_raw(ADC1_CHANNEL_0);
    66.     uint8_t value = map(sample, 0, 4095, 0, 255);
    67.     audioBuffer[bufferPointer] = value;
    68.     bufferPointer++;
    69.     if (bufferPointer == AUDIO_BUFFER_MAX)
    70.     {
    71.         memcpy(audioBufferTmp, audioBuffer, AUDIO_BUFFER_MAX);
    72.         bufferPointer = 0;
    73.         audio_buffer_ready = true;
    74.     }
    75.     portEXIT_CRITICAL_ISR(&timerMux);
    76. }
    77.  
    78. void loop() {
    79.     if (!startRecording)
    80.         return;
    81.     if (audio_buffer_ready)
    82.     {
    83.         audio_buffer_ready = false;
    84.         audio_data_size += fContent.write((const uint8_t *)audioBufferTmp, sizeof(audioBufferTmp));
    85.     }
    86.    
    87.     if (audio_data_size > 500000) //500000 это тот самый размер аудиоданных (~1 мин)
    88.     {
    89.         startRecording = false;
    90.         timerAlarmDisable(timer);
    91.         CreateWavHeader(header, audio_data_size);
    92.         fContent.seek(0);
    93.         fContent.write((const byte *)header, sizeof(header));
    94.         fContent.close();
    95.         SD.end(); //корректно отключаем SD, я уже одну убил
    96.         Serial.println("Done!");
    97.         Serial.print("Audio Data size:");
    98.         Serial.println(audio_data_size, DEC);
    99.     }
    100.    
    101. }
    102.  
    103. void CreateWavHeader(byte* header, int waveDataSize) {
    104.     header[0] = 'R';
    105.     header[1] = 'I';
    106.     header[2] = 'F';
    107.     header[3] = 'F';
    108.     unsigned int fileSizeMinus8 = waveDataSize + 44 - 8;
    109.     header[4] = (byte)(fileSizeMinus8 & 0xFF);
    110.     header[5] = (byte)((fileSizeMinus8 >> 8) & 0xFF);
    111.     header[6] = (byte)((fileSizeMinus8 >> 16) & 0xFF);
    112.     header[7] = (byte)((fileSizeMinus8 >> 24) & 0xFF);
    113.     header[8] = 'W';
    114.     header[9] = 'A';
    115.     header[10] = 'V';
    116.     header[11] = 'E';
    117.     header[12] = 'f';
    118.     header[13] = 'm';
    119.     header[14] = 't';
    120.     header[15] = ' ';
    121.     header[16] = 0x10;
    122.     header[17] = 0x00;
    123.     header[18] = 0x00;
    124.     header[19] = 0x00;
    125.     header[20] = 0x01;
    126.     header[21] = 0x00;
    127.     header[22] = 0x01;
    128.     header[23] = 0x00;
    129.     header[24] = 0x40;
    130.     header[25] = 0x1F;
    131.     header[26] = 0x00;
    132.     header[27] = 0x00;
    133.     header[28] = 0x40;
    134.     header[29] = 0x1F;
    135.     header[30] = 0x00;
    136.     header[31] = 0x00;
    137.     header[32] = 0x01;
    138.     header[33] = 0x00;
    139.     header[34] = 0x08;
    140.     header[35] = 0x00;
    141.     header[36] = 'd';
    142.     header[37] = 'a';
    143.     header[38] = 't';
    144.     header[39] = 'a';
    145.     header[40] = (byte)(waveDataSize & 0xFF);
    146.     header[41] = (byte)((waveDataSize >> 8) & 0xFF);
    147.     header[42] = (byte)((waveDataSize >> 16) & 0xFF);
    148.     header[43] = (byte)((waveDataSize >> 24) & 0xFF);
    149. }
    150.  
    151. uint16_t changeEndianess(uint16_t val)
    152. {
    153.     return (val << 8) | ((val >> 8) & 0x00ff);
    154. }
    Прошу предложения, замечания и 12-ти битный wav-файл (они вообще бывают и проигрываются стандартными плеерами?). Не допер как собрать чанк формата и не нашел конвертера который бы мог сделать 12 бит, а так хоть хексом подгляжу.
     
  2. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    вопрос уточните.
    Вы же принимаете 12 бит.
    укажите что у вас буфер 16 битный и пишите в него.
    или что-то другое надо?
     
  3. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    Да, принимаю12 бит, точнее 4 байта инт со значимыми 12 битами, потом масштабирую на 8. это потому что не получается проиграть полученный 12битный. То ли я не правильно заголовок составляю, то ли в принципе 12 бит не играются тем же виндоус плеером. Дело в том что 12 бит понятное дело это 2 байта. выравниваются по левому краю, плюс младший байт со старшим переставляются при записи в файл. Я все это проделывал, но плеер не распознает формат, чую заголовок формирую не правильно и подглядеть некуда
     
  4. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    качал разные конвертеры так ни олин из них 12 ьитный вав делать не могет
     
  5. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    что мешает делать 16 бит? т е 12 бит помещаете в 16 бит.будет громкость меньше.
    если надо громкость повысить то 12 бит двигаете влево на 4 бита и пишите в 16 бит.
     
  6. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    а заголовок в чанке формат тоже под 16 бит? там есть два байта под bitPerSample, ну и другие поля зависящие от этого значения...Предлагаете заголовок под 16 бит собрать? Определяться будет как 16 бит а пофакту 12. Надо попробовать
     
  7. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    чем отличается 12 бит от 16 бит? тем что сигнал в 12 битах в 16 раз слабее (вместо крика будет шопот).
    другое дело что если будете воспроизводить через ШИМ то качество будет что с 12 что с 16 что с 8 практически одинаковое
     
  8. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    да просто хотелось стандарта придерживаться. воспроизводить буду через цап. заказал td1387
     
  9. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    вы же с микрофона вводите голос. качество будет не очень
    если воспроизводите сами то зачем вам заголовки
    или вы сжимаете данные?
    тогда тем более зачем 16 бит.
    надо изначально определиться вам с качеством и разрядностью чтобы избыточность не гонять впустую.
     
  10. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    -------------
     
  11. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    чтобы не тратить память надо определить буфер в байтах
    и упаковывать два отсчета в три байта.
     
  12. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
  13. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    Воспроизводить я буду не только то что с микрофона, но и качественные короткие сэмплы. Устройство многофункциональное по задумке. А на счет чистого потока это прямо мысли читаете :) тем более что реализовал уже такое через встроеный цап, битности не хватает
     
  14. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    а как вы установили, что битности не хватает?
    я например делал говорящий прибор и гонял 8 и 12 бит через ШИМ и ЦАП результат получился одинаковый.
     
  15. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    а как вы 12 бит через 8 битный цап гоняли?
     
  16. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    я так понял лучше чем качество в 8 бит там и не получить. поэтому наверное одинаково и получалось
     
  17. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    я гонял 12 бит через цап 12 бит.
    -MCP4725
     
  18. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    а ну поэтому я цап 16 бит i2s заказал. чтоб уж гонять так гонять)) 8 бит встроеного для моих целей не хватает
     
  19. nikolz

    nikolz Гуру

    Сообщения:
    5.047
    Симпатии:
    461
    у вас ацп 12 бит в результате 16 бит цап будет лишь шуметь в младших битах либо работать как 12 бит
     
  20. unreg

    unreg Новичок

    Сообщения:
    69
    Симпатии:
    0
    да мне не только мои 12 гонять, мне надо будет нормальные качественные данные проигрывать 16/44. микрофон лишь часть задумки и для него хватит и 12
     

Поделиться этой страницей