Merge branch 'audioreactive-prototype' into merge-audio
This commit is contained in:
commit
67a51be9ee
File diff suppressed because it is too large
Load Diff
@ -18,19 +18,36 @@
|
||||
Until this configuration is moved to the webinterface
|
||||
*/
|
||||
|
||||
// if you have problems to get your microphone work on the left channel, uncomment the following line
|
||||
//#define I2S_USE_RIGHT_CHANNEL // (experimental) define this to use right channel (digital mics only)
|
||||
#ifdef I2S_USE_RIGHT_CHANNEL
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_RIGHT
|
||||
#define I2S_MIC_CHANNEL_TEXT "right channel only."
|
||||
#else
|
||||
#define I2S_MIC_CHANNEL I2S_CHANNEL_FMT_ONLY_LEFT
|
||||
#define I2S_MIC_CHANNEL_TEXT "left channel only."
|
||||
#endif
|
||||
|
||||
// Uncomment the line below to utilize ADC1 _exclusively_ for I2S sound input.
|
||||
// benefit: analog mic inputs will be sampled contiously -> better response times and less "glitches"
|
||||
// WARNING: this option WILL lock-up your device in case that any other analogRead() operation is performed;
|
||||
// for example if you want to read "analog buttons"
|
||||
//#define I2S_GRAB_ADC1_COMPLETELY // (experimental) continously sample analog ADC microphone. WARNING will cause analogRead() lock-up
|
||||
|
||||
// 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
|
||||
#define I2S_unsigned_datatype uint16_t
|
||||
#undef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
#else
|
||||
#define I2S_SAMPLE_RESOLUTION I2S_BITS_PER_SAMPLE_32BIT
|
||||
#define I2S_datatype int32_t
|
||||
#define I2S_unsigned_datatype uint32_t
|
||||
#define I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
#endif
|
||||
|
||||
|
||||
/* Interface class
|
||||
AudioSource serves as base class for all microphone types
|
||||
This enables accessing all microphones with one single interface
|
||||
@ -62,27 +79,26 @@ class AudioSource {
|
||||
*/
|
||||
virtual void getSamples(float *buffer, uint16_t num_samples) = 0;
|
||||
|
||||
/* Get an up-to-date sample without DC offset */
|
||||
virtual int getSampleWithoutDCOffset() { return _sampleNoDCOffset; };
|
||||
/* check if the audio source driver was initialized successfully */
|
||||
virtual bool isInitialized(void) {return(_initialized);}
|
||||
|
||||
/* identify Audiosource type - I2S-ADC or I2S-digital */
|
||||
typedef enum{Type_unknown=0, Type_I2SAdc=1, Type_I2SDigital=2} AudioSourceType;
|
||||
virtual AudioSourceType getType(void) {return(Type_I2SDigital);} // default is "I2S digital source" - ADC type overrides this method
|
||||
|
||||
protected:
|
||||
/* Post-process audio sample - currently on needed for I2SAdcSource*/
|
||||
virtual I2S_datatype postProcessSample(I2S_datatype sample_in) {return(sample_in);} // default method can be overriden by instances (ADC) that need sample postprocessing
|
||||
|
||||
// Private constructor, to make sure it is not callable except from derived classes
|
||||
AudioSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) :
|
||||
AudioSource(int sampleRate, int blockSize) :
|
||||
_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
|
||||
volatile int _sampleNoDCOffset; // Up-to-date sample without DCOffset
|
||||
float _dcOffset; // Rolling average DC offset
|
||||
int16_t _shift; // Shift obtained samples to the right (positive) or left(negative) by this amount
|
||||
uint32_t _mask; // Bitmask for sample data after shifting. Bitmask 0X0FFF means that we need to convert 12bit ADC samples from unsigned to signed
|
||||
bool _initialized; // Gets set to true if initialization is successful
|
||||
};
|
||||
|
||||
@ -91,13 +107,13 @@ class AudioSource {
|
||||
*/
|
||||
class I2SSource : public AudioSource {
|
||||
public:
|
||||
I2SSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) :
|
||||
AudioSource(sampleRate, blockSize, lshift, mask) {
|
||||
I2SSource(int sampleRate, int blockSize) :
|
||||
AudioSource(sampleRate, blockSize) {
|
||||
_config = {
|
||||
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
|
||||
.sample_rate = _sampleRate,
|
||||
.bits_per_sample = I2S_SAMPLE_RESOLUTION,
|
||||
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
|
||||
.channel_format = I2S_MIC_CHANNEL,
|
||||
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 2, 0)
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_STAND_I2S),
|
||||
#else
|
||||
@ -176,9 +192,6 @@ class I2SSource : public AudioSource {
|
||||
size_t bytes_read = 0; /* Counter variable to check if we actually got enough data */
|
||||
I2S_datatype newSamples[num_samples]; /* Intermediary sample storage */
|
||||
|
||||
// Reset dc offset
|
||||
_dcOffset = 0.0f;
|
||||
|
||||
err = i2s_read(I2S_NUM_0, (void *)newSamples, sizeof(newSamples), &bytes_read, portMAX_DELAY);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to get samples: %d\n", err);
|
||||
@ -193,30 +206,17 @@ 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
|
||||
if (_shift != 0)
|
||||
newSamples[i] >>= 16;
|
||||
#endif
|
||||
float currSample = 0.0f;
|
||||
if(_shift > 0)
|
||||
currSample = (float) (newSamples[i] >> _shift);
|
||||
else {
|
||||
if(_shift < 0)
|
||||
currSample = (float) (newSamples[i] << (- _shift)); // need to "pump up" 12bit ADC to full 16bit as delivered by other digital mics
|
||||
else
|
||||
#ifdef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
currSample = (float) newSamples[i] / 65536.0f; // _shift == 0 -> use the chance to keep lower 16bits
|
||||
#else
|
||||
currSample = (float) newSamples[i];
|
||||
#endif
|
||||
}
|
||||
buffer[i] = currSample;
|
||||
_dcOffset = ((_dcOffset * 31) + currSample) / 32;
|
||||
}
|
||||
|
||||
// Update no-DC sample
|
||||
_sampleNoDCOffset = buffer[num_samples - 1] - _dcOffset;
|
||||
newSamples[i] = postProcessSample(newSamples[i]); // perform postprocessing (needed for ADC samples)
|
||||
|
||||
float currSample = 0.0f;
|
||||
#ifdef I2S_SAMPLE_DOWNSCALE_TO_16BIT
|
||||
currSample = (float) newSamples[i] / 65536.0f; // 32bit input -> 16bit; keeping lower 16bits as decimal places
|
||||
#else
|
||||
currSample = (float) newSamples[i]; // 16bit input -> use as-is
|
||||
#endif
|
||||
buffer[i] = currSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -275,8 +275,8 @@ class ES7243 : public I2SSource {
|
||||
}
|
||||
|
||||
public:
|
||||
ES7243(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) :
|
||||
I2SSource(sampleRate, blockSize, lshift, mask) {
|
||||
ES7243(int sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize) {
|
||||
_config.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT;
|
||||
};
|
||||
|
||||
@ -314,8 +314,8 @@ public:
|
||||
*/
|
||||
class I2SAdcSource : public I2SSource {
|
||||
public:
|
||||
I2SAdcSource(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) :
|
||||
I2SSource(sampleRate, blockSize, lshift, mask) {
|
||||
I2SAdcSource(int sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize) {
|
||||
_config = {
|
||||
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_ADC_BUILT_IN),
|
||||
.sample_rate = _sampleRate,
|
||||
@ -326,14 +326,22 @@ class I2SAdcSource : public I2SSource {
|
||||
#else
|
||||
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S | I2S_COMM_FORMAT_I2S_MSB),
|
||||
#endif
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL2,
|
||||
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
|
||||
.dma_buf_count = 8,
|
||||
.dma_buf_len = _blockSize
|
||||
.dma_buf_len = _blockSize,
|
||||
.use_apll = false,
|
||||
.tx_desc_auto_clear = false,
|
||||
.fixed_mclk = 0
|
||||
};
|
||||
}
|
||||
|
||||
/* identify Audiosource type - I2S-ADC*/
|
||||
AudioSourceType getType(void) {return(Type_I2SAdc);}
|
||||
|
||||
void initialize(int8_t audioPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
_myADCchannel = 0x0F;
|
||||
if(!pinManager.allocatePin(audioPin, false, PinOwner::UM_Audioreactive)) {
|
||||
DEBUGSR_PRINTF("failed to allocate GPIO for audio analog input: %d\n", audioPin);
|
||||
return;
|
||||
}
|
||||
_audioPin = audioPin;
|
||||
@ -345,6 +353,7 @@ class I2SAdcSource : public I2SSource {
|
||||
return;
|
||||
} else {
|
||||
adc_gpio_init(ADC_UNIT_1, adc_channel_t(channel));
|
||||
_myADCchannel = channel;
|
||||
}
|
||||
|
||||
// Install Driver
|
||||
@ -360,61 +369,115 @@ class I2SAdcSource : public I2SSource {
|
||||
DEBUGSR_PRINTF("Failed to set i2s adc mode: %d\n", err);
|
||||
return;
|
||||
}
|
||||
// adc1_config_channel_atten(adc1_channel_t(channel), ADC_ATTEN_DB_11)); //see https://github.com/espressif/arduino-esp32/blob/master/libraries/ESP32/examples/I2S/HiFreq_ADC/HiFreq_ADC.ino
|
||||
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
#if defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// according to docs from espressif, the ADC needs to be started explicitly
|
||||
// fingers crossed
|
||||
err = i2s_adc_enable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to enable i2s adc: %d\n", err);
|
||||
//return;
|
||||
}
|
||||
#endif
|
||||
err = i2s_adc_enable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to enable i2s adc: %d\n", err);
|
||||
//return;
|
||||
}
|
||||
#else
|
||||
err = i2s_adc_disable(I2S_NUM_0);
|
||||
//err = i2s_stop(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to initially disable i2s adc: %d\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
|
||||
I2S_datatype postProcessSample(I2S_datatype sample_in) {
|
||||
static I2S_datatype lastADCsample = 0; // last good sample
|
||||
static unsigned int broken_samples_counter = 0; // number of consecutive broken (and fixed) ADC samples
|
||||
I2S_datatype sample_out = 0;
|
||||
|
||||
// bring sample down down to 16bit unsigned
|
||||
I2S_unsigned_datatype rawData = * reinterpret_cast<I2S_unsigned_datatype *> (&sample_in); // C++ acrobatics to get sample as "unsigned"
|
||||
#ifndef I2S_USE_16BIT_SAMPLES
|
||||
rawData = (rawData >> 16) & 0xFFFF; // scale input down from 32bit -> 16bit
|
||||
I2S_datatype lastGoodSample = lastADCsample / 16384 ; // prepare "last good sample" accordingly (26bit-> 12bit with correct sign handling)
|
||||
#else
|
||||
rawData = rawData & 0xFFFF; // input is already in 16bit, just mask off possible junk
|
||||
I2S_datatype lastGoodSample = lastADCsample * 4; // prepare "last good sample" accordingly (10bit-> 12bit)
|
||||
#endif
|
||||
|
||||
// decode ADC sample data fields
|
||||
uint16_t the_channel = (rawData >> 12) & 0x000F; // upper 4 bit = ADC channel
|
||||
uint16_t the_sample = rawData & 0x0FFF; // lower 12bit -> ADC sample (unsigned)
|
||||
I2S_datatype finalSample = (int(the_sample) - 2048); // convert unsigned sample to signed (centered at 0);
|
||||
|
||||
if ((the_channel != _myADCchannel) && (_myADCchannel != 0x0F)) { // 0x0F means "don't know what my channel is"
|
||||
// fix bad sample
|
||||
finalSample = lastGoodSample; // replace with last good ADC sample
|
||||
broken_samples_counter ++;
|
||||
if (broken_samples_counter > 256) _myADCchannel = 0x0F; // too many bad samples in a row -> disable sample corrections
|
||||
//Serial.print("\n!ADC rogue sample 0x"); Serial.print(rawData, HEX); Serial.print("\tchannel:");Serial.println(the_channel);
|
||||
} else broken_samples_counter = 0; // good sample - reset counter
|
||||
|
||||
// back to original resolution
|
||||
#ifndef I2S_USE_16BIT_SAMPLES
|
||||
finalSample = finalSample << 16; // scale up from 16bit -> 32bit;
|
||||
#endif
|
||||
|
||||
finalSample = finalSample / 4; // mimic old analog driver behaviour (12bit -> 10bit)
|
||||
sample_out = (3 * finalSample + lastADCsample) / 4; // apply low-pass filter (2-tap FIR)
|
||||
//sample_out = (finalSample + lastADCsample) / 2; // apply stronger low-pass filter (2-tap FIR)
|
||||
|
||||
lastADCsample = sample_out; // update ADC last sample
|
||||
return(sample_out);
|
||||
}
|
||||
|
||||
|
||||
void getSamples(float *buffer, uint16_t num_samples) {
|
||||
/* Enable ADC. This has to be enabled and disabled directly before and
|
||||
* after sampling, otherwise Wifi dies
|
||||
*/
|
||||
if (_initialized) {
|
||||
#if !defined(ARDUINO_ARCH_ESP32)
|
||||
// old code - works for me without enable/disable, at least on ESP32.
|
||||
esp_err_t err = i2s_adc_enable(I2S_NUM_0);
|
||||
//esp_err_t err = i2s_start(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to enable i2s adc: %d\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if !defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// old code - works for me without enable/disable, at least on ESP32.
|
||||
//esp_err_t err = i2s_start(I2S_NUM_0);
|
||||
esp_err_t err = i2s_adc_enable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to enable i2s adc: %d\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
I2SSource::getSamples(buffer, num_samples);
|
||||
|
||||
#if !defined(ARDUINO_ARCH_ESP32)
|
||||
// old code - works for me without enable/disable, at least on ESP32.
|
||||
err = i2s_adc_disable(I2S_NUM_0);
|
||||
//err = i2s_stop(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to disable i2s adc: %d\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#if !defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// old code - works for me without enable/disable, at least on ESP32.
|
||||
err = i2s_adc_disable(I2S_NUM_0); //i2s_adc_disable() may cause crash with IDF 4.4 (https://github.com/espressif/arduino-esp32/issues/6832)
|
||||
//err = i2s_stop(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to disable i2s adc: %d\n", err);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void deinitialize() {
|
||||
pinManager.deallocatePin(_audioPin, PinOwner::UM_Audioreactive);
|
||||
_initialized = false;
|
||||
_myADCchannel = 0x0F;
|
||||
|
||||
esp_err_t err;
|
||||
#if defined(ARDUINO_ARCH_ESP32)
|
||||
// according to docs from espressif, the ADC needs to be stopped explicitly
|
||||
// fingers crossed
|
||||
err = i2s_adc_disable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to disable i2s adc: %d\n", err);
|
||||
//return;
|
||||
}
|
||||
#endif
|
||||
#if defined(I2S_GRAB_ADC1_COMPLETELY)
|
||||
// according to docs from espressif, the ADC needs to be stopped explicitly
|
||||
// fingers crossed
|
||||
err = i2s_adc_disable(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to disable i2s adc: %d\n", err);
|
||||
}
|
||||
#endif
|
||||
|
||||
i2s_stop(I2S_NUM_0);
|
||||
err = i2s_driver_uninstall(I2S_NUM_0);
|
||||
if (err != ESP_OK) {
|
||||
DEBUGSR_PRINTF("Failed to uninstall i2s driver: %d\n", err);
|
||||
@ -424,6 +487,7 @@ class I2SAdcSource : public I2SSource {
|
||||
|
||||
private:
|
||||
int8_t _audioPin;
|
||||
int8_t _myADCchannel = 0x0F; // current ADC channel for analog input. 0x0F means "undefined"
|
||||
};
|
||||
|
||||
/* SPH0645 Microphone
|
||||
@ -432,8 +496,8 @@ class I2SAdcSource : public I2SSource {
|
||||
*/
|
||||
class SPH0654 : public I2SSource {
|
||||
public:
|
||||
SPH0654(int sampleRate, int blockSize, int16_t lshift, uint32_t mask) :
|
||||
I2SSource(sampleRate, blockSize, lshift, mask)
|
||||
SPH0654(int sampleRate, int blockSize) :
|
||||
I2SSource(sampleRate, blockSize)
|
||||
{}
|
||||
|
||||
void initialize(uint8_t i2swsPin, uint8_t i2ssdPin, uint8_t i2sckPin, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE, int8_t = I2S_PIN_NO_CHANGE) {
|
||||
|
@ -6157,7 +6157,8 @@ uint16_t mode_gravcenter(void) { // Gravcenter. By Andrew Tuline.
|
||||
}
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
|
||||
SEGMENT.fade_out(240);
|
||||
//SEGMENT.fade_out(240);
|
||||
SEGMENT.fade_out(251); // 30%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0f;
|
||||
segmentSampleAvg *= 0.125; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
@ -6206,8 +6207,9 @@ uint16_t mode_gravcentric(void) { // Gravcentric. By Andrew
|
||||
|
||||
// printUmData();
|
||||
|
||||
SEGMENT.fade_out(240);
|
||||
SEGMENT.fade_out(240); // twice? really?
|
||||
//SEGMENT.fade_out(240);
|
||||
//SEGMENT.fade_out(240); // twice? really?
|
||||
SEGMENT.fade_out(253); // 50%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0;
|
||||
segmentSampleAvg *= 0.125f; // divide by 8, to compensate for later "sensitivty" upscaling
|
||||
@ -6254,7 +6256,8 @@ uint16_t mode_gravimeter(void) { // Gravmeter. By Andrew Tuline.
|
||||
}
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
|
||||
SEGMENT.fade_out(240);
|
||||
//SEGMENT.fade_out(240);
|
||||
SEGMENT.fade_out(249); // 25%
|
||||
|
||||
float segmentSampleAvg = volumeSmth * (float)SEGMENT.intensity / 255.0;
|
||||
segmentSampleAvg *= 0.25; // divide by 4, to compensate for later "sensitivty" upscaling
|
||||
@ -6294,7 +6297,7 @@ uint16_t mode_juggles(void) { // Juggles. By Andrew Tuline.
|
||||
}
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
|
||||
SEGMENT.fade_out(224);
|
||||
SEGMENT.fade_out(224); // 6.25%
|
||||
uint16_t my_sampleAgc = fmax(fmin(volumeSmth, 255.0), 0);
|
||||
|
||||
for (size_t i=0; i<SEGMENT.intensity/32+1U; i++) {
|
||||
@ -6419,11 +6422,13 @@ uint16_t mode_noisemeter(void) { // Noisemeter. By Andrew Tuline.
|
||||
float volumeSmth = *(float*) um_data->u_data[0];
|
||||
int16_t volumeRaw = *(int16_t*)um_data->u_data[1];
|
||||
|
||||
uint8_t fadeRate = map(SEGMENT.speed,0,255,224,255);
|
||||
//uint8_t fadeRate = map(SEGMENT.speed,0,255,224,255);
|
||||
uint8_t fadeRate = map(SEGMENT.speed,0,255,200,254);
|
||||
SEGMENT.fade_out(fadeRate);
|
||||
|
||||
float tmpSound2 = volumeRaw * 2.0 * (float)SEGMENT.intensity / 255.0;
|
||||
int maxLen = mapf(tmpSound2, 0, 255, 0, SEGLEN); // map to pixels availeable in current segment // Still a bit too sensitive.
|
||||
if (maxLen <0) maxLen = 0;
|
||||
if (maxLen >SEGLEN) maxLen = SEGLEN;
|
||||
|
||||
for (int i=0; i<maxLen; i++) { // The louder the sound, the wider the soundbar. By Andrew Tuline.
|
||||
@ -6521,7 +6526,7 @@ static const char _data_FX_MODE_PLASMOID[] PROGMEM = "Plasmoid@Phase,# of pixels
|
||||
uint16_t mode_puddlepeak(void) { // Puddlepeak. By Andrew Tuline.
|
||||
|
||||
uint16_t size = 0;
|
||||
uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 255);
|
||||
uint8_t fadeVal = map(SEGMENT.speed,0,255, 224, 254);
|
||||
uint16_t pos = random(SEGLEN); // Set a random starting position.
|
||||
|
||||
um_data_t *um_data;
|
||||
@ -6563,7 +6568,7 @@ static const char _data_FX_MODE_PUDDLEPEAK[] PROGMEM = "Puddlepeak@Fade rate,Pud
|
||||
//////////////////////
|
||||
uint16_t mode_puddles(void) { // Puddles. By Andrew Tuline.
|
||||
uint16_t size = 0;
|
||||
uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 255);
|
||||
uint8_t fadeVal = map(SEGMENT.speed, 0, 255, 224, 254);
|
||||
uint16_t pos = random16(SEGLEN); // Set a random starting position.
|
||||
|
||||
SEGMENT.fade_out(fadeVal);
|
||||
@ -6714,10 +6719,13 @@ uint16_t mode_freqmap(void) { // Map FFT_MajorPeak to SEGLEN.
|
||||
|
||||
SEGMENT.fade_out(SEGMENT.speed);
|
||||
|
||||
uint16_t locn = (log10f((float)FFT_MajorPeak) - 1.78f) * (float)SEGLEN/(3.71f-1.78f); // log10 frequency range is from 1.78 to 3.71. Let's scale to SEGLEN.
|
||||
// int locn = (log10f((float)FFT_MajorPeak) - 1.78f) * (float)SEGLEN/(3.71f-1.78f); // log10 frequency range is from 1.78 to 3.71. Let's scale to SEGLEN.
|
||||
int locn = (log10f((float)FFT_MajorPeak) - 1.78f) * (float)SEGLEN/(4.0102f-1.78f); // log10 frequency range is from 1.78 to 3.71. Let's scale to SEGLEN.
|
||||
if (locn < 1) locn = 0; // avoid underflow
|
||||
|
||||
if (locn >=SEGLEN) locn = SEGLEN-1;
|
||||
uint16_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(3.71f-1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
//uint16_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(3.71f-1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
uint16_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(4.0102f-1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
uint16_t bright = (int)my_magnitude;
|
||||
|
||||
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), bright));
|
||||
@ -6756,7 +6764,8 @@ uint16_t mode_freqmatrix(void) { // Freqmatrix. By Andreas Plesch
|
||||
|
||||
CRGB color = CRGB::Black;
|
||||
|
||||
if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0;
|
||||
//if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0;
|
||||
if (FFT_MajorPeak > 10240) FFT_MajorPeak = 0;
|
||||
// MajorPeak holds the freq. value which is most abundant in the last sample.
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz
|
||||
// we will treat everything with less than 65Hz as 0
|
||||
@ -6803,7 +6812,8 @@ uint16_t mode_freqpixels(void) { // Freqpixel. By Andrew Tuline.
|
||||
|
||||
for (int i=0; i < SEGMENT.intensity/32+1; i++) {
|
||||
uint16_t locn = random16(0,SEGLEN);
|
||||
uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78) * 255.0/(3.71-1.78); // Scale log10 of frequency values to the 255 colour index.
|
||||
//uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78) * 255.0/(3.71-1.78); // Scale log10 of frequency values to the 255 colour index.
|
||||
uint8_t pixCol = (log10f(FFT_MajorPeak) - 1.78f) * 255.0f/(4.0102f-1.78f); // Scale log10 of frequency values to the 255 colour index.
|
||||
SEGMENT.setPixelColor(locn, color_blend(SEGCOLOR(1), SEGMENT.color_from_palette(SEGMENT.intensity+pixCol, false, PALETTE_SOLID_WRAP, 0), (int)my_magnitude));
|
||||
}
|
||||
|
||||
@ -6853,7 +6863,8 @@ uint16_t mode_freqwave(void) { // Freqwave. By Andreas Pleschun
|
||||
|
||||
CRGB color = 0;
|
||||
|
||||
if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0.0f;
|
||||
//if (FFT_MajorPeak > 5120) FFT_MajorPeak = 0.0f;
|
||||
if (FFT_MajorPeak > 10240) FFT_MajorPeak = 0.0f;
|
||||
// MajorPeak holds the freq. value which is most abundant in the last sample.
|
||||
// With our sampling rate of 10240Hz we have a usable freq range from roughtly 80Hz to 10240/2 Hz
|
||||
// we will treat everything with less than 65Hz as 0
|
||||
@ -6909,7 +6920,8 @@ uint16_t mode_gravfreq(void) { // Gravfreq. By Andrew Tuline.
|
||||
|
||||
for (int i=0; i<tempsamp; i++) {
|
||||
|
||||
uint8_t index = (log10((int)FFT_MajorPeak) - (3.71-1.78)) * 255; //int? shouldn't it be floor() or similar
|
||||
//uint8_t index = (log10((int)FFT_MajorPeak) - (3.71-1.78)) * 255; //int? shouldn't it be floor() or similar
|
||||
uint8_t index = (log10f(FFT_MajorPeak) - (4.0102f-1.78f)) * 255; //int? shouldn't it be floor() or similar
|
||||
|
||||
SEGMENT.setPixelColor(i+SEGLEN/2, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||
SEGMENT.setPixelColor(SEGLEN/2-i-1, SEGMENT.color_from_palette(index, false, PALETTE_SOLID_WRAP, 0));
|
||||
|
@ -216,10 +216,13 @@ void handleAnalog(uint8_t b)
|
||||
void handleButton()
|
||||
{
|
||||
static unsigned long lastRead = 0UL;
|
||||
static unsigned long lastRun = 0UL;
|
||||
bool analog = false;
|
||||
unsigned long now = millis();
|
||||
|
||||
if (strip.isUpdating()) return; // don't interfere with strip updates. Our button will still be there in 1ms (next cycle)
|
||||
//if (strip.isUpdating()) return; // don't interfere with strip updates. Our button will still be there in 1ms (next cycle)
|
||||
if (strip.isUpdating() && (millis() - lastRun < 400)) return; // be niced, but avoid button starvation
|
||||
lastRun = millis();
|
||||
|
||||
for (uint8_t b=0; b<WLED_MAX_BUTTONS; b++) {
|
||||
#ifdef ESP8266
|
||||
|
Loading…
Reference in New Issue
Block a user