#include "infra/Audio.h" #include #include "config/config.h" #define PRECEDING_BUFFER_SIZE 4 Audio::Audio(MicType micType) { _wavData = new char*[_wavDataSize/_dividedWavDataSize]; for (int i = 0; i < _wavDataSize/_dividedWavDataSize; ++i) _wavData[i] = new char[_dividedWavDataSize]; _precedingWavBuffer = new CircularBuffer(PRECEDING_BUFFER_SIZE); // _precedingWavDataSize/_dividedWavDataSize i2s = new I2S(micType); } Audio::~Audio() { for (int i = 0; i < _wavDataSize/_dividedWavDataSize; ++i) delete[] _wavData[i]; delete[] _wavData; delete i2s; emptyPrecedingBuffer(); } void Audio::_createWavHeader(byte* header, int waveDataSize){ header[0] = 'R'; header[1] = 'I'; header[2] = 'F'; header[3] = 'F'; unsigned int fileSizeMinus8 = waveDataSize + 44 - 8; header[4] = (byte)(fileSizeMinus8 & 0xFF); header[5] = (byte)((fileSizeMinus8 >> 8) & 0xFF); header[6] = (byte)((fileSizeMinus8 >> 16) & 0xFF); header[7] = (byte)((fileSizeMinus8 >> 24) & 0xFF); header[8] = 'W'; header[9] = 'A'; header[10] = 'V'; header[11] = 'E'; header[12] = 'f'; header[13] = 'm'; header[14] = 't'; header[15] = ' '; header[16] = 0x10; // linear PCM header[17] = 0x00; header[18] = 0x00; header[19] = 0x00; header[20] = 0x01; // linear PCM header[21] = 0x00; header[22] = 0x01; // monoral header[23] = 0x00; header[24] = 0x80; // sampling rate 16000 header[25] = 0x3E; header[26] = 0x00; header[27] = 0x00; header[28] = 0x00; // Byte/sec = 16000x2x1 = 32000 header[29] = 0x7D; header[30] = 0x00; header[31] = 0x00; header[32] = 0x02; // 16bit monoral header[33] = 0x00; header[34] = 0x10; // 16bit header[35] = 0x00; header[36] = 'd'; header[37] = 'a'; header[38] = 't'; header[39] = 'a'; header[40] = (byte)(waveDataSize & 0xFF); header[41] = (byte)((waveDataSize >> 8) & 0xFF); header[42] = (byte)((waveDataSize >> 16) & 0xFF); header[43] = (byte)((waveDataSize >> 24) & 0xFF); } char** Audio::record() { _noiseDetectedInPrecedingBuffer = false; _createWavHeader(_paddedHeader, _wavDataSize); _startMicros = micros(); //_readFromPrecedingBuffer(_wavData, _precedingWavDataSize); //_recordToBuffer(_wavData + _precedingWavDataSize, _wavDataSize - _precedingWavDataSize); _recordToBuffer(_wavData, _wavDataSize); return _wavData; } void Audio::_recordToBuffer(char** wavBuffer, int waveDataSize) { int bitBitPerSample = i2s->GetBitPerSample(); if (bitBitPerSample == 16) { for (int j = 0; j < waveDataSize / _dividedWavDataSize; ++j) { i2s->Read(_i2sBuffer, _i2sBufferSize/2); _convertBufferToWav(wavBuffer[j]); } } else if (bitBitPerSample == 32) { for (int j = 0; j < waveDataSize / _dividedWavDataSize; ++j) { i2s->Read(_i2sBuffer, _i2sBufferSize); for (int i = 0; i < _i2sBufferSize/8; ++i) { wavBuffer[j][2*i] = _i2sBuffer[8*i + 2] << 4; // TODO: check << 4 in 16bit wavBuffer[j][2*i + 1] = _i2sBuffer[8*i + 3] << 4; } } } } void Audio::emptyPrecedingBuffer() { while (!_precedingWavBuffer->isEmpty()) { char* tmp; _precedingWavBuffer->popFront(tmp); delete tmp; } } void Audio::writeToPrecedingBuffer() { if (_precedingWavBuffer->isFull()) { char* tmp; _precedingWavBuffer->popFront(tmp); delete tmp; } i2s->Read(_i2sBuffer, _i2sBufferSize/2); _noiseDetectedInPrecedingBuffer = _isNoiseDetectedInPrecedingBuffer(); char* _partialWavBuffer = new char[_precedingWavDataSize]; _convertBufferToWav(_partialWavBuffer); CircularBufferErrorCode err = _precedingWavBuffer->pushBack(_partialWavBuffer); } void Audio::_readFromPrecedingBuffer(char** wavBuffer, int waveDataSize) { char* tmp; for (int i = 0; i < PRECEDING_BUFFER_SIZE; i++) { _precedingWavBuffer->popFront(tmp); wavBuffer[i] = tmp; } emptyPrecedingBuffer(); } void Audio::_convertBufferToWav(char* partialWavBuffer) { for (int i = 0; i < _i2sBufferSize/8; ++i) { partialWavBuffer[2*i] = _i2sBuffer[4*i + 2]; partialWavBuffer[2*i + 1] = _i2sBuffer[4*i + 3]; } } int Audio::getSize() { return (_wavDataSize + sizeof(_paddedHeader)) * 4 / 3; // 4/3 is from base64 encoding } String Audio::print(Stream* stream) { String enc = base64::encode(_paddedHeader, sizeof(_paddedHeader)); enc.replace("\n", ""); stream->print(enc); for (int j = 0; j < _wavDataSize / _dividedWavDataSize; ++j) { enc = base64::encode((byte*)_wavData[j], _dividedWavDataSize); enc.replace("\n", ""); stream->print(enc); } return enc; } unsigned long Audio::getStartMicros() { return _startMicros; } bool Audio::_isNoiseDetectedInPrecedingBuffer() { if (*(int*)_i2sBuffer > NOISE_THRESHOLD || *(int*)_i2sBuffer < -NOISE_THRESHOLD) { Serial.println("Noise detected"); return true; } else { return false; } } bool Audio::isNoiseDetected() { return _noiseDetectedInPrecedingBuffer; }