Unverified Commit 1a9a252e authored by Wolle's avatar Wolle Committed by GitHub

Merge pull request #571 from schreibfaul1/volume-curve

Volume curve
parents a4c3529c 8b41160e
......@@ -3,8 +3,8 @@
*
* Created on: Oct 26.2018
*
* Version 3.0.5
* Updated on: Aug 04.2023
* Version 3.0.6
* Updated on: Aug 05.2023
* Author: Wolle (schreibfaul1)
*
*/
......@@ -244,6 +244,8 @@ Audio::Audio(bool internalDAC /* = false */, uint8_t channelEnabled /* = I2S_DAC
m_filter[i].b1 = 0;
m_filter[i].b2 = 0;
}
computeLimit(); // first init, vol = 21, vol_steps = 21
}
//---------------------------------------------------------------------------------------------------------------------
void Audio::setBufsize(int rambuf_sz, int psrambuf_sz) {
......@@ -4357,11 +4359,7 @@ bool Audio::setAudioPlayPosition(uint16_t sec){
//---------------------------------------------------------------------------------------------------------------------
void Audio::setVolumeSteps(uint8_t steps) {
m_vol_steps = steps;
if (steps < 1)
m_vol_step_div = 64; /* avoid div-by-zero :-) */
else
m_vol_step_div = steps * steps;
// log_i("m_vol_step_div: %d", m_vol_step_div);
if (steps < 1) m_vol_steps = 64; /* avoid div-by-zero :-) */
}
//---------------------------------------------------------------------------------------------------------------------
uint8_t Audio::maxVolume() {
......@@ -4633,38 +4631,67 @@ void Audio::setBalance(int8_t bal){ // bal -16...16
if(bal < -16) bal = -16;
if(bal > 16) bal = 16;
m_balance = bal;
computeLimit();
}
//---------------------------------------------------------------------------------------------------------------------
void Audio::setVolume(uint8_t vol) {
if (vol > m_vol_steps) vol = m_vol_steps;
m_vol = vol * vol;
return;
void Audio::setVolume(uint8_t vol, uint8_t curve) { // curve 0: default, curve 1: flat at the beginning
if (vol > m_vol_steps) m_vol = m_vol_steps;
else m_vol = vol;
if (curve > 1) m_curve = 1;
else m_curve = curve;
computeLimit();
}
//---------------------------------------------------------------------------------------------------------------------
uint8_t Audio::getVolume() {
uint8_t vol = sqrt(m_vol);
return vol;
return m_vol;
}
//---------------------------------------------------------------------------------------------------------------------
uint8_t Audio::getI2sPort() {
return m_i2s_num;
}
//---------------------------------------------------------------------------------------------------------------------
int32_t Audio::Gain(int16_t s[2]) {
int32_t v[2];
int32_t l = m_vol, r = m_vol;
void Audio::computeLimit(){ // is calculated when the volume or balance changes
double l = 1, r = 1, v = 1; // assume 100%
/* balance is left -16...+16 right */
/* TODO: logarithmic scaling of balance, too? */
if(m_balance < 0){
r -= (int32_t)m_vol * abs(m_balance) / 16;
r -= (double)abs(m_balance) / 16;
} else if(m_balance > 0){
l -= (int32_t)m_vol * abs(m_balance) / 16;
l -= (double)abs(m_balance) / 16;
}
switch(m_curve){
case 0:
v = (double)pow(m_vol, 2) / pow(m_vol_steps, 2); // square (default)
break;
case 1: // logarithmic
double log1 = log(1);
if (m_vol>0) {
v = m_vol * ((std::exp( log1 + (m_vol-1) * (std::log(m_vol_steps)-log1) / (m_vol_steps-1)))/m_vol_steps) / m_vol_steps;
}
else {
v = 0;
}
break;
}
m_limit_left = l * v;
m_limit_right = r * v;
// log_i("m_limit_left %f, m_limit_right %f ",m_limit_left, m_limit_right);
}
//---------------------------------------------------------------------------------------------------------------------
int32_t Audio::Gain(int16_t s[2]) {
int32_t v[2];
/* important: these multiplications must all be signed ints, or the result will be invalid */
v[LEFTCHANNEL] = (s[LEFTCHANNEL] * l) / m_vol_step_div;
v[RIGHTCHANNEL]= (s[RIGHTCHANNEL] * r) / m_vol_step_div;
v[LEFTCHANNEL] = s[LEFTCHANNEL] * m_limit_left;
v[RIGHTCHANNEL]= s[RIGHTCHANNEL] * m_limit_right;
return (v[LEFTCHANNEL] << 16) | (v[RIGHTCHANNEL] & 0xffff);
}
......
......@@ -3,8 +3,8 @@
*
* Created on: Oct 28,2018
*
* Version 3.0.5
* Updated on: Aug 04.2023
* Version 3.0.6
* Updated on: Aug 05.2023
* Author: Wolle (schreibfaul1)
*/
......@@ -185,7 +185,7 @@ public:
void forceMono(bool m);
void setBalance(int8_t bal = 0);
void setVolumeSteps(uint8_t steps);
void setVolume(uint8_t vol);
void setVolume(uint8_t vol, uint8_t curve = 0);
uint8_t getVolume();
uint8_t maxVolume();
uint8_t getI2sPort();
......@@ -256,6 +256,7 @@ private:
bool playChunk();
bool playSample(int16_t sample[2]);
void computeVUlevel(int16_t sample[2]);
void computeLimit();
int32_t Gain(int16_t s[2]);
void showstreamtitle(const char* ml);
bool parseContentType(char* ct);
......@@ -265,8 +266,8 @@ private:
esp_err_t I2Sstop(uint8_t i2s_num);
void urlencode(char* buff, uint16_t buffLen, bool spacesOnly = false);
int16_t* IIR_filterChain0(int16_t iir_in[2], bool clear = false);
int16_t* IIR_filterChain1(int16_t* iir_in, bool clear = false);
int16_t* IIR_filterChain2(int16_t* iir_in, bool clear = false);
int16_t* IIR_filterChain1(int16_t iir_in[2], bool clear = false);
int16_t* IIR_filterChain2(int16_t iir_in[2], bool clear = false);
inline void setDatamode(uint8_t dm){m_datamode=dm;}
inline uint8_t getDatamode(){return m_datamode;}
inline uint32_t streamavail(){ return _client ? _client->available() : 0;}
......@@ -509,9 +510,11 @@ private:
uint32_t m_metacount = 0; // counts down bytes between metadata
int m_controlCounter = 0; // Status within readID3data() and readWaveHeader()
int8_t m_balance = 0; // -16 (mute left) ... +16 (mute right)
uint16_t m_vol=64; // volume
uint16_t m_vol = 21; // volume
uint8_t m_vol_steps = 21; // default
int32_t m_vol_step_div = 21 * 21; //
double m_limit_left = 0; // limiter 0 ... 1, left channel
double m_limit_right = 0; // limiter 0 ... 1, right channel
uint8_t m_curve = 0; // volume characteristic
uint8_t m_bitsPerSample = 16; // bitsPerSample
uint8_t m_channels = 2;
uint8_t m_i2s_num = I2S_NUM_0; // I2S_NUM_0 or I2S_NUM_1
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment