Skip to content

Commit a4aff1d

Browse files
committed
PWM decimation
1 parent ee55bc8 commit a4aff1d

File tree

11 files changed

+60
-24
lines changed

11 files changed

+60
-24
lines changed

src/AudioConfig.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,6 +809,11 @@ using WiFiServerSecure = BearSSL::WiFiServerSecure;
809809
# define ANALOG_MAX_SAMPLE_RATE 44100
810810
#endif
811811

812+
#ifndef PWM_MAX_SAMPLE_RATE
813+
# define PWM_MAX_SAMPLE_RATE 8000
814+
#endif
815+
816+
812817
#ifndef URL_CLIENT_TIMEOUT
813818
# define URL_CLIENT_TIMEOUT 60000;
814819
# define URL_HANDSHAKE_TIMEOUT 120000

src/AudioTools/AudioCodecs/AudioEncoded.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ class EncodedAudioOutput : public ModifyingOutput {
9393
}
9494
}
9595

96+
9697
void setOutput(Print &outputStream) { setOutput(&outputStream); }
9798

9899
/// Defines the output
@@ -266,18 +267,18 @@ class EncodedAudioStream : public ReformatBaseStream {
266267
}
267268

268269
EncodedAudioStream(AudioOutput *outputStream, AudioDecoder *decoder) {
269-
setOutput(*outputStream);
270270
setDecoder(decoder);
271+
setOutput(*outputStream);
271272
}
272273

273274
EncodedAudioStream(Print *outputStream, AudioDecoder *decoder) {
274-
setOutput(*outputStream);
275275
setDecoder(decoder);
276+
setOutput(*outputStream);
276277
}
277278

278279
EncodedAudioStream(Print *outputStream, AudioEncoder *encoder) {
279-
setOutput(*outputStream);
280280
setEncoder(encoder);
281+
setOutput(*outputStream);
281282
}
282283

283284
EncodedAudioStream(AudioDecoder *decoder) { setDecoder(decoder); }

src/AudioTools/AudioCodecs/CodecMP3Helix.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ class MP3DecoderHelix : public AudioDecoder {
7070
}
7171

7272
/// Defines the output Stream
73-
virtual void setOutput(Print &outStream){
73+
void setOutput(Print &outStream) override {
74+
AudioDecoder::setOutput(outStream);
7475
if (mp3!=nullptr) mp3->setOutput(outStream);
7576
}
7677

src/AudioTools/CoreAudio/AudioPWM/AudioPWM.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class PWMAudioOutput : public AudioOutput {
3434
PWMConfig config() { return audio_config; }
3535

3636
/// updates the sample rate dynamically
37-
virtual void setAudioInfo(AudioInfo info) {
37+
void setAudioInfo(AudioInfo info) override {
3838
TRACEI();
3939
AudioOutput::cfg = info;
4040
PWMConfig cfg = audio_config;
@@ -43,9 +43,9 @@ class PWMAudioOutput : public AudioOutput {
4343
cfg.sample_rate = info.sample_rate;
4444
cfg.bits_per_sample = info.bits_per_sample;
4545
cfg.channels = info.channels;
46-
cfg.logInfo();
4746
end();
4847
begin(cfg);
48+
cfg.logInfo();
4949
}
5050
}
5151

@@ -59,8 +59,7 @@ class PWMAudioOutput : public AudioOutput {
5959
bool begin(PWMConfig config) {
6060
TRACED();
6161
this->audio_config = config;
62-
AudioOutput::setAudioInfo(audio_config);
63-
return pwm.begin(audio_config);
62+
return begin();
6463
}
6564

6665
bool begin() {

src/AudioTools/CoreAudio/AudioPWM/PWMAudioAVR.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@ class PWMDriverAVR : public DriverPWMBase {
7373
/// Setup LED PWM
7474
void setupPWM() {
7575
TRACED();
76+
audio_config.pwm_frequency = 62500;
77+
7678
if (audio_config.channels > 2) {
7779
LOGW("Max 2 channels supported - you requested %d",
7880
audio_config.channels);

src/AudioTools/CoreAudio/AudioPWM/PWMAudioBase.h

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,18 +37,23 @@ struct PWMConfig : public AudioInfo {
3737
bits_per_sample = 16;
3838
}
3939

40-
// basic pwm information
40+
/// size of an inidividual buffer
4141
uint16_t buffer_size = PWM_BUFFER_SIZE;
42+
/// number of buffers
4243
uint8_t buffers = PWM_BUFFER_COUNT;
4344

44-
// additinal info which might not be used by all processors
45-
uint32_t pwm_frequency = PWM_AUDIO_FREQUENCY; // audable range is from 20 to
46-
// 20,000Hz (not used by ESP32)
47-
uint8_t resolution = 8; // Only used by ESP32: must be between 8 and 11 ->
48-
// drives pwm frequency
49-
uint8_t timer_id = 0; // Only used by ESP32 must be between 0 and 3
45+
/// additinal info which might not be used by all processors
46+
uint32_t pwm_frequency = 0; // audable range is from 20 to
47+
/// Only used by ESP32: must be between 8 and 11 -> drives pwm frequency // 20,000Hz (not used by ESP32)
48+
uint8_t resolution = 8;
49+
/// Timer used: Only used by ESP32 must be between 0 and 3
50+
uint8_t timer_id = 0;
51+
52+
/// max sample sample rate that still produces good audio
53+
uint32_t max_sample_rate = PWM_MAX_SAMPLE_RATE;
5054

5155
#ifndef __AVR__
56+
/// GPIO of starting pin
5257
uint16_t start_pin = PIN_PWM_START;
5358

5459
/// support assignament of int array
@@ -116,7 +121,8 @@ class DriverPWMBase {
116121

117122
// restart with prior definitions
118123
bool begin(PWMConfig cfg) {
119-
TRACED();
124+
TRACEI();
125+
120126
decimation_factor = 0;
121127
audio_config = cfg;
122128
decimate.setChannels(cfg.channels);
@@ -140,9 +146,9 @@ class DriverPWMBase {
140146
// initialize if necessary
141147
if (!isTimerStarted() || !cfg.equals(actual_info)) {
142148
audio_config.logConfig();
149+
actual_info = cfg;
143150
setupPWM();
144151
setupTimer();
145-
actual_info = cfg;
146152
}
147153

148154
// reset class variables
@@ -323,19 +329,19 @@ class DriverPWMBase {
323329
}
324330

325331
/// Provides the max working sample rate
326-
virtual int maxSampleRate() { return 48000; }
332+
virtual int maxSampleRate() { return audio_config.max_sample_rate; }
327333

328334
/// The requested sampling rate is too hight: we only process half of the
329335
/// samples so we can half the sampling rate
330336
virtual bool isDecimateActive() {
331-
return audio_config.sample_rate >= ANALOG_MAX_SAMPLE_RATE;
337+
return audio_config.sample_rate >= audio_config.max_sample_rate;
332338
}
333339

334340
/// Decimation factor to reduce the sample rate
335341
virtual int decimation() {
336342
if (decimation_factor == 0){
337343
for (int j = 1; j < 20; j++){
338-
if (audio_config.sample_rate / j <= ANALOG_MAX_SAMPLE_RATE){
344+
if (audio_config.sample_rate / j <= audio_config.max_sample_rate){
339345
decimation_factor = j;
340346
LOGI("Decimation factor: %d" ,j);
341347
return j;

src/AudioTools/CoreAudio/AudioPWM/PWMAudioESP32.h

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,16 +59,18 @@ class PWMDriverESP32 : public DriverPWMBase {
5959
virtual void startTimer() {
6060
if (!timer) {
6161
TRACEI();
62-
audio_config = audioInfo();
63-
timer.begin(pwm_callback, audio_config.sample_rate, HZ);
62+
timer.begin(pwm_callback, effectiveOutputSampleRate(), HZ);
63+
actual_timer_frequency = effectiveOutputSampleRate();
6464
is_timer_started = true;
6565
}
6666
}
6767

6868
/// Setup LED PWM
6969
virtual void setupPWM() {
7070
// frequency is driven by selected resolution
71-
audio_config.pwm_frequency = frequency(audio_config.resolution) * 1000;
71+
if (audio_config.pwm_frequency == 0){
72+
audio_config.pwm_frequency = frequency(audio_config.resolution) * 1000;
73+
}
7274

7375
pins.resize(audio_config.channels);
7476
for (int j = 0; j < audio_config.channels; j++) {
@@ -102,6 +104,11 @@ class PWMDriverESP32 : public DriverPWMBase {
102104
virtual void setupTimer() {
103105
timer.setCallbackParameter(this);
104106
timer.setIsSave(false);
107+
108+
if (actual_timer_frequency != effectiveOutputSampleRate()){
109+
timer.end();
110+
startTimer();
111+
}
105112
}
106113

107114
/// write a pwm value to the indicated channel. The max value depends on the
@@ -117,6 +124,7 @@ class PWMDriverESP32 : public DriverPWMBase {
117124
protected:
118125
Vector<PinInfo> pins;
119126
TimerAlarmRepeating timer;
127+
uint32_t actual_timer_frequency = 0;
120128

121129
/// provides the max value for the indicated resulution
122130
int maxUnsignedValue(int resolution) { return pow(2, resolution); }

src/AudioTools/CoreAudio/AudioPWM/PWMAudioMBED.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ class PWMDriverMBED : public DriverPWMBase {
6565
/// Setup PWM Pins
6666
virtual void setupPWM() {
6767
TRACED();
68+
if (audio_config.pwm_frequency == 0){
69+
audio_config.pwm_frequency = PWM_AUDIO_FREQUENCY;
70+
}
71+
6872
unsigned long period =
6973
1000000l / audio_config.pwm_frequency; // -> 30.517578125 microseconds
7074
pins.resize(audio_config.channels);

src/AudioTools/CoreAudio/AudioPWM/PWMAudioRP2040.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ class PWMDriverRP2040 : public DriverPWMBase {
9999
// defines the pwm_config which will be used to drive the pins
100100
pwm_config setupPWMConfig() {
101101
TRACED();
102+
if (audio_config.pwm_frequency == 0){
103+
audio_config.pwm_frequency = PWM_AUDIO_FREQUENCY;
104+
}
102105
// setup pwm frequency
103106
pwm_config pico_pwm_config = pwm_get_default_config();
104107
int wrap_value = maxOutputValue(); // amplitude of square wave (pwm values

src/AudioTools/CoreAudio/AudioPWM/PWMAudioRenesas.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ class PWMDriverRenesas : public DriverPWMBase {
7878
/// Setup PWM Pins
7979
virtual void setupPWM() {
8080
TRACED();
81+
if (audio_config.pwm_frequency == 0){
82+
audio_config.pwm_frequency = PWM_AUDIO_FREQUENCY;
83+
}
84+
8185
pins.resize(audio_config.channels);
8286
for (int j = 0; j < audio_config.channels; j++) {
8387
LOGD("Processing channel %d", j);
@@ -113,7 +117,7 @@ class PWMDriverRenesas : public DriverPWMBase {
113117
}
114118
}
115119

116-
int maxSampleRate() override { return ANALOG_MAX_SAMPLE_RATE; }
120+
int maxSampleRate() override { return audio_config.max_sample_rate; }
117121

118122
int decimation() override {
119123
for (int j = 1; j < 5; j++) {

0 commit comments

Comments
 (0)