arduino-audio-tools
AnalogAudioMBED.h
1 
2 #pragma once
3 
4 #include "AudioConfig.h"
5 #if defined(IS_MBED) && defined(USE_ANALOG) || defined(DOXYGEN)
6 
7 namespace audio_tools {
8 
17 public:
19  AnalogDriverMBED() = default;
20 
22  virtual ~AnalogDriverMBED() { end(); }
23 
25  bool begin(AnalogConfig cfg) {
26  TRACEI();
27  if (cfg.bits_per_sample != 16) {
28  LOGE("Only 16 bits_per_sample supported");
29  return false;
30  }
31  if (cfg.channels > 2) {
32  LOGE("max channels: 2");
33  return false;
34  }
35  if (cfg.channels <= 0) {
36  LOGE("no channels");
37  return false;
38  }
39  info = cfg;
40  auto_center.begin(config.channels, config.bits_per.sample);
41  int n_samples = cfg.buffer_size / (cfg.bits_per_sample / 8);
42  ring_buffer.resize(n_samples);
43  switch (info.channels) {
44  case 1:
45  dac1.begin(AN_RESOLUTION_12, info.sample_rate, n_samples,
46  cfg.buffer_count);
47  break;
48  case 2:
49  dac1.begin(AN_RESOLUTION_12, info.sample_rate, n_samples / 2,
50  cfg.buffer_count);
51  dac2.begin(AN_RESOLUTION_12, info.sample_rate, n_samples / 2,
52  cfg.buffer_count);
53  break;
54  }
55  return true;
56  }
57 
59  void end() override {
60  active = false;
61  dac1.stop();
62  dac2.stop();
63  adc1.stop();
64  adc2.stop();
65  }
66 
67  int availableForWrite() {
68  return dac1.available() ? info.buffer_size : 0;
69  }
70 
72  size_t write(const uint8_t *src, size_t size_bytes) override {
73  TRACED();
74  if (!dac1.available())
75  return 0;
76 
77  // collect data in ringbuffer
78  size_t result = 0;
79  int sample_count = size_bytes / 2;
80  Sample *data = (Sample *)src;
81  for (int j = 0; j < sample_count; j++) {
82  ring_buffer.write(data[j]);
83  // process ringbuffer when it is full
84  if (ring_buffer.isFull()) {
85  result += writeBuffer();
86  }
87  }
88  return result;
89  }
90 
91  void flush() {
92  const int size = info.buffer_size;
93  const uint8_t data[size] = {0};
94  write(data, size);
95  ring_buffer.reset();
96  }
97 
98  size_t readBytes(uint8_t *dest, size_t size_bytes) override {
99  TRACED();
100  size_t result = 0;
101  int16_t *data = (int16_t *)dest;
102  size_t samples = size_bytes / 2;
103  switch (info.channels) {
104  case 1:
105  for (int j = 0; j < samples; j++) {
106  data[j] = adc1.read();
107  result += 2;
108  }
109  break;
110  case 2:
111  for (int j = 0; j < samples; j += 2) {
112  data[j] = adc1.read();
113  data[j + 1] = adc2.read();
114  result += 4;
115  }
116  break;
117  }
118 
119  // make sure that the center is at 0
120  if (adc_config.is_auto_center_read){
121  auto_center.convert(dest, result);
122  }
123 
124  return result;
125  }
126 
127  virtual int available() override { return info.buffer_size; }
128 
129 protected:
130  audio_tools::RingBuffer<Sample> ring_buffer{0};
131  AnalogConfig info;
132  ConverterAutoCenter auto_center;
133  AdvancedDAC dac1{PIN_DAC_1};
134  AdvancedDAC dac2{PIN_DAC_2};
135  AdvancedADC adc1{PIN_ANALOG_START};
136  AdvancedADC adc2{PIN_ANALOG_START + 1};
137  bool active = false;
138 
140  size_t writeBuffer() {
141  size_t result = 0;
142  switch (info.channels) {
143  case 1: {
144  SampleBuffer buf = dac1.dequeue();
145  for (size_t i = 0; i < buf.size(); i++) {
146  buf[i] = ring_buffer.read();
147  result += 2;
148  }
149  dac1.write(buf);
150  } break;
151  case 2: {
152  SampleBuffer buf1 = dac1.dequeue();
153  SampleBuffer buf2 = dac2.dequeue();
154  for (size_t i = 0; i < buf1.size(); i += 2) {
155  buf1[i] = ring_buffer.read();
156  buf2[i] = ring_buffer.read();
157  result += 4;
158  }
159  dac1.write(buf1);
160  dac2.write(buf2);
161  } break;
162  }
163  assert(ring_buffer.isEmpty());
164  return result;
165  }
166 };
167 
169 using AnalogDriver = AnalogDriverMBED;
170 
171 } // namespace audio_tools
172 
173 #endif // USE_ANALOG
ESP32 specific configuration for i2s input via adc. The default input pin is GPIO34....
Definition: AnalogConfigESP32.h:21
Definition: AnalogAudioBase.h:13
Please use AnalogAudioStream: A ADC and DAC API for the Arduino Giga.
Definition: AnalogAudioMBED.h:16
size_t write(const uint8_t *src, size_t size_bytes) override
writes the data to the I2S interface
Definition: AnalogAudioMBED.h:72
bool begin(AnalogConfig cfg)
starts the DAC
Definition: AnalogAudioMBED.h:25
void end() override
stops the I2S and unistalls the driver
Definition: AnalogAudioMBED.h:59
virtual ~AnalogDriverMBED()
Destructor.
Definition: AnalogAudioMBED.h:22
size_t writeBuffer()
The ringbuffer is used to make sure that we can write full SampleBuffers.
Definition: AnalogAudioMBED.h:140
AnalogDriverMBED()=default
Default constructor.
virtual T read()
reads a single value
Definition: Buffers.h:305
virtual bool write(T data)
write add an entry to the buffer
Definition: Buffers.h:343
virtual void reset()
clears the buffer
Definition: Buffers.h:355
virtual bool isFull()
checks if the buffer is full
Definition: Buffers.h:338
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
AnalogDriverArduino AnalogDriver
AnalogAudioStream.
Definition: AnalogAudioArduino.h:258
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:53
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:55
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:57