diff --git a/usermods/audioreactive/audio_reactive.h b/usermods/audioreactive/audio_reactive.h index aaac238c..b3567f6d 100644 --- a/usermods/audioreactive/audio_reactive.h +++ b/usermods/audioreactive/audio_reactive.h @@ -101,7 +101,7 @@ const uint16_t samples = 512; // This value MUST ALWAYS be a p //unsigned int sampling_period_us; //unsigned long microseconds; -static AudioSource *audioSource; +static AudioSource *audioSource = nullptr; static byte soundSquelch = 10; // default squelch value for volume reactive routines static byte sampleGain = 1; // default sample gain @@ -162,7 +162,7 @@ void FFTcode(void * parameter) { // Only run the FFT computing code if we're not in Receive mode if (audioSyncEnabled & 0x02) continue; - audioSource->getSamples(vReal, samplesFFT); + if (audioSource) audioSource->getSamples(vReal, samplesFFT); // old code - Last sample in vReal is our current mic sample //micDataSm = (uint16_t)vReal[samples - 1]; // will do a this a bit later @@ -739,7 +739,7 @@ class AudioReactive : public Usermod { // usermod exchangeable data // we will assign all usermod exportable data here as pointers to original variables or arrays and allocate memory for pointers um_data = new um_data_t; - um_data->u_size = 8; + um_data->u_size = 11; um_data->u_type = new um_types_t[um_data->u_size]; um_data->u_data = new void*[um_data->u_size]; um_data->u_data[0] = &maxVol; @@ -758,25 +758,20 @@ class AudioReactive : public Usermod { um_data->u_type[6] = UMT_DOUBLE; um_data->u_data[7] = &FFT_Magnitude; um_data->u_type[7] = UMT_DOUBLE; + um_data->u_data[8] = &sampleAvg; + um_data->u_type[8] = UMT_FLOAT; + um_data->u_data[9] = &soundAgc; + um_data->u_type[9] = UMT_BYTE; + um_data->u_data[10] = &sampleAgc; + um_data->u_type[10] = UMT_FLOAT; //... // these are values used by effects in soundreactive fork - //uint8_t *fftResult = um_data->; - //float *fftAvg = um_data->; - //float *fftBin = um_data->; - //float *fftCalc = um_data->; - //double FFT_MajorPeak = um_data->; - //double FFT_Magnitude = um_data->; - //float sampleAgc = um_data->; //float sampleReal = um_data->; //float multAgc = um_data->; - //float sampleAvg = um_data->; - //int16_t sample = um_data->; //int16_t rawSampleAgc = um_data->; //bool samplePeak = um_data->; //uint8_t squelch = um_data->; //uint8_t soundSquelch = um_data->; - //uint8_t soundAgc = um_data->; - //uint8_t maxVol = um_data->; //uint8_t binNum = um_data->; //uint16_t *myVals = um_data->; //int16_t sample = um_data->; @@ -788,43 +783,43 @@ class AudioReactive : public Usermod { delay(100); // Give that poor microphone some time to setup. switch (dmType) { case 1: - DEBUGSR_PRINTLN("AS: Generic I2S Microphone."); + DEBUGSR_PRINTLN(F("AS: Generic I2S Microphone.")); audioSource = new I2SSource(SAMPLE_RATE, BLOCK_SIZE, 0, 0xFFFFFFFF); delay(100); - audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin); + if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin); break; case 2: - DEBUGSR_PRINTLN("AS: ES7243 Microphone."); + DEBUGSR_PRINTLN(F("AS: ES7243 Microphone.")); audioSource = new ES7243(SAMPLE_RATE, BLOCK_SIZE, 0, 0xFFFFFFFF); delay(100); - audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin); + if (audioSource) audioSource->initialize(sdaPin, sclPin, i2swsPin, i2ssdPin, i2sckPin); break; case 3: - DEBUGSR_PRINTLN("AS: SPH0645 Microphone"); + DEBUGSR_PRINTLN(F("AS: SPH0645 Microphone")); audioSource = new SPH0654(SAMPLE_RATE, BLOCK_SIZE, 0, 0xFFFFFFFF); delay(100); audioSource->initialize(i2swsPin, i2ssdPin, i2sckPin); break; case 4: - DEBUGSR_PRINTLN("AS: Generic I2S Microphone with Master Clock"); + DEBUGSR_PRINTLN(F("AS: Generic I2S Microphone with Master Clock")); audioSource = new I2SSourceWithMasterClock(SAMPLE_RATE, BLOCK_SIZE, 0, 0xFFFFFFFF); delay(100); - audioSource->initialize(mclkPin, i2swsPin, i2ssdPin, i2sckPin); + if (audioSource) audioSource->initialize(mclkPin, i2swsPin, i2ssdPin, i2sckPin); break; case 5: - DEBUGSR_PRINTLN("AS: I2S PDM Microphone"); + DEBUGSR_PRINTLN(F("AS: I2S PDM Microphone")); audioSource = new I2SPdmSource(SAMPLE_RATE, BLOCK_SIZE, 0, 0xFFFFFFFF); delay(100); - audioSource->initialize(i2swsPin, i2ssdPin); + if (audioSource) audioSource->initialize(i2swsPin, i2ssdPin); break; case 0: default: - DEBUGSR_PRINTLN("AS: Analog Microphone."); + DEBUGSR_PRINTLN(F("AS: Analog Microphone.")); // we don't do the down-shift by 16bit any more //audioSource = new I2SAdcSource(SAMPLE_RATE, BLOCK_SIZE, -4, 0x0FFF); // request upscaling to 16bit - still produces too much noise audioSource = new I2SAdcSource(SAMPLE_RATE, BLOCK_SIZE, 0, 0x0FFF); // keep at 12bit - less noise delay(100); - audioSource->initialize(audioPin); + if (audioSource) audioSource->initialize(audioPin); break; } diff --git a/wled00/FX.cpp b/wled00/FX.cpp index 99836f8d..aefc57ec 100644 --- a/wled00/FX.cpp +++ b/wled00/FX.cpp @@ -5478,43 +5478,6 @@ uint16_t WS2812FX::mode_2Dtartan(void) { // By: Elliott Kember https:/ static const char *_data_FX_MODE_TARTAN PROGMEM = "2D Tartan@X scale,Y scale;;!"; -///////////////////////// -// * 2D Waverly // -///////////////////////// -uint16_t WS2812FX::mode_2DWaverly(void) { // By: Stepko, https://editor.soulmatelights.com/gallery/652-wave , modified by Andrew Tuline - if (!isMatrix) return mode_static(); // not a 2D set-up - - const uint16_t cols = SEGMENT.virtualWidth(); - const uint16_t rows = SEGMENT.virtualHeight(); - const uint16_t dataSize = sizeof(CRGB) * SEGMENT.width() * SEGMENT.height(); // using width*height prevents reallocation if mirroring is enabled - - if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed - CRGB *leds = reinterpret_cast(SEGENV.data); - - if (SEGENV.call == 0) fill_solid(leds, CRGB::Black); - - fadeToBlackBy(leds, SEGMENT.speed); - - long t = now / 2; - for (uint16_t i = 0; i < cols; i++) { - //uint8_t tmpSound = (soundAgc) ? sampleAgc : sampleAvg; - - uint16_t thisVal = /*tmpSound*/((SEGMENT.intensity>>2)+1) * inoise8(i * 45 , t , t)/64; - uint16_t thisMax = map(thisVal, 0, 512, 0, rows); - - for (uint16_t j = 0; j < thisMax; j++) { - leds[XY(i, j)] += ColorFromPalette(currentPalette, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND); - leds[XY((cols - 1) - i, (rows - 1) - j)] += ColorFromPalette(currentPalette, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND); - } - } - blur2d(leds, 16); - - setPixels(leds); - return FRAMETIME; -} // mode_2DWaverly() -static const char *_data_FX_MODE_WAVERLY PROGMEM = "2D Waverly@Fade rate,Sensitivity;;!"; - - ///////////////////////// // 2D Akemi // ///////////////////////// @@ -6010,6 +5973,62 @@ uint16_t WS2812FX::mode_2Ddriftrose(void) { static const char *_data_FX_MODE_DRIFT_ROSE PROGMEM = "2D Drift Rose@Fade,Blur;;"; +/////////////////////////////////////////////////////////////////////////////// +//************************* audio routines ********************************** + + +///////////////////////// +// * 2D Waverly // +///////////////////////// +// By: Stepko, https://editor.soulmatelights.com/gallery/652-wave , modified by Andrew Tuline +uint16_t WS2812FX::mode_2DWaverly(void) { + if (!isMatrix) return mode_static(); // not a 2D set-up + + const uint16_t cols = SEGMENT.virtualWidth(); + const uint16_t rows = SEGMENT.virtualHeight(); + const uint16_t dataSize = sizeof(CRGB) * SEGMENT.width() * SEGMENT.height(); // using width*height prevents reallocation if mirroring is enabled + + if (!SEGENV.allocateData(dataSize)) return mode_static(); //allocation failed + CRGB *leds = reinterpret_cast(SEGENV.data); + + if (SEGENV.call == 0) { + fill_solid(leds, CRGB::Black); + } + + um_data_t *um_data; + uint8_t *soundAgc = nullptr; + float *sampleAgc, *sampleAvg; + if (usermods.getUMData(&um_data, USERMOD_ID_AUDIOREACTIVE)) { + soundAgc = (uint8_t*)um_data->u_data[9]; + sampleAgc = (float*)um_data->u_data[10]; + sampleAvg = (float*)um_data->u_data[8]; + } + + fadeToBlackBy(leds, SEGMENT.speed); + + long t = millis() / 2; + for (uint16_t i = 0; i < cols; i++) { + uint16_t thisVal = (1 + SEGMENT.intensity/64) * inoise8(i * 45 , t , t)/2; + // use audio if available + if (um_data && soundAgc) { + thisVal /= 32; // reduce intensity of inoise8() + thisVal *= (*soundAgc) ? *sampleAgc : *sampleAvg; + } + uint16_t thisMax = map(thisVal, 0, 512, 0, rows); + + for (uint16_t j = 0; j < thisMax; j++) { + leds[XY(i, j)] += ColorFromPalette(currentPalette, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND); + leds[XY((cols - 1) - i, (rows - 1) - j)] += ColorFromPalette(currentPalette, map(j, 0, thisMax, 250, 0), 255, LINEARBLEND); + } + } + blur2d(leds, 16); + + setPixels(leds); + return FRAMETIME; +} // mode_2DWaverly() +static const char *_data_FX_MODE_WAVERLY PROGMEM = " ♪ 2D Waverly@Amplification,Sensitivity=64;;!"; + + ////////////////////////////////////////////////////////////////////////////////////////// // mode data const char *WS2812FX::_modeData[MODE_COUNT] = {