Skip to content

Commit 8998990

Browse files
committed
sound sync: use last remaining gap to transmit soundPressure
* use last remaining two bytes in audioSyncPacket for transmitting soundPressure * 0x0 is treated as "legacy value" --> soundPressure = volumeSmth; * decodeAudioData: ensure receivedPacket struct members are correctly aligned - strictly speaking it is not safe to cast a uint8_t* as it does not offer any alignment guarantees. * remove 8266 special handling in audioreactive::setup()
1 parent e28fa67 commit 8998990

1 file changed

Lines changed: 46 additions & 40 deletions

File tree

usermods/audioreactive/audio_reactive.h

Lines changed: 46 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ class AudioReactive : public Usermod {
10501050
// new "V2" audiosync struct - 44 Bytes
10511051
struct __attribute__ ((packed)) audioSyncPacket { // WLEDMM "packed" ensures that there are no additional gaps
10521052
char header[6]; // 06 Bytes offset 0
1053-
uint8_t gap1[2]; // gap added by compiler: 02 Bytes, offset 6
1053+
uint8_t pressure[2]; // 02 Bytes, offset 6 - sound pressure as fixed point (8bit integer, 8bit fraction)
10541054
float sampleRaw; // 04 Bytes offset 8 - either "sampleRaw" or "rawSampleAgc" depending on soundAgc setting
10551055
float sampleSmth; // 04 Bytes offset 12 - either "sampleAvg" or "sampleAgc" depending on soundAgc setting
10561056
uint8_t samplePeak; // 01 Bytes offset 16 - 0 no peak; >=1 peak detected. In future, this will also provide peak Magnitude
@@ -1065,8 +1065,8 @@ class AudioReactive : public Usermod {
10651065
struct audioSyncPacket_v1 {
10661066
char header[6]; // 06 Bytes
10671067
uint8_t myVals[32]; // 32 Bytes
1068-
int sampleAgc; // 04 Bytes
1069-
int sampleRaw; // 04 Bytes
1068+
int32_t sampleAgc; // 04 Bytes
1069+
int32_t sampleRaw; // 04 Bytes
10701070
float sampleAvg; // 04 Bytes
10711071
bool samplePeak; // 01 Bytes
10721072
uint8_t fftResult[16]; // 16 Bytes
@@ -1602,6 +1602,14 @@ class AudioReactive : public Usermod {
16021602
transmitData.fftResult[i] = fftResult[i];
16031603
}
16041604

1605+
// WLEDMM transmit soundPressure as 16 bit fixed point
1606+
uint32_t pressure16bit = max(0.0f, soundPressure) * 256.0f; // convert to fixed point, remove negative values
1607+
uint16_t pressInt = pressure16bit / 256; // integer part
1608+
uint16_t pressFract = pressure16bit % 256; // faction part
1609+
if (pressInt > 255) pressInt = 255; // saturation at 255
1610+
transmitData.pressure[0] = (uint8_t)pressInt;
1611+
transmitData.pressure[1] = (uint8_t)pressFract;
1612+
16051613
transmitData.FFT_Magnitude = my_magnitude;
16061614
transmitData.FFT_MajorPeak = FFT_MajorPeak;
16071615

@@ -1622,30 +1630,33 @@ class AudioReactive : public Usermod {
16221630

16231631
bool decodeAudioData(int packetSize, uint8_t *fftBuff) {
16241632
if((0 == packetSize) || (nullptr == fftBuff)) return false; // sanity check
1625-
audioSyncPacket *receivedPacket = reinterpret_cast<audioSyncPacket*>(fftBuff);
1633+
//audioSyncPacket *receivedPacket = reinterpret_cast<audioSyncPacket*>(fftBuff);
1634+
audioSyncPacket receivedPacket;
1635+
memset(&receivedPacket, 0, sizeof(receivedPacket)); // start clean
1636+
memcpy(&receivedPacket, fftBuff, min((unsigned)packetSize, (unsigned)sizeof(receivedPacket))); // don't violate alignment - thanks @willmmiles
16261637

16271638
// validate sequence, discard out-of-sequence packets
16281639
static uint8_t lastFrameCounter = 0;
16291640
// add info for UI
1630-
if ((receivedPacket->frameCounter > 0) && (lastFrameCounter > 0)) receivedFormat = 3; // v2+
1641+
if ((receivedPacket.frameCounter > 0) && (lastFrameCounter > 0)) receivedFormat = 3; // v2+
16311642
else receivedFormat = 2; // v2
16321643
// check sequence
16331644
bool sequenceOK = false;
1634-
if(receivedPacket->frameCounter > lastFrameCounter) sequenceOK = true; // sequence OK
1635-
if((lastFrameCounter < 12) && (receivedPacket->frameCounter > 248)) sequenceOK = false; // prevent sequence "roll-back" due to late packets (1->254)
1636-
if((lastFrameCounter > 248) && (receivedPacket->frameCounter < 12)) sequenceOK = true; // handle roll-over (255 -> 0)
1645+
if(receivedPacket.frameCounter > lastFrameCounter) sequenceOK = true; // sequence OK
1646+
if((lastFrameCounter < 12) && (receivedPacket.frameCounter > 248)) sequenceOK = false; // prevent sequence "roll-back" due to late packets (1->254)
1647+
if((lastFrameCounter > 248) && (receivedPacket.frameCounter < 12)) sequenceOK = true; // handle roll-over (255 -> 0)
16371648
if(audioSyncSequence == false) sequenceOK = true; // sequence checking disabled by user
1638-
if((sequenceOK == false) && (receivedPacket->frameCounter != 0)) { // always accept "0" - its the legacy value
1639-
DEBUGSR_PRINTF("Skipping audio frame out of order or duplicated - %u vs %u\n", lastFrameCounter, receivedPacket->frameCounter);
1649+
if((sequenceOK == false) && (receivedPacket.frameCounter != 0)) { // always accept "0" - its the legacy value
1650+
DEBUGSR_PRINTF("Skipping audio frame out of order or duplicated - %u vs %u\n", lastFrameCounter, receivedPacket.frameCounter);
16401651
return false; // reject out-of sequence frame
16411652
}
16421653
else {
1643-
lastFrameCounter = receivedPacket->frameCounter;
1654+
lastFrameCounter = receivedPacket.frameCounter;
16441655
}
16451656

16461657
// update samples for effects
1647-
volumeSmth = fmaxf(receivedPacket->sampleSmth, 0.0f);
1648-
volumeRaw = fmaxf(receivedPacket->sampleRaw, 0.0f);
1658+
volumeSmth = fmaxf(receivedPacket.sampleSmth, 0.0f);
1659+
volumeRaw = fmaxf(receivedPacket.sampleRaw, 0.0f);
16491660
#ifdef ARDUINO_ARCH_ESP32
16501661
// update internal samples
16511662
sampleRaw = volumeRaw;
@@ -1658,18 +1669,26 @@ class AudioReactive : public Usermod {
16581669
// If it's true already, then the animation still needs to respond.
16591670
autoResetPeak();
16601671
if (!samplePeak) {
1661-
samplePeak = receivedPacket->samplePeak >0 ? true:false;
1672+
samplePeak = receivedPacket.samplePeak >0 ? true:false;
16621673
if (samplePeak) timeOfPeak = millis();
16631674
//userVar1 = samplePeak;
16641675
}
16651676
//These values are only computed by ESP32
1666-
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) fftResult[i] = receivedPacket->fftResult[i];
1667-
my_magnitude = fmaxf(receivedPacket->FFT_Magnitude, 0.0f);
1677+
for (int i = 0; i < NUM_GEQ_CHANNELS; i++) fftResult[i] = receivedPacket.fftResult[i];
1678+
my_magnitude = fmaxf(receivedPacket.FFT_Magnitude, 0.0f);
16681679
FFT_Magnitude = my_magnitude;
1669-
FFT_MajorPeak = constrain(receivedPacket->FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
1670-
soundPressure = volumeSmth; // substitute - V2 format does not (yet) include this value
1671-
agcSensitivity = 128.0f; // substitute - V2 format does not (yet) include this value
1672-
zeroCrossingCount = receivedPacket->zeroCrossingCount;
1680+
FFT_MajorPeak = constrain(receivedPacket.FFT_MajorPeak, 1.0f, 11025.0f); // restrict value to range expected by effects
1681+
agcSensitivity = 128.0f; // substitute - V2 format does not include this value
1682+
zeroCrossingCount = receivedPacket.zeroCrossingCount;
1683+
1684+
// WLEDMM extract soundPressure
1685+
if ((receivedPacket.pressure[0] != 0) || (receivedPacket.pressure[1] != 0)) {
1686+
// found something in gap "reserved2"
1687+
soundPressure = float(receivedPacket.pressure[1]) / 256.0f; // fractional part
1688+
soundPressure += float(receivedPacket.pressure[0]); // integer part
1689+
} else {
1690+
soundPressure = volumeSmth; // fallback
1691+
}
16731692

16741693
return true;
16751694
}
@@ -1786,36 +1805,23 @@ class AudioReactive : public Usermod {
17861805
um_data->u_type[4] = UMT_FLOAT;
17871806
um_data->u_data[5] = &my_magnitude; // used (New)
17881807
um_data->u_type[5] = UMT_FLOAT;
1789-
#ifdef ARDUINO_ARCH_ESP32
17901808
um_data->u_data[6] = &maxVol; // assigned in effect function from UI element!!! (Puddlepeak, Ripplepeak, Waterfall)
17911809
um_data->u_type[6] = UMT_BYTE;
17921810
um_data->u_data[7] = &binNum; // assigned in effect function from UI element!!! (Puddlepeak, Ripplepeak, Waterfall)
17931811
um_data->u_type[7] = UMT_BYTE;
1812+
#ifdef ARDUINO_ARCH_ESP32
17941813
um_data->u_data[8] = &FFT_MajPeakSmth; // new
17951814
um_data->u_type[8] = UMT_FLOAT;
1796-
um_data->u_data[9] = &soundPressure; // used (New)
1797-
um_data->u_type[9] = UMT_FLOAT;
1798-
um_data->u_data[10] = &agcSensitivity; // used (New)
1799-
um_data->u_type[10] = UMT_FLOAT;
1800-
um_data->u_data[11] = &zeroCrossingCount;
1801-
um_data->u_type[11] = UMT_UINT16;
18021815
#else
1803-
// ESP8266
1804-
// See https://github.com/MoonModules/WLED/pull/60#issuecomment-1666972133 for explanation of these alternative sources of data
1805-
1806-
um_data->u_data[6] = &maxVol; // assigned in effect function from UI element!!! (Puddlepeak, Ripplepeak, Waterfall)
1807-
um_data->u_type[6] = UMT_BYTE;
1808-
um_data->u_data[7] = &binNum; // assigned in effect function from UI element!!! (Puddlepeak, Ripplepeak, Waterfall)
1809-
um_data->u_type[7] = UMT_BYTE;
1810-
um_data->u_data[8] = &FFT_MajorPeak; // new - substitute for FFT_MajPeakSmth
1816+
um_data->u_data[8] = &FFT_MajorPeak; // substitute for 8266
18111817
um_data->u_type[8] = UMT_FLOAT;
1812-
um_data->u_data[9] = &volumeSmth; // used (New) - substitute for soundPressure
1818+
#endif
1819+
um_data->u_data[9] = &soundPressure; // used (New)
18131820
um_data->u_type[9] = UMT_FLOAT;
1814-
um_data->u_data[10] = &agcSensitivity; // used (New) - dummy value (128 => 50%)
1821+
um_data->u_data[10] = &agcSensitivity; // used (New) - dummy value on 8266
18151822
um_data->u_type[10] = UMT_FLOAT;
1816-
um_data->u_data[11] = &zeroCrossingCount;
1823+
um_data->u_data[11] = &zeroCrossingCount; // for auto playlist usermod
18171824
um_data->u_type[11] = UMT_UINT16;
1818-
#endif
18191825
}
18201826

18211827
#ifdef ARDUINO_ARCH_ESP32
@@ -2201,7 +2207,7 @@ class AudioReactive : public Usermod {
22012207
volumeSmth =0.0f;
22022208
volumeRaw =0;
22032209
my_magnitude = 0.1; FFT_Magnitude = 0.01; FFT_MajorPeak = 2;
2204-
soundPressure = 1.0f;
2210+
soundPressure = 1.0f;
22052211
agcSensitivity = 64.0f;
22062212
#ifdef ARDUINO_ARCH_ESP32
22072213
multAgc = 1;

0 commit comments

Comments
 (0)