Skip to content

Commit 27e33a1

Browse files
committed
v0.9.390
1 parent 9ad82ac commit 27e33a1

File tree

16 files changed

+149
-60
lines changed

16 files changed

+149
-60
lines changed

README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,11 +234,15 @@ Work is in progress...
234234

235235
---
236236
## Version history
237+
### v0.9.390
238+
- updated the VU meter algorithms - shamelessly borrowed from @schreibfaul1, ([thanks a lot!](https://github.com/schreibfaul1/ESP32-audioI2S/blob/1296374fc513a6d6bfaa3b1ca08f6ba938b18d99/src/Audio.cpp#L5030))
239+
- fixed the magic error "HSPI" redefined.
240+
237241
### v0.9.380
238242
- fixed compilation error for ESP32 cores >= 3.1.0
239243
- fixed freezing error with incorrectly configured RTC module
240244
- [www|uart|telnet] new command `mode` - change SD/WEB mode. (0 - WEB, 1 - SD, 2 - Toggle)
241-
example: http://<ipaddr>/?mode=2
245+
example: http://\<ipaddress\>/?mode=2
242246

243247
#### v0.9.375
244248
- fixed the issue with saving settings for TIMEZONE.

yoRadio/src/audioI2S/Audio.cpp

Lines changed: 77 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2335,31 +2335,18 @@ bool Audio::pauseResume() {
23352335
bool Audio::playChunk() {
23362336
// If we've got data, try and pump it out..
23372337
int16_t sample[2];
2338-
/* VU Meter ************************************************************************************************************/
2339-
/* По мотивам https://github.com/schreibfaul1/ESP32-audioI2S/pull/170/commits/6cce84217e5bc8f2f8925936affc84576932a29b */
2340-
uint8_t maxl = 0, maxr = 0;
2341-
uint8_t minl = 0xFF, minr = 0xFF;
2342-
/************************************************************************************************************ VU Meter */
23432338
if(getBitsPerSample() == 8) {
23442339
if(getChannels() == 1) {
23452340
while(m_validSamples) {
23462341
uint8_t x = m_outBuff[m_curSample] & 0x00FF;
23472342
uint8_t y = (m_outBuff[m_curSample] & 0xFF00) >> 8;
23482343
sample[LEFTCHANNEL] = x;
23492344
sample[RIGHTCHANNEL] = x;
2350-
if(sample[LEFTCHANNEL] > maxl ) maxl = sample[LEFTCHANNEL];
2351-
if(sample[RIGHTCHANNEL] > maxr ) maxr = sample[RIGHTCHANNEL];
2352-
if(sample[LEFTCHANNEL] < minl ) minl = sample[LEFTCHANNEL];
2353-
if(sample[RIGHTCHANNEL] < minr ) minr = sample[RIGHTCHANNEL];
23542345
while(1) {
23552346
if(playSample(sample)) break;
23562347
} // Can't send?
23572348
sample[LEFTCHANNEL] = y;
23582349
sample[RIGHTCHANNEL] = y;
2359-
if(sample[LEFTCHANNEL] > maxl ) maxl = sample[LEFTCHANNEL];
2360-
if(sample[RIGHTCHANNEL] > maxr ) maxr = sample[RIGHTCHANNEL];
2361-
if(sample[LEFTCHANNEL] < minl ) minl = sample[LEFTCHANNEL];
2362-
if(sample[RIGHTCHANNEL] < minr ) minr = sample[RIGHTCHANNEL];
23632350
while(1) {
23642351
if(playSample(sample)) break;
23652352
} // Can't send?
@@ -2380,19 +2367,13 @@ bool Audio::playChunk() {
23802367
sample[LEFTCHANNEL] = xy;
23812368
sample[RIGHTCHANNEL] = xy;
23822369
}
2383-
if(sample[LEFTCHANNEL] > maxl ) maxl = sample[LEFTCHANNEL];
2384-
if(sample[RIGHTCHANNEL] > maxr ) maxr = sample[RIGHTCHANNEL];
2385-
if(sample[LEFTCHANNEL] < minl ) minl = sample[LEFTCHANNEL];
2386-
if(sample[RIGHTCHANNEL] < minr ) minr = sample[RIGHTCHANNEL];
23872370
while(1) {
23882371
if(playSample(sample)) break;
23892372
} // Can't send?
23902373
m_validSamples--;
23912374
m_curSample++;
23922375
}
23932376
}
2394-
vuLeft = maxl - minl;
2395-
vuRight = maxr - minr;
23962377
m_curSample = 0;
23972378
return true;
23982379
}
@@ -2401,10 +2382,6 @@ bool Audio::playChunk() {
24012382
while(m_validSamples) {
24022383
sample[LEFTCHANNEL] = m_outBuff[m_curSample];
24032384
sample[RIGHTCHANNEL] = m_outBuff[m_curSample];
2404-
if(sample[LEFTCHANNEL] > maxl ) maxl = sample[LEFTCHANNEL];
2405-
if(sample[RIGHTCHANNEL] > maxr ) maxr = sample[RIGHTCHANNEL];
2406-
if(sample[LEFTCHANNEL] < minl ) minl = sample[LEFTCHANNEL];
2407-
if(sample[RIGHTCHANNEL] < minr ) minr = sample[RIGHTCHANNEL];
24082385
if(!playSample(sample)) {
24092386
log_e("can't send");
24102387
return false;
@@ -2425,17 +2402,11 @@ bool Audio::playChunk() {
24252402
sample[LEFTCHANNEL] = xy;
24262403
sample[RIGHTCHANNEL] = xy;
24272404
}
2428-
if(sample[LEFTCHANNEL] > maxl ) maxl = sample[LEFTCHANNEL];
2429-
if(sample[RIGHTCHANNEL] > maxr ) maxr = sample[RIGHTCHANNEL];
2430-
if(sample[LEFTCHANNEL] < minl ) minl = sample[LEFTCHANNEL];
2431-
if(sample[RIGHTCHANNEL] < minr ) minr = sample[RIGHTCHANNEL];
24322405
playSample(sample);
24332406
m_validSamples--;
24342407
m_curSample++;
24352408
}
24362409
}
2437-
vuLeft = maxl - minl;
2438-
vuRight = maxr - minr;
24392410
m_curSample = 0;
24402411
return true;
24412412
}
@@ -2444,10 +2415,86 @@ bool Audio::playChunk() {
24442415
stopSong();
24452416
return false;
24462417
}
2418+
2419+
/*
2420+
* Shamelessly borrowed from @schreibfaul1 https://github.com/schreibfaul1/ESP32-audioI2S/blob/1296374fc513a6d6bfaa3b1ca08f6ba938b18d99/src/Audio.cpp#L5030
2421+
*/
2422+
void Audio::_computeVUlevel(int16_t sample[2]) {
2423+
if(!config.store.vumeter) return;
2424+
static uint8_t sampleArray[2][4][8] = {0};
2425+
static uint8_t cnt0 = 0, cnt1 = 0, cnt2 = 0, cnt3 = 0, cnt4 = 0;
2426+
static bool f_vu = false;
2427+
2428+
auto avg = [&](uint8_t* sampArr) { // lambda, inner function, compute the average of 8 samples
2429+
uint16_t av = 0;
2430+
for(int i = 0; i < 8; i++) { av += sampArr[i]; }
2431+
return av >> 3;
2432+
};
2433+
2434+
auto largest = [&](uint8_t* sampArr) { // lambda, inner function, compute the largest of 8 samples
2435+
uint16_t maxValue = 0;
2436+
for(int i = 0; i < 8; i++) {
2437+
if(maxValue < sampArr[i]) maxValue = sampArr[i];
2438+
}
2439+
return maxValue;
2440+
};
2441+
2442+
if(cnt0 == 64) {
2443+
cnt0 = 0;
2444+
cnt1++;
2445+
}
2446+
if(cnt1 == 8) {
2447+
cnt1 = 0;
2448+
cnt2++;
2449+
}
2450+
if(cnt2 == 8) {
2451+
cnt2 = 0;
2452+
cnt3++;
2453+
}
2454+
if(cnt3 == 8) {
2455+
cnt3 = 0;
2456+
cnt4++;
2457+
f_vu = true;
2458+
}
2459+
if(cnt4 == 8) { cnt4 = 0; }
2460+
2461+
if(!cnt0) { // store every 64th sample in the array[0]
2462+
sampleArray[LEFTCHANNEL][0][cnt1] = abs(sample[LEFTCHANNEL] >> 7);
2463+
sampleArray[RIGHTCHANNEL][0][cnt1] = abs(sample[RIGHTCHANNEL] >> 7);
2464+
}
2465+
if(!cnt1) { // store argest from 64 * 8 samples in the array[1]
2466+
sampleArray[LEFTCHANNEL][1][cnt2] = largest(sampleArray[LEFTCHANNEL][0]);
2467+
sampleArray[RIGHTCHANNEL][1][cnt2] = largest(sampleArray[RIGHTCHANNEL][0]);
2468+
}
2469+
if(!cnt2) { // store avg from 64 * 8 * 8 samples in the array[2]
2470+
sampleArray[LEFTCHANNEL][2][cnt3] = largest(sampleArray[LEFTCHANNEL][1]);
2471+
sampleArray[RIGHTCHANNEL][2][cnt3] = largest(sampleArray[RIGHTCHANNEL][1]);
2472+
}
2473+
if(!cnt3) { // store avg from 64 * 8 * 8 * 8 samples in the array[3]
2474+
sampleArray[LEFTCHANNEL][3][cnt4] = avg(sampleArray[LEFTCHANNEL][2]);
2475+
sampleArray[RIGHTCHANNEL][3][cnt4] = avg(sampleArray[RIGHTCHANNEL][2]);
2476+
}
2477+
if(f_vu) {
2478+
f_vu = false;
2479+
vuLeft = avg(sampleArray[LEFTCHANNEL][3]);
2480+
if(vuLeft>config.vuThreshold) config.vuThreshold = vuLeft;
2481+
vuRight = avg(sampleArray[RIGHTCHANNEL][3]);
2482+
if(vuRight>config.vuThreshold) config.vuThreshold = vuRight;
2483+
}
2484+
cnt1++;
2485+
}
2486+
2487+
uint16_t Audio::get_VUlevel(uint16_t dimension){
2488+
if(!config.store.vumeter || config.vuThreshold==0) return 0;
2489+
uint8_t L = map(vuLeft, config.vuThreshold, 0, 0, dimension);
2490+
uint8_t R = map(vuRight, config.vuThreshold, 0, 0, dimension);
2491+
return (L << 8) | R;
2492+
}
24472493
//---------------------------------------------------------------------------------------------------------------------
24482494

24492495
void Audio::loop() {
24502496
if(!m_f_running) {
2497+
vuLeft=0; vuRight=0;
24512498
vTaskDelay(2);
24522499
return;
24532500
}
@@ -4563,7 +4610,7 @@ bool Audio::playSample(int16_t sample[2]) {
45634610
sample = IIR_filterChain1(sample);
45644611
sample = IIR_filterChain2(sample);
45654612
//-------------------------------------------
4566-
4613+
_computeVUlevel(sample);
45674614
uint32_t s32 = Gain(sample); // vosample2lume;
45684615

45694616
if(m_f_internalDAC) {

yoRadio/src/audioI2S/AudioEx.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#ifndef AUDIOBUFFER_MULTIPLIER2
3636
#define AUDIOBUFFER_MULTIPLIER2 8
3737
#endif
38+
3839
#if ESP_ARDUINO_VERSION >= ESP_ARDUINO_VERSION_VAL(3, 0, 0)
3940
#include "hal/gpio_ll.h"
4041
#endif
@@ -211,7 +212,8 @@ class Audio : private AudioBuffer{
211212
/* VU METER */
212213
void setVUmeter() {};
213214
void getVUlevel() {};
214-
uint8_t vuLeft, vuRight;
215+
uint16_t get_VUlevel(uint16_t dimension);
216+
215217
bool eofHeader;
216218
esp_err_t i2s_mclk_pin_select(const uint8_t pin);
217219
uint32_t inBufferFilled(); // returns the number of stored bytes in the inputbuffer
@@ -284,7 +286,7 @@ class Audio : private AudioBuffer{
284286
inline uint32_t streamavail(){ return _client ? _client->available() : 0;}
285287
void IIR_calculateCoefficients(int8_t G1, int8_t G2, int8_t G3);
286288
bool ts_parsePacket(uint8_t* packet, uint8_t* packetStart, uint8_t* packetLength);
287-
289+
void _computeVUlevel(int16_t sample[2]);
288290
// implement several function with respect to the index of string
289291
void trim(char *s) {
290292
//fb trim in place
@@ -561,6 +563,7 @@ class Audio : private AudioBuffer{
561563
int16_t m_pidOfAAC;
562564
uint8_t m_packetBuff[m_tsPacketSize];
563565
int16_t m_pesDataLength = 0;
566+
uint16_t vuLeft, vuRight;
564567
};
565568

566569
//----------------------------------------------------------------------------------------------------------------------

yoRadio/src/audioVS1053/audioVS1053Ex.cpp

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1658,16 +1658,26 @@ void Audio::setVUmeter() {
16581658
*
16591659
* \warning This feature is only available with patches that support VU meter.
16601660
*/
1661-
void Audio::getVUlevel() {
1661+
const uint8_t everyn = 4;
1662+
void Audio::computeVUlevel() {
16621663
if(!VS_PATCH_ENABLE) return;
1663-
if(!_vuInitalized) return;
1664+
static uint8_t cc = 0;
1665+
cc++;
1666+
if(!_vuInitalized || !config.store.vumeter || cc!=everyn) return;
1667+
if(cc==everyn) cc=0;
16641668
int16_t reg = read_register(SCI_AICTRL3);
1665-
uint8_t rl = map((uint8_t)reg, 85, 92, 0, 255);
1666-
uint8_t rr = map((uint8_t)(reg >> 8), 85, 92, 0, 255);
1667-
//if(rl>30 || !isRunning()) vuLeft = rl;
1668-
//if(rr>30 || !isRunning()) vuRight = rr;
1669-
vuLeft = rl;
1670-
vuRight = rr;
1669+
vuLeft = map((uint8_t)(reg & 0x00FF), 85, 92, 0, 255);
1670+
vuRight = map((uint8_t)(reg >> 8), 85, 92, 0, 255);
1671+
if(vuLeft>config.vuThreshold) config.vuThreshold = vuLeft;
1672+
if(vuRight>config.vuThreshold) config.vuThreshold=vuRight;
1673+
}
1674+
1675+
uint16_t Audio::get_VUlevel(uint16_t dimension){
1676+
if(!VS_PATCH_ENABLE) return 0;
1677+
if(!_vuInitalized || !config.store.vumeter || config.vuThreshold==0) return 0;
1678+
uint8_t L = map(vuLeft, config.vuThreshold, 0, 0, dimension);
1679+
uint8_t R = map(vuRight, config.vuThreshold, 0, 0, dimension);
1680+
return (L << 8) | R;
16711681
}
16721682
//---------------------------------------------------------------------------------------------------------------------
16731683
void Audio::setConnectionTimeout(uint16_t timeout_ms, uint16_t timeout_ms_ssl){

yoRadio/src/audioVS1053/audioVS1053Ex.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ class Audio : private AudioBuffer{
236236

237237
const char volumetable[22]={ 0,50,60,65,70,75,80,82,84,86,
238238
88,90,91,92,93,94,95,96,97,98,99,100}; //22 elements
239+
uint8_t vuLeft, vuRight;
239240
protected:
240241
inline void DCS_HIGH() {(dcs_pin&0x20) ? GPIO.out1_w1ts.data = 1 << (dcs_pin - 32) : GPIO.out_w1ts = 1 << dcs_pin;}
241242
inline void DCS_LOW() {(dcs_pin&0x20) ? GPIO.out1_w1tc.data = 1 << (dcs_pin - 32) : GPIO.out_w1tc = 1 << dcs_pin;}
@@ -324,8 +325,8 @@ class Audio : private AudioBuffer{
324325
void forceMono(bool m) {} // TODO
325326
/* VU METER */
326327
void setVUmeter();
327-
void getVUlevel();
328-
uint8_t vuLeft, vuRight;
328+
uint16_t get_VUlevel(uint16_t dimension);
329+
void computeVUlevel();
329330
bool eofHeader;
330331
// implement several function with respect to the index of string
331332
bool startsWith (const char* base, const char* str) { return (strstr(base, str) - base) == 0;}

yoRadio/src/core/config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ uint8_t Config::setLastSSID(uint8_t val) {
407407
}
408408

409409
void Config::setTitle(const char* title) {
410+
vuThreshold = 0;
410411
memset(config.station.title, 0, BUFLEN);
411412
strlcpy(config.station.title, title, BUFLEN);
412413
u8fix(config.station.title);

yoRadio/src/core/config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ class Config {
174174
uint16_t sleepfor;
175175
uint32_t sdResumePos;
176176
bool emptyFS;
177+
uint16_t vuThreshold;
177178
public:
178179
Config() {};
179180
//void save();

yoRadio/src/core/display.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,9 @@ void Display::loop() {
452452
}
453453
}
454454
dsp.loop();
455+
#if I2S_DOUT==255
456+
player.computeVUlevel();
457+
#endif
455458
}
456459

457460
void Display::_setRSSI(int rssi) {

yoRadio/src/core/netserver.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -287,11 +287,12 @@ void NetServer::processQueue(){
287287
return;
288288
break;
289289
}
290-
case GETSYSTEM: sprintf (wsbuf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d}",
290+
case GETSYSTEM: sprintf (wsbuf, "{\"sst\":%d,\"aif\":%d,\"vu\":%d,\"softr\":%d,\"vut\":%d}",
291291
config.store.smartstart != 2,
292292
config.store.audioinfo,
293293
config.store.vumeter,
294-
config.store.softapdelay);
294+
config.store.softapdelay,
295+
config.vuThreshold);
295296
break;
296297
case GETSCREEN: sprintf (wsbuf, "{\"flip\":%d,\"inv\":%d,\"nump\":%d,\"tsf\":%d,\"tsd\":%d,\"dspon\":%d,\"br\":%d,\"con\":%d}",
297298
config.store.flipscreen,

yoRadio/src/core/network.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ void ticks() {
7272
#ifdef USE_SD
7373
if(display.mode()!=SDCHANGE) player.sendCommand({PR_CHECKSD, 0});
7474
#endif
75+
player.sendCommand({PR_VUTONUS, 0});
7576
}
7677
}
7778

0 commit comments

Comments
 (0)