mirror of
https://github.com/wled/WLED.git
synced 2025-07-19 08:46:34 +00:00
audiosync receive improvements (maintainer edit)
* fixed a few typo's in comments * fixed 8266 specific warning about 'comparison of integer expressions of different signedness' based on recommendations made by @willmmiles: * make sure that audioSyncPacket is the same size (44bytes) on all platforms * use static buffer for receiving (avoids heap fragmentation) * copy receive buffer to local audioSyncPacket struct - avoids alignment problems * esp32 only: to stay in sync with UDP, Udp.flush() is needed when Udp.parsePacket() is _not_ followed by Udp.read()
This commit is contained in:
parent
cc9db0220c
commit
3a8e19d1b4
@ -76,7 +76,7 @@ static uint8_t soundAgc = 0; // Automagic gain control: 0 - n
|
|||||||
static float FFT_MajorPeak = 1.0f; // FFT: strongest (peak) frequency
|
static float FFT_MajorPeak = 1.0f; // FFT: strongest (peak) frequency
|
||||||
static float FFT_Magnitude = 0.0f; // FFT: volume (magnitude) of peak frequency
|
static float FFT_Magnitude = 0.0f; // FFT: volume (magnitude) of peak frequency
|
||||||
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
|
static bool samplePeak = false; // Boolean flag for peak - used in effects. Responding routine may reset this flag. Auto-reset after strip.getMinShowDelay()
|
||||||
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same tiem as samplePeak, but reset by transmitAudioData
|
static bool udpSamplePeak = false; // Boolean flag for peak. Set at the same time as samplePeak, but reset by transmitAudioData
|
||||||
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
|
static unsigned long timeOfPeak = 0; // time of last sample peak detection.
|
||||||
static uint8_t fftResult[NUM_GEQ_CHANNELS]= {0};// Our calculated freq. channel result table to be used by effects
|
static uint8_t fftResult[NUM_GEQ_CHANNELS]= {0};// Our calculated freq. channel result table to be used by effects
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ static uint16_t decayTime = 1400; // int: decay time in milliseconds
|
|||||||
|
|
||||||
// peak detection
|
// peak detection
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
static void detectSamplePeak(void); // peak detection function (needs scaled FFT reasults in vReal[]) - no used for 8266 receive-only mode
|
static void detectSamplePeak(void); // peak detection function (needs scaled FFT results in vReal[]) - no used for 8266 receive-only mode
|
||||||
#endif
|
#endif
|
||||||
static void autoResetPeak(void); // peak auto-reset function
|
static void autoResetPeak(void); // peak auto-reset function
|
||||||
static uint8_t maxVol = 31; // (was 10) Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
static uint8_t maxVol = 31; // (was 10) Reasonable value for constant volume for 'peak detector', as it won't always trigger (deprecated)
|
||||||
@ -587,19 +587,21 @@ class AudioReactive : public Usermod {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// new "V2" audiosync struct - 40 Bytes
|
// new "V2" audiosync struct - 44 Bytes
|
||||||
struct audioSyncPacket {
|
struct __attribute__ ((packed)) audioSyncPacket { // "packed" ensures that there are no additional gaps
|
||||||
char header[6]; // 06 Bytes
|
char header[6]; // 06 Bytes offset 0
|
||||||
float sampleRaw; // 04 Bytes - either "sampleRaw" or "rawSampleAgc" depending on soundAgc setting
|
uint8_t reserved1[2]; // 02 Bytes, offset 6 - gap required by the compiler - not used yet
|
||||||
float sampleSmth; // 04 Bytes - either "sampleAvg" or "sampleAgc" depending on soundAgc setting
|
float sampleRaw; // 04 Bytes offset 8 - either "sampleRaw" or "rawSampleAgc" depending on soundAgc setting
|
||||||
uint8_t samplePeak; // 01 Bytes - 0 no peak; >=1 peak detected. In future, this will also provide peak Magnitude
|
float sampleSmth; // 04 Bytes offset 12 - either "sampleAvg" or "sampleAgc" depending on soundAgc setting
|
||||||
uint8_t reserved1; // 01 Bytes - for future extensions - not used yet
|
uint8_t samplePeak; // 01 Bytes offset 16 - 0 no peak; >=1 peak detected. In future, this will also provide peak Magnitude
|
||||||
uint8_t fftResult[16]; // 16 Bytes
|
uint8_t reserved2; // 01 Bytes offset 17 - for future extensions - not used yet
|
||||||
float FFT_Magnitude; // 04 Bytes
|
uint8_t fftResult[16]; // 16 Bytes offset 18
|
||||||
float FFT_MajorPeak; // 04 Bytes
|
uint16_t reserved3; // 02 Bytes, offset 34 - gap required by the compiler - not used yet
|
||||||
|
float FFT_Magnitude; // 04 Bytes offset 36
|
||||||
|
float FFT_MajorPeak; // 04 Bytes offset 40
|
||||||
};
|
};
|
||||||
|
|
||||||
// old "V1" audiosync struct - 83 Bytes - for backwards compatibility
|
// old "V1" audiosync struct - 83 Bytes payload, 88 bytes total (with padding added by compiler) - for backwards compatibility
|
||||||
struct audioSyncPacket_v1 {
|
struct audioSyncPacket_v1 {
|
||||||
char header[6]; // 06 Bytes
|
char header[6]; // 06 Bytes
|
||||||
uint8_t myVals[32]; // 32 Bytes
|
uint8_t myVals[32]; // 32 Bytes
|
||||||
@ -612,6 +614,8 @@ class AudioReactive : public Usermod {
|
|||||||
double FFT_MajorPeak; // 08 Bytes
|
double FFT_MajorPeak; // 08 Bytes
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define UDPSOUND_MAX_PACKET 88 // max packet size for audiosync
|
||||||
|
|
||||||
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
|
// set your config variables to their boot default value (this can also be done in readFromConfig() or a constructor if you prefer)
|
||||||
#ifdef UM_AUDIOREACTIVE_ENABLE
|
#ifdef UM_AUDIOREACTIVE_ENABLE
|
||||||
bool enabled = true;
|
bool enabled = true;
|
||||||
@ -997,7 +1001,6 @@ class AudioReactive : public Usermod {
|
|||||||
transmitData.sampleSmth = (soundAgc) ? sampleAgc : sampleAvg;
|
transmitData.sampleSmth = (soundAgc) ? sampleAgc : sampleAvg;
|
||||||
transmitData.samplePeak = udpSamplePeak ? 1:0;
|
transmitData.samplePeak = udpSamplePeak ? 1:0;
|
||||||
udpSamplePeak = false; // Reset udpSamplePeak after we've transmitted it
|
udpSamplePeak = false; // Reset udpSamplePeak after we've transmitted it
|
||||||
transmitData.reserved1 = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) {
|
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) {
|
||||||
transmitData.fftResult[i] = (uint8_t)constrain(fftResult[i], 0, 254);
|
transmitData.fftResult[i] = (uint8_t)constrain(fftResult[i], 0, 254);
|
||||||
@ -1023,10 +1026,13 @@ class AudioReactive : public Usermod {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void decodeAudioData(int packetSize, uint8_t *fftBuff) {
|
void decodeAudioData(int packetSize, uint8_t *fftBuff) {
|
||||||
audioSyncPacket *receivedPacket = reinterpret_cast<audioSyncPacket*>(fftBuff);
|
audioSyncPacket receivedPacket;
|
||||||
|
memset(&receivedPacket, 0, sizeof(receivedPacket)); // start clean
|
||||||
|
memcpy(&receivedPacket, fftBuff, min((unsigned)packetSize, (unsigned)sizeof(receivedPacket))); // don't violate alignment - thanks @willmmiles#
|
||||||
|
|
||||||
// update samples for effects
|
// update samples for effects
|
||||||
volumeSmth = fmaxf(receivedPacket->sampleSmth, 0.0f);
|
volumeSmth = fmaxf(receivedPacket.sampleSmth, 0.0f);
|
||||||
volumeRaw = fmaxf(receivedPacket->sampleRaw, 0.0f);
|
volumeRaw = fmaxf(receivedPacket.sampleRaw, 0.0f);
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
// update internal samples
|
// update internal samples
|
||||||
sampleRaw = volumeRaw;
|
sampleRaw = volumeRaw;
|
||||||
@ -1039,15 +1045,15 @@ class AudioReactive : public Usermod {
|
|||||||
// If it's true already, then the animation still needs to respond.
|
// If it's true already, then the animation still needs to respond.
|
||||||
autoResetPeak();
|
autoResetPeak();
|
||||||
if (!samplePeak) {
|
if (!samplePeak) {
|
||||||
samplePeak = receivedPacket->samplePeak >0 ? true:false;
|
samplePeak = receivedPacket.samplePeak >0 ? true:false;
|
||||||
if (samplePeak) timeOfPeak = millis();
|
if (samplePeak) timeOfPeak = millis();
|
||||||
//userVar1 = samplePeak;
|
//userVar1 = samplePeak;
|
||||||
}
|
}
|
||||||
//These values are only computed by ESP32
|
//These values are only computed by ESP32
|
||||||
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) fftResult[i] = receivedPacket->fftResult[i];
|
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) fftResult[i] = receivedPacket.fftResult[i];
|
||||||
my_magnitude = fmaxf(receivedPacket->FFT_Magnitude, 0.0f);
|
my_magnitude = fmaxf(receivedPacket.FFT_Magnitude, 0.0f);
|
||||||
FFT_Magnitude = my_magnitude;
|
FFT_Magnitude = my_magnitude;
|
||||||
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
FFT_MajorPeak = constrain(receivedPacket.FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
|
||||||
}
|
}
|
||||||
|
|
||||||
void decodeAudioData_v1(int packetSize, uint8_t *fftBuff) {
|
void decodeAudioData_v1(int packetSize, uint8_t *fftBuff) {
|
||||||
@ -1084,9 +1090,12 @@ class AudioReactive : public Usermod {
|
|||||||
bool haveFreshData = false;
|
bool haveFreshData = false;
|
||||||
|
|
||||||
size_t packetSize = fftUdp.parsePacket();
|
size_t packetSize = fftUdp.parsePacket();
|
||||||
if (packetSize > 5) {
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
|
if ((packetSize > 0) && ((packetSize < 5) || (packetSize > UDPSOUND_MAX_PACKET))) fftUdp.flush(); // discard invalid packets (too small or too big) - only works on esp32
|
||||||
|
#endif
|
||||||
|
if ((packetSize > 5) && (packetSize <= UDPSOUND_MAX_PACKET)) {
|
||||||
//DEBUGSR_PRINTLN("Received UDP Sync Packet");
|
//DEBUGSR_PRINTLN("Received UDP Sync Packet");
|
||||||
uint8_t fftBuff[packetSize];
|
static uint8_t fftBuff[UDPSOUND_MAX_PACKET+1] = { 0 }; // static buffer for receiving, to reuse the same memory and avoid heap fragmentation
|
||||||
fftUdp.read(fftBuff, packetSize);
|
fftUdp.read(fftBuff, packetSize);
|
||||||
|
|
||||||
// VERIFY THAT THIS IS A COMPATIBLE PACKET
|
// VERIFY THAT THIS IS A COMPATIBLE PACKET
|
||||||
@ -1229,7 +1238,7 @@ class AudioReactive : public Usermod {
|
|||||||
|
|
||||||
if (!audioSource) enabled = false; // audio failed to initialise
|
if (!audioSource) enabled = false; // audio failed to initialise
|
||||||
#endif
|
#endif
|
||||||
if (enabled) onUpdateBegin(false); // create FFT task, and initailize network
|
if (enabled) onUpdateBegin(false); // create FFT task, and initialize network
|
||||||
|
|
||||||
|
|
||||||
#ifdef ARDUINO_ARCH_ESP32
|
#ifdef ARDUINO_ARCH_ESP32
|
||||||
@ -1243,7 +1252,7 @@ class AudioReactive : public Usermod {
|
|||||||
disableSoundProcessing = true;
|
disableSoundProcessing = true;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (enabled) disableSoundProcessing = false; // all good - enable audio processing
|
if (enabled) disableSoundProcessing = false; // all good - enable audio processing
|
||||||
if (enabled) connectUDPSoundSync();
|
if (enabled) connectUDPSoundSync();
|
||||||
if (enabled && addPalettes) createAudioPalettes();
|
if (enabled && addPalettes) createAudioPalettes();
|
||||||
initDone = true;
|
initDone = true;
|
||||||
@ -1803,7 +1812,6 @@ class AudioReactive : public Usermod {
|
|||||||
dynLim[F("rise")] = attackTime;
|
dynLim[F("rise")] = attackTime;
|
||||||
dynLim[F("fall")] = decayTime;
|
dynLim[F("fall")] = decayTime;
|
||||||
|
|
||||||
|
|
||||||
JsonObject sync = top.createNestedObject("sync");
|
JsonObject sync = top.createNestedObject("sync");
|
||||||
sync["port"] = audioSyncPort;
|
sync["port"] = audioSyncPort;
|
||||||
sync["mode"] = audioSyncEnabled;
|
sync["mode"] = audioSyncEnabled;
|
||||||
@ -2008,8 +2016,8 @@ CRGB AudioReactive::getCRGBForBand(int x, int pal) {
|
|||||||
void AudioReactive::fillAudioPalettes() {
|
void AudioReactive::fillAudioPalettes() {
|
||||||
if (!palettes) return;
|
if (!palettes) return;
|
||||||
size_t lastCustPalette = strip.customPalettes.size();
|
size_t lastCustPalette = strip.customPalettes.size();
|
||||||
if (lastCustPalette >= palettes) lastCustPalette -= palettes;
|
if (int(lastCustPalette) >= palettes) lastCustPalette -= palettes;
|
||||||
for (size_t pal=0; pal<palettes; pal++) {
|
for (int pal=0; pal<palettes; pal++) {
|
||||||
uint8_t tcp[16]; // Needs to be 4 times however many colors are being used.
|
uint8_t tcp[16]; // Needs to be 4 times however many colors are being used.
|
||||||
// 3 colors = 12, 4 colors = 16, etc.
|
// 3 colors = 12, 4 colors = 16, etc.
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user