5#if defined(USE_ANALOG) && defined(ARDUINO)
23class AnalogAudioArduino :
public AudioStream {
25 AnalogAudioArduino() =
default;
28 AnalogConfigStd defaultConfig() {
33 void setAudioInfo(AudioInfo info)
override {
35 if (config.sample_rate != info.sample_rate ||
36 config.channels != info.channels ||
37 config.bits_per_sample != info.bits_per_sample) {
38 config.sample_rate = info.sample_rate;
39 config.bits_per_sample = info.bits_per_sample;
40 config.channels = info.channels;
47 bool begin()
override {
return begin(config); }
49 bool begin(AnalogConfigStd cfg) {
53 if (config.rx_tx_mode == RXTX_MODE) {
54 LOGE(
"RXTX not supported");
58 frame_size = config.channels * (config.bits_per_sample / 8);
61 if (!setupPins())
return false;
63 if (!setupTx())
return false;
65 if (!setupBuffer())
return false;
71 void end()
override { timer.end(); }
73 int available()
override {
74 if (config.rx_tx_mode == TX_MODE)
return 0;
75 return buffer ==
nullptr ? 0 : buffer->available() * 2;
79 size_t readBytes(uint8_t *data,
size_t len)
override {
80 if (config.rx_tx_mode == TX_MODE)
return 0;
81 if (buffer ==
nullptr)
return 0;
82 int bytes = len / frame_size * frame_size;
83 return buffer->readArray(data, bytes);
86 int availableForWrite()
override {
87 if (config.rx_tx_mode == RX_MODE)
return 0;
88 if (buffer ==
nullptr)
return 0;
89 return config.is_blocking_write ? config.buffer_size
90 : buffer->availableForWrite();
93 size_t write(
const uint8_t *data,
size_t len)
override {
94 LOGD(
"write: %d", (
int)len);
95 if (config.rx_tx_mode == RX_MODE)
return 0;
97 len = len / frame_size * frame_size;
99 if (isCombinedChannel()) {
100 ChannelReducer cr(1, 2, config.bits_per_sample);
101 len = cr.convert((uint8_t *)data, len);
102 LOGD(
"ChannelReducer len: %d", (
int)len);
105 if (isDecimateActive()) {
106 Decimate dec(decim, 1, config.bits_per_sample);
107 len = dec.convert((uint8_t *)data, len);
108 LOGD(
"Decimate len: %d for factor %d", (
int)len, decim);
112 if (config.is_blocking_write) {
113 LOGD(
"Waiting for buffer to be available");
114 while (buffer->availableForWrite() < len) {
120 switch(config.bits_per_sample){
122 result = buffer->writeArray(data, len);
125 size_t samples = len / 2;
126 int16_t *p16 = (int16_t*)data;
127 for (
int j=0;j<samples;j++){
128 uint8_t sample =
map(p16[j],-32768, 32767,0,255);
129 if (buffer->write(sample)){
137 size_t samples = len / 3;
139 for (
int j=0;j<samples;j++){
140 uint8_t sample =
map(p24[j],-8388608, 8388607,0,255);
141 if (buffer->write(sample)){
150 size_t samples = len / 4;
151 int32_t *p32 = (int32_t*)data;
152 for (
int j=0;j<samples;j++){
153 uint8_t sample =
map(p32[j],-2147483648, 2147483647,0,255);
154 if (buffer->write(sample)){
165 return result * result_factor;
169 AnalogConfigStd config;
171 BaseBuffer<uint8_t> *buffer =
nullptr;
172 int avg_value, min, max, count;
173 bool is_combined_channels =
false;
174 uint16_t frame_size = 0;
175 int result_factor = 1;
177 bool is_active =
false;
181 if (config.rx_tx_mode == TX_MODE) {
184 if (config.channels == 2) {
185 is_combined_channels =
true;
188 LOGE(
"Unsupported channels");
192 if (isDecimateActive()) {
193 LOGI(
"Using reduced sample rate: %d", effectiveOutputSampleRate());
194 decim = decimation();
195 result_factor = result_factor * decim;
197 if (isCombinedChannel()) {
198 LOGI(
"Combining channels");
199 result_factor = result_factor * 2;
206 if (buffer ==
nullptr) {
208 buffer =
new RingBuffer<uint8_t>(config.buffer_size * config.buffer_count);
209 if (buffer ==
nullptr) {
210 LOGE(
"Not enough memory for buffer");
218 int sample_rate = config.rx_tx_mode ==
TX_MODE ? effectiveOutputSampleRate()
219 : config.sample_rate;
220 LOGI(
"sample_rate: %d", sample_rate);
221 timer.setCallbackParameter(
this);
222 return timer.begin(callback, sample_rate, TimeUnit::HZ);
226 static void callback(
void *arg) {
228 AnalogAudioArduino *self = (AnalogAudioArduino *)arg;
230 if (self->buffer ==
nullptr)
return;
233 if (self->config.rx_tx_mode == RX_MODE) {
234 int channels = self->config.channels;
235 for (
int j = 0; j < channels; j++) {
237 value = analogRead(self->config.pins_data[j]);
238 if (self->config.is_auto_center_read) {
239 self->updateMinMax(value);
241 value = (value - self->avg_value) * 16;
242 self->buffer->write(value);
245 }
else if (self->config.rx_tx_mode == TX_MODE) {
246 int channels = self->config.channels;
248 for (
int j = 0; j < channels; j++) {
249 self->buffer->read(sample);
250 int pin = self->config.pins_data[j];
251 analogWrite(pin, sample);
261 Pins& pins = config.pins();
262 if (pins.size()<config.channels){
263 LOGE(
"Only pins %d of %d defined", pins.size(), config.channels);
268 if (config.rx_tx_mode == RX_MODE) {
269 LOGI(
"rx start_pin: %d", config.start_pin);
271 for (
int j = 0; j < config.channels; j++) {
272 int pin = config.pins_data [j];
274 LOGD(
"pinMode(%d, INPUT)", pin);
277 if (config.is_auto_center_read) {
279 for (
int j = 0; j < 1024; j++) {
280 updateMinMax(analogRead(config.pins_data[0]));
282 LOGI(
"Avg Signal was %d", avg_value);
284 }
else if (config.rx_tx_mode == TX_MODE) {
286 for (
int j = 0; j < config.channels; j++) {
287 int pin = config.pins_data[j];
288 LOGI(
"tx pin %d: %d", j, pin);
290 LOGD(
"pinMode(%d, OUTPUT)", pin);
296 void updateMinMax(
int value) {
297 if (value < min) min = value;
298 if (value > max) max = value;
299 if (count++ == 1024) updateAvg();
303 avg_value = (max + min) / 2;
311 bool isDecimateActive() {
312 return config.sample_rate >= config.max_sample_rate;
316 bool isCombinedChannel() {
return is_combined_channels; }
319 int effectiveOutputSampleRate() {
return config.sample_rate / decimation(); }
322 if (config.sample_rate <= config.max_sample_rate)
return 1;
323 for (
int j = 2; j < 6; j += 2) {
324 if (config.sample_rate / j <= config.max_sample_rate) {
#define ANALOG_MAX_OUT_CHANNELS
Definition AnalogConfigStd.h:14
#define INPUT
Definition Arduino.h:34
#define OUTPUT
Definition Arduino.h:38
long map(long x, long in_min, long in_max, long out_min, long out_max)
Maps input to output values.
Definition Arduino.h:182
#define TRACEI()
Definition AudioLoggerIDF.h:32
#define TRACED()
Definition AudioLoggerIDF.h:31
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
Vector< int > Pins
Type alias for a collection of pin numbers.
Definition AudioTypes.h:525
@ TX_MODE
Definition AudioTypes.h:26
constexpr const _Ep * end(initializer_list< _Ep > __il) noexcept
Definition InitializerList.h:63
constexpr const _Ep * begin(initializer_list< _Ep > __il) noexcept
Definition InitializerList.h:55