Skip to content

Commit 5449cdd

Browse files
committed
Arduino UNO R4
1 parent 3348035 commit 5449cdd

File tree

12 files changed

+399
-90
lines changed

12 files changed

+399
-90
lines changed

src/AudioAnalog/AnalogAudio.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ class AnalogAudioStream : public AudioStream {
8787
int available() override {
8888
return driver.available();
8989
}
90+
91+
int availableForWrite() override {
92+
return driver.availableForWrite();
93+
}
94+
9095
protected:
9196
AnalogDriver driver;
9297
AnalogConfig adc_config;

src/AudioAnalog/AnalogAudioArduino.h

Lines changed: 117 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -24,28 +24,21 @@ class AnalogDriverArduino : public AnalogDriverBase {
2424

2525
bool begin(AnalogConfig cfg) {
2626
TRACED();
27-
if (cfg.rx_tx_mode == RXTX_MODE) {
27+
config = cfg;
28+
if (config.rx_tx_mode == RXTX_MODE) {
2829
LOGE("RXTX not supported");
2930
return false;
3031
}
31-
config = cfg;
32-
if (buffer == nullptr) {
33-
// allocate buffer_count
34-
buffer = new NBuffer<int16_t>(cfg.buffer_size, cfg.buffer_count);
35-
if (buffer == nullptr) {
36-
LOGE("Not enough memory for buffer");
37-
return false;
38-
}
39-
// setup pins
40-
setupPins();
41-
} else {
42-
timer.end();
43-
}
32+
33+
frame_size = config.channels*(config.bits_per_sample/8);
34+
result_factor = 1;
35+
36+
if (!setupTx()) return false;
37+
38+
if (!setupBuffer()) return false;
4439

4540
// (re)start timer
46-
LOGI("sample_rate: %d", cfg.sample_rate);
47-
timer.setCallbackParameter(this);
48-
return timer.begin(callback, cfg.sample_rate, TimeUnit::HZ);
41+
return setupTimer();
4942
}
5043

5144
void end() override { timer.end(); }
@@ -59,35 +52,107 @@ class AnalogDriverArduino : public AnalogDriverBase {
5952
size_t readBytes(uint8_t *values, size_t len) {
6053
if (config.rx_tx_mode == TX_MODE) return 0;
6154
if (buffer == nullptr) return 0;
62-
int samples = len / 2;
63-
return buffer->readArray((int16_t *)values, samples) * 2;
55+
int bytes = len / frame_size * frame_size;
56+
return buffer->readArray(values, bytes);
6457
}
6558

6659
int availableForWrite() {
6760
if (config.rx_tx_mode == RX_MODE) return 0;
68-
return buffer == nullptr ? 0 : buffer->availableForWrite() * 2;
61+
if (buffer == nullptr) return 0;
62+
return config.is_blocking_write ? config.buffer_size : buffer->availableForWrite();
6963
}
7064

7165
size_t write(const uint8_t *data, size_t len) {
66+
LOGD("write: %d", (int)len);
7267
if (config.rx_tx_mode == RX_MODE) return 0;
68+
// only process full frames
69+
len = len / frame_size * frame_size;
70+
71+
if (isCombinedChannel()){
72+
ChannelReducer cr(1, 2, config.bits_per_sample);
73+
len = cr.convert((uint8_t*)data, len);
74+
LOGD("ChannelReducer len: %d", (int) len);
75+
}
76+
77+
if (isDecimateActive()){
78+
Decimate dec(decim, 1, config.bits_per_sample);
79+
len = dec.convert((uint8_t*)data, len);
80+
LOGD("Decimate len: %d for factor %d", (int) len, decim);
81+
}
7382

7483
// blocking write ?
7584
if (config.is_blocking_write) {
7685
LOGD("Waiting for buffer to be available");
77-
while (buffer->availableForWrite() == 0) {
86+
while (buffer->availableForWrite() < len) {
7887
delay(10);
7988
}
8089
}
90+
8191
// write data
82-
int16_t *data_16 = (int16_t *)data;
83-
return buffer->writeArray(data_16, len / 2) * 2;
92+
size_t result = buffer->writeArray(data, len) * result_factor;
93+
LOGD("write: -> %d / factor: %d", (int)result, result_factor);
94+
return result;
8495
}
8596

8697
protected:
8798
AnalogConfig config;
8899
TimerAlarmRepeating timer;
89-
BaseBuffer<int16_t> *buffer = nullptr;
100+
BaseBuffer<uint8_t> *buffer = nullptr;
90101
int avg_value, min, max, count;
102+
bool is_combined_channels = false;
103+
uint16_t frame_size = 0;
104+
int result_factor = 1;
105+
int decim = 1;
106+
107+
bool setupTx(){
108+
if (config.rx_tx_mode == TX_MODE) {
109+
// check channels
110+
if (config.channels>ANALOG_MAX_OUT_CHANNELS){
111+
if (config.channels == 2){
112+
is_combined_channels = true;
113+
config.channels = 1;
114+
} else {
115+
LOGE("Unsupported channels");
116+
return false;
117+
}
118+
}
119+
if (isDecimateActive()){
120+
LOGI("Using reduced sample rate: %d", effectiveOutputSampleRate());
121+
decim = decimation();
122+
result_factor = result_factor * decim;
123+
}
124+
if (isCombinedChannel()){
125+
LOGI("Combining channels");
126+
result_factor = result_factor * 2;
127+
}
128+
}
129+
return true;
130+
}
131+
132+
bool setupBuffer(){
133+
if (buffer == nullptr) {
134+
// allocate buffer_count
135+
buffer = new RingBuffer<uint8_t>(config.buffer_size * config.buffer_count);
136+
if (buffer == nullptr) {
137+
LOGE("Not enough memory for buffer");
138+
return false;
139+
}
140+
// setup pins
141+
setupPins();
142+
} else {
143+
LOGE("Not enough memory");
144+
timer.end();
145+
return false;
146+
}
147+
return true;
148+
}
149+
150+
bool setupTimer(){
151+
int sample_rate = config.rx_tx_mode == TX_MODE ? effectiveOutputSampleRate() : config.sample_rate;
152+
LOGI("sample_rate: %d", sample_rate);
153+
timer.setCallbackParameter(this);
154+
return timer.begin(callback, sample_rate, TimeUnit::HZ);
155+
}
91156

92157
/// Sample data and write to buffer
93158
static void callback(void *arg) {
@@ -163,6 +228,34 @@ class AnalogDriverArduino : public AnalogDriverBase {
163228
max = INT_MIN;
164229
count = 0;
165230
}
231+
232+
/// The requested sampling rate is too hight: we only process half of the samples so we can half the sampling rate
233+
bool isDecimateActive(){
234+
return config.sample_rate >= ANALOG_MAX_SAMPLE_RATE;
235+
}
236+
237+
// combined stereo channel to mono
238+
bool isCombinedChannel(){
239+
return is_combined_channels;
240+
}
241+
242+
/// Returns the effective output sample rate
243+
int effectiveOutputSampleRate(){
244+
return config.sample_rate / decimation();
245+
}
246+
247+
int decimation() {
248+
if (config.sample_rate <= ANALOG_MAX_SAMPLE_RATE) return 1;
249+
for(int j=2;j<6;j+=2){
250+
if (config.sample_rate/j <= ANALOG_MAX_SAMPLE_RATE) {
251+
return j;
252+
}
253+
}
254+
return 6;
255+
}
256+
257+
258+
166259
};
167260

168261
using AnalogDriver = AnalogDriverArduino;

src/AudioAnalog/AnalogAudioBase.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ namespace audio_tools {
1818
*/
1919
class AnalogConfig : public AudioInfo {
2020
public:
21-
int buffer_count = I2S_BUFFER_COUNT;
22-
int buffer_size = I2S_BUFFER_SIZE;
21+
int buffer_count = PWM_BUFFER_COUNT;
22+
int buffer_size = PWM_BUFFER_SIZE;
2323
RxTxMode rx_tx_mode;
2424
bool is_blocking_write = true;
2525
bool is_auto_center_read = true;

src/AudioConfig.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,8 @@
133133
#define PWM_BUFFER_SIZE 1024
134134
#endif
135135

136-
#ifndef PWM_BUFFERS
137-
#define PWM_BUFFERS 4
136+
#ifndef PWM_BUFFER_COUNT
137+
#define PWM_BUFFER_COUNT 4
138138
#endif
139139

140140
#ifndef PWM_AUDIO_FREQUENCY
@@ -601,6 +601,8 @@ using WiFiServerSecure = BearSSL::WiFiServerSecure;
601601
#define PIN_ANALOG_START A0
602602
#define ANALOG_BUFFER_SIZE 512
603603
#define ANALOG_BUFFERS 5
604+
#define ANALOG_MAX_OUT_CHANNELS 1
605+
#define ANALOG_MAX_SAMPLE_RATE 16000
604606
// default pins for UNO VS1053 shield
605607
#define VS1053_CS 6
606608
#define VS1053_DCS 7

src/AudioHttp/AudioServer.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ class AudioServer {
132132
}
133133

134134
// defines a converter that will be used when the audio is rendered
135-
void setConverter(BaseConverter<int16_t> *c){
135+
void setConverter(BaseConverter *c){
136136
converter_ptr = c;
137137
}
138138

@@ -160,7 +160,7 @@ class AudioServer {
160160
AudioServerDataCallback callback = nullptr;
161161
Stream *in = nullptr;
162162
StreamCopy copier;
163-
BaseConverter<int16_t> *converter_ptr = nullptr;
163+
BaseConverter *converter_ptr = nullptr;
164164

165165
void setupServer(int port) {
166166
WiFiServer tmp(port);
@@ -286,7 +286,7 @@ class AudioEncoderServer : public AudioServer {
286286
* @param sample_rate
287287
* @param channels
288288
*/
289-
void begin(Stream &in, int sample_rate, int channels, int bits_per_sample=16, BaseConverter<int16_t> *converter=nullptr) {
289+
void begin(Stream &in, int sample_rate, int channels, int bits_per_sample=16, BaseConverter *converter=nullptr) {
290290
TRACED();
291291
this->in = &in;
292292
audio_info.sample_rate = sample_rate;
@@ -307,7 +307,7 @@ class AudioEncoderServer : public AudioServer {
307307
* @param info
308308
* @param converter
309309
*/
310-
void begin(Stream &in, AudioInfo info, BaseConverter<int16_t> *converter=nullptr) {
310+
void begin(Stream &in, AudioInfo info, BaseConverter *converter=nullptr) {
311311
TRACED();
312312
this->in = &in;
313313
this->audio_info = info;

src/AudioI2S/I2SESP32.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,15 +111,15 @@ class I2SDriverESP32 {
111111
// convert to 1 channel
112112
switch(cfg.bits_per_sample){
113113
case 16: {
114-
ChannelReducer<int16_t> reducer16(1, 2);
114+
ChannelReducerT<int16_t> reducer16(1, 2);
115115
result = reducer16.convert((uint8_t*)dest,temp, result);
116116
} break;
117117
case 24: {
118-
ChannelReducer<int24_t> reducer24(1,2);
118+
ChannelReducerT<int24_t> reducer24(1,2);
119119
result = reducer24.convert((uint8_t*)dest,temp,result);
120120
} break;
121121
case 32: {
122-
ChannelReducer<int32_t> reducer32(1, 2);
122+
ChannelReducerT<int32_t> reducer32(1, 2);
123123
result = reducer32.convert((uint8_t*)dest, temp, result);
124124
} break;
125125
default:

0 commit comments

Comments
 (0)