diff --git a/wled00/audio_reactive.h b/wled00/audio_reactive.h index b253859fbc..403cddaef6 100644 --- a/wled00/audio_reactive.h +++ b/wled00/audio_reactive.h @@ -40,7 +40,7 @@ AudioSource *audioSource; // #define MIC_SAMPLING_LOG // #define FFT_SAMPLING_LOG -#define MAJORPEAK_SUPPRESS_NOISE // define to activate a dirty hack that ignores the lowest + hightest FFT bins +//#define MAJORPEAK_SUPPRESS_NOISE // define to activate a dirty hack that ignores the lowest + hightest FFT bins const i2s_port_t I2S_PORT = I2S_NUM_0; const int BLOCK_SIZE = 128; @@ -347,6 +347,8 @@ void FFTcode( void * parameter) { FFT.MajorPeak(&FFT_MajorPeak, &FFT_Magnitude); // let the effects know which freq was most dominant #ifdef MAJORPEAK_SUPPRESS_NOISE + // dirty hack: limit suppressed channel intensities to FFT_Magnitude + for (int k=0; k < 24; k++) if(xtemp[k] > FFT_Magnitude) xtemp[k] = FFT_Magnitude; // restore bins vReal[0] = xtemp[0]; vReal[1] = xtemp[1]; diff --git a/wled00/audio_source.h b/wled00/audio_source.h index af17333cae..47b84665d4 100644 --- a/wled00/audio_source.h +++ b/wled00/audio_source.h @@ -8,6 +8,18 @@ Until this configuration is moved to the webinterface */ +// data type requested from the I2S driver - currently we always use 32bit +//#define I2S_USE_16BIT_SAMPLES // (experimental) define this to request 16bit - more efficient but possibly less compatible +#ifdef I2S_USE_16BIT_SAMPLES +#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_16BIT +#define I2S_datatype int16_t +#undef I2S_SAMPLE_DOWNSCALE_TO_16BIT +#else +#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_32BIT +#define I2S_datatype int32_t +#define I2S_SAMPLE_DOWNSCALE_TO_16BIT +#endif + #ifndef MCLK_PIN int mclkPin = 0; #else @@ -68,7 +80,7 @@ class AudioSource { protected: // Private constructor, to make sure it is not callable except from derived classes - AudioSource(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : _sampleRate(sampleRate), _blockSize(blockSize), _sampleNoDCOffset(0), _dcOffset(0.0f), _shift(lshift), _mask(mask), _initialized(false) {}; + AudioSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : _sampleRate(sampleRate), _blockSize(blockSize), _sampleNoDCOffset(0), _dcOffset(0.0f), _shift(lshift), _mask(mask), _initialized(false) {}; int _sampleRate; /* Microphone sampling rate */ int _blockSize; /* I2S block size */ @@ -84,16 +96,16 @@ class AudioSource { */ class I2SSource : public AudioSource { public: - I2SSource(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : + I2SSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : AudioSource(sampleRate, blockSize, lshift, mask) { _config = { .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX), .sample_rate = _sampleRate, - .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .bits_per_sample = I2S_SAMPLE_RESOLUTION, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, - .dma_buf_count = 12, + .dma_buf_count = 8, .dma_buf_len = _blockSize }; @@ -155,7 +167,7 @@ class I2SSource : public AudioSource { if(_initialized) { esp_err_t err; size_t bytes_read = 0; /* Counter variable to check if we actually got enough data */ - int16_t samples[num_samples]; /* Intermediary sample storage */ + I2S_datatype samples[num_samples]; /* Intermediary sample storage */ // Reset dc offset _dcOffset = 0.0f; @@ -174,6 +186,10 @@ class I2SSource : public AudioSource { // Store samples in sample buffer and update DC offset for (int i = 0; i < num_samples; i++) { + // pre-shift samples down to 16bit +#ifdef I2S_SAMPLE_DOWNSCALE_TO_16BIT + samples[i] >>= 16; +#endif // pre-processing of ADC samples if (_mask == 0x0FFF) { // 0x0FFF means that we have 12bit unsigned data from ADC -> convert to signed samples[i] = samples[i] - 2048; @@ -213,7 +229,7 @@ class I2SSource : public AudioSource { */ class I2SSourceWithMasterClock : public I2SSource { public: - I2SSourceWithMasterClock(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : + I2SSourceWithMasterClock(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : I2SSource(sampleRate, blockSize, lshift, mask) { }; @@ -281,7 +297,7 @@ class ES7243 : public I2SSourceWithMasterClock { public: - ES7243(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : + ES7243(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : I2SSourceWithMasterClock(sampleRate, blockSize, lshift, mask) { _config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT; }; @@ -312,16 +328,16 @@ class ES7243 : public I2SSourceWithMasterClock { */ class I2SAdcSource : public I2SSource { public: - I2SAdcSource(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : + I2SAdcSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : I2SSource(sampleRate, blockSize, lshift, mask){ _config = { .mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN), .sample_rate = _sampleRate, - .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT, + .bits_per_sample = I2S_SAMPLE_RESOLUTION, .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT, .communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB), .intr_alloc_flags = ESP_INTR_FLAG_LEVEL1, - .dma_buf_count = 12, + .dma_buf_count = 8, .dma_buf_len = _blockSize }; } @@ -424,7 +440,7 @@ class I2SAdcSource : public I2SSource { class SPH0654 : public I2SSource { public: - SPH0654(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : + SPH0654(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : I2SSource(sampleRate, blockSize, lshift, mask){} void initialize() { @@ -443,7 +459,7 @@ class SPH0654 : public I2SSource { class I2SPdmSource : public I2SSource { public: - I2SPdmSource(int sampleRate, int blockSize, uint16_t lshift, uint32_t mask) : + I2SPdmSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) : I2SSource(sampleRate, blockSize, lshift, mask) { _config.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM); // Change mode to pdm