arduino-audio-tools
Loading...
Searching...
No Matches
I2SCodecStream.h
1#pragma once
2#include "AudioBoard.h" // install audio-driver library
3#include "AudioToolsConfig.h"
4#include "AudioTools/CoreAudio/AudioI2S/I2SStream.h"
5
6//#pragma GCC diagnostic ignored "-Wclass-memaccess"
7
8// Added to be compatible with the AudioKitStream.h
9#ifndef PIN_AUDIO_KIT_SD_CARD_CS
10#define PIN_AUDIO_KIT_SD_CARD_CS 13
11#define PIN_AUDIO_KIT_SD_CARD_MISO 2
12#define PIN_AUDIO_KIT_SD_CARD_MOSI 15
13#define PIN_AUDIO_KIT_SD_CARD_CLK 14
14#endif
15
16namespace audio_tools {
17
24struct I2SCodecConfig : public I2SConfig {
25 input_device_t input_device = ADC_INPUT_LINE1;
26 output_device_t output_device = DAC_OUTPUT_ALL;
27 // to be compatible with the AudioKitStream -> do not activate SD spi if false
28 bool sd_active = true;
29 bool sdmmc_active = false;
30 // define pin source in driver configuration
31 PinFunction i2s_function = PinFunction::UNDEFINED; //CODEC;
32 bool operator==(I2SCodecConfig alt) {
33 return input_device == alt.input_device &&
34 output_device == alt.output_device && *((AudioInfo *)this) == alt;
35 }
36
37 bool operator!=(I2SCodecConfig alt) { return !(*this == alt); }
38};
39
47 public:
49 I2SCodecStream() = default;
60
63 auto cfg1 = i2s.defaultConfig(mode);
65 memcpy(&cfg, &cfg1, sizeof(cfg1));
66 cfg.input_device = ADC_INPUT_LINE1;
67 cfg.output_device = DAC_OUTPUT_ALL;
68 cfg.sd_active = true;
69 cfg.rx_tx_mode = mode;
70 return cfg;
71 }
72
73 bool begin() {
74 TRACED();
75 return begin(cfg);
76 }
77
79 virtual bool begin(I2SCodecConfig cfg) {
80 TRACED();
81 this->cfg = cfg;
82 this->info = cfg;
83 return begin1();
84 }
85
87 void end() {
88 TRACED();
89 if (p_board) p_board->end();
90 i2s.end();
91 is_active = false;
92 }
93
95 virtual void setAudioInfo(AudioInfo info) {
96 TRACEI();
98 i2s.setAudioInfo(info);
99
100 cfg.sample_rate = info.sample_rate;
102 cfg.channels = info.channels;
103
104 // update codec_cfg
105 codec_cfg.i2s.bits = toCodecBits(cfg.bits_per_sample);
106 codec_cfg.i2s.rate = toRate(cfg.sample_rate);
107
108 // return if we we are not ready
109 if (!is_active || p_board == nullptr) {
110 return;
111 }
112
113 // return if there is nothing to do
114 if (cfg.sample_rate == info.sample_rate &&
115 cfg.bits_per_sample == info.bits_per_sample &&
116 cfg.channels == info.channels) {
117 return;
118 }
119
120 // update cfg
121 p_board->setConfig(codec_cfg);
122 }
123
125 virtual size_t write(const uint8_t *data, size_t len) {
126 LOGD("I2SStream::write: %d", len);
127 return i2s.write(data, len);
128 }
129
131 virtual size_t readBytes(uint8_t *data, size_t len) override {
132 return i2s.readBytes(data, len);
133 }
134
136 virtual int available() override { return i2s.available(); }
137
139 virtual int availableForWrite() override { return i2s.availableForWrite(); }
140
142 bool setVolume(float vol) override {
144 if (!is_active || p_board == nullptr) return false;
145 return p_board->setVolume(vol * 100.0);
146 }
147
149 float volume() override {
150 if (p_board == nullptr) return 0.0f;
151 return static_cast<float>(p_board->getVolume()) / 100.0f;
152 }
154 float getVolume() { return volume(); }
155
157 bool setMute(bool mute) {
158 if (p_board == nullptr) return false;
159 return p_board->setMute(mute);
160 }
162 bool setMute(bool mute, int line) {
163 if (p_board == nullptr) return false;
164 return p_board->setMute(mute, line);
165 }
166
168 bool setPAPower(bool active) {
169 if (p_board == nullptr) return false;
170 return p_board->setPAPower(active);
171 }
172
174 bool setInputVolume(float vol){
175 if (!is_active || p_board == nullptr) return false;
176 return p_board->setInputVolume(100.0 * vol);
177 }
178
180 AudioBoard &board() { return *p_board; }
182 void setBoard(AudioBoard &board) { p_board = &board; }
184 void setBoard(AudioBoard *board) { p_board = board; }
186 bool hasBoard() { return p_board != nullptr; }
187
189 GpioPin getPinID(PinFunction function) {
190 if (p_board == nullptr) return -1;
191 return p_board->getPins().getPinID(function);
192 }
193
195 GpioPin getPinID(PinFunction function, int pos) {
196 if (p_board == nullptr) return -1;
197 return p_board->getPins().getPinID(function, pos);
198 }
199
201 GpioPin getKey(int pos) { return getPinID(PinFunction::KEY, pos); }
202
204 DriverPins &getPins() { return p_board->getPins(); }
205
207 I2SDriver *driver() { return i2s.driver(); }
208
210 void digitalWrite(int pin, bool value) {
211 p_board->getPins().getGPIO().digitalWrite(pin, value);
212 }
213
215 bool digitalRead(int pin) {
216 return p_board->getPins().getGPIO().digitalRead(pin);
217 }
218
219 protected:
220 I2SStream i2s;
221 I2SCodecConfig cfg;
222 CodecConfig codec_cfg;
223 AudioBoard *p_board = nullptr;
224 bool is_active = false;
225
226 bool begin1() {
227 TRACED();
229 setupI2SPins();
230 if (!beginCodec(cfg)) {
231 TRACEE();
232 is_active = false;
233 return false;
234 }
235 is_active = i2s.begin(cfg);
236
237 // if setvolume was called before begin
238 float tobeVol = VolumeSupport::volume();
239 if (is_active && tobeVol >= 0.0f) {
240 setVolume(tobeVol);
241 }
242 return is_active;
243 }
244
247 if (cfg.i2s_function == PinFunction::UNDEFINED){
248 if (cfg.rx_tx_mode == RX_MODE){
249 auto i2s = p_board->getPins().getI2SPins(PinFunction::CODEC_ADC);
250 if (i2s){
251 cfg.i2s_function = PinFunction::CODEC_ADC;
252 LOGI("using i2s_function: CODEC_ADC");
253 } else {
254 cfg.i2s_function = PinFunction::CODEC;
255 }
256 } else {
257 cfg.i2s_function = PinFunction::CODEC;
258 }
259 }
260 }
261
264 TRACED();
265 // determine relevant I2S pins from driver configuration
266 auto i2s = getI2SPins();
267 if (i2s) {
268 // determine i2s pins from board definition
269 PinsI2S i2s_pins = i2s.value();
270 cfg.pin_bck = i2s_pins.bck;
271 cfg.pin_mck = i2s_pins.mclk;
272 cfg.pin_ws = i2s_pins.ws;
273 switch (cfg.rx_tx_mode) {
274 case RX_MODE:
275 cfg.pin_data = i2s_pins.data_in;
276 break;
277 case TX_MODE:
278 cfg.pin_data = i2s_pins.data_out;
279 break;
280 default:
281 cfg.pin_data = i2s_pins.data_out;
282 cfg.pin_data_rx = i2s_pins.data_in;
283 break;
284 }
285 }
286 }
287
288 audio_driver_local::Optional<PinsI2S> getI2SPins(){
289 TRACED();
290 audio_driver_local::Optional<PinsI2S> i2s;
291 // Deterine I2S pins
292 return p_board->getPins().getI2SPins(cfg.i2s_function);
293 }
294
295 bool beginCodec(I2SCodecConfig info) {
296 TRACED();
297 switch (cfg.rx_tx_mode) {
298 case RX_MODE:
299 codec_cfg.input_device = info.input_device;
300 codec_cfg.output_device = DAC_OUTPUT_NONE;
301 break;
302 case TX_MODE:
303 codec_cfg.output_device = info.output_device;
304 codec_cfg.input_device = ADC_INPUT_NONE;
305 break;
306 default:
307 codec_cfg.input_device = info.input_device;
308 codec_cfg.output_device = info.output_device;
309 break;
310 }
311 codec_cfg.sd_active = info.sd_active;
312 codec_cfg.sdmmc_active = info.sdmmc_active;
313 LOGD("input: %d", info.input_device);
314 LOGD("output: %d", info.output_device);
315 codec_cfg.i2s.bits = toCodecBits(info.bits_per_sample);
316 codec_cfg.i2s.rate = toRate(info.sample_rate);
317 codec_cfg.i2s.fmt = toFormat(info.i2s_format);
318 codec_cfg.i2s.signal_type = (signal_t) info.signal_type;
319 // use reverse logic for codec setting
320 codec_cfg.i2s.mode = info.is_master ? MODE_SLAVE : MODE_MASTER;
321 if (p_board == nullptr) return false;
322
323 // setup driver only on changes
324 return p_board->begin(codec_cfg);
325 }
326
327 sample_bits_t toCodecBits(int bits) {
328 switch (bits) {
329 case 16:
330 LOGD("BIT_LENGTH_16BITS");
331 return BIT_LENGTH_16BITS;
332 case 24:
333 LOGD("BIT_LENGTH_24BITS");
334 return BIT_LENGTH_24BITS;
335 case 32:
336 LOGD("BIT_LENGTH_32BITS");
337 return BIT_LENGTH_32BITS;
338 }
339 LOGE("Unsupported bits: %d", bits);
340 return BIT_LENGTH_16BITS;
341 }
342 samplerate_t toRate(int rate) {
343 if (rate <= 8000) {
344 LOGD("RATE_8K");
345 return RATE_8K;
346 }
347 if (rate <= 11000) {
348 LOGD("RATE_11K");
349 return RATE_11K;
350 }
351 if (rate <= 16000) {
352 LOGD("RATE_16K");
353 return RATE_16K;
354 }
355 if (rate <= 22050) {
356 LOGD("RATE_22K");
357 return RATE_22K;
358 }
359 if (rate <= 32000) {
360 LOGD("RATE_32K");
361 return RATE_32K;
362 }
363 if (rate <= 44100) {
364 LOGD("RATE_44K");
365 return RATE_44K;
366 }
367 if (rate <= 48000 || rate > 48000) {
368 LOGD("RATE_48K");
369 return RATE_44K;
370 }
371 LOGE("Invalid rate: %d using 44K", rate);
372 return RATE_44K;
373 }
374
375 i2s_format_t toFormat(I2SFormat fmt) {
376 switch (fmt) {
377 case I2S_PHILIPS_FORMAT:
378 case I2S_STD_FORMAT:
379 LOGD("I2S_NORMAL");
380 return I2S_NORMAL;
381 case I2S_LEFT_JUSTIFIED_FORMAT:
382 case I2S_MSB_FORMAT:
383 LOGD("I2S_LEFT");
384 return I2S_LEFT;
385 case I2S_RIGHT_JUSTIFIED_FORMAT:
386 case I2S_LSB_FORMAT:
387 LOGD("I2S_RIGHT");
388 return I2S_RIGHT;
389 case I2S_PCM:
390 LOGD("I2S_DSP");
391 return I2S_DSP;
392 default:
393 LOGE("unsupported mode");
394 return I2S_NORMAL;
395 }
396 }
397};
398
399} // namespace audio_tools
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition BaseStream.h:122
virtual void setAudioInfo(AudioInfo newInfo) override
Defines the input AudioInfo.
Definition BaseStream.h:130
I2S Stream which also sets up a codec chip and i2s.
Definition I2SCodecStream.h:46
bool hasBoard()
checks if a board has been defined
Definition I2SCodecStream.h:186
DriverPins & getPins()
Provides access to the pin information.
Definition I2SCodecStream.h:204
I2SCodecStream(AudioBoard &board)
Default constructor: for available AudioBoard values check audioboard variables in https://pschatzman...
Definition I2SCodecStream.h:57
bool setMute(bool mute, int line)
Mute / unmute of an individual line (codec)
Definition I2SCodecStream.h:162
virtual size_t readBytes(uint8_t *data, size_t len) override
Reads the audio data.
Definition I2SCodecStream.h:131
void setBoard(AudioBoard &board)
(re)defines the board
Definition I2SCodecStream.h:182
I2SCodecStream(AudioBoard *board)
Provide board via pointer.
Definition I2SCodecStream.h:59
virtual int availableForWrite() override
Provides the available audio data.
Definition I2SCodecStream.h:139
bool setInputVolume(float vol)
Sets the volume of the microphone (if available)
Definition I2SCodecStream.h:174
I2SCodecConfig defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration.
Definition I2SCodecStream.h:62
float volume() override
Provides the actual volume (0.0f - 1.0f)
Definition I2SCodecStream.h:149
I2SDriver * driver()
Provides the i2s driver.
Definition I2SCodecStream.h:207
virtual void setAudioInfo(AudioInfo info)
updates the sample rate dynamically
Definition I2SCodecStream.h:95
virtual size_t write(const uint8_t *data, size_t len)
Writes the audio data to I2S.
Definition I2SCodecStream.h:125
GpioPin getKey(int pos)
Provides the gpio for the indicated key pos.
Definition I2SCodecStream.h:201
AudioBoard & board()
Provides the board.
Definition I2SCodecStream.h:180
void digitalWrite(int pin, bool value)
set value of digital pin
Definition I2SCodecStream.h:210
I2SCodecStream()=default
Default Constructor (w/o codec)
bool setMute(bool mute)
Mute / unmote.
Definition I2SCodecStream.h:157
virtual bool begin(I2SCodecConfig cfg)
Starts the I2S interface.
Definition I2SCodecStream.h:79
void setupI2SFunction()
if the cfg.i2s_function was not defined we determine the "correct" default value
Definition I2SCodecStream.h:246
void end()
Stops the I2S interface.
Definition I2SCodecStream.h:87
void setupI2SPins()
We use the board pins if they are available.
Definition I2SCodecStream.h:263
GpioPin getPinID(PinFunction function, int pos)
Provides the gpio for the indicated function.
Definition I2SCodecStream.h:195
float getVolume()
legacy: same as volume()
Definition I2SCodecStream.h:154
void setBoard(AudioBoard *board)
(re)defines the board
Definition I2SCodecStream.h:184
bool digitalRead(int pin)
get value of digital pin
Definition I2SCodecStream.h:215
bool setPAPower(bool active)
Sets the output of the PA Power Pin.
Definition I2SCodecStream.h:168
bool setVolume(float vol) override
sets the volume (range 0.0f - 1.0f)
Definition I2SCodecStream.h:142
GpioPin getPinID(PinFunction function)
Provides the gpio for the indicated function.
Definition I2SCodecStream.h:189
virtual int available() override
Provides the available audio data.
Definition I2SCodecStream.h:136
Configuration for ESP32 legacy i2s.
Definition I2SConfigESP32.h:24
RxTxMode rx_tx_mode
public settings
Definition I2SConfigESP32.h:60
Basic I2S API - for the ESP32. If we receive 1 channel, we expand the result to 2 channels.
Definition I2SESP32.h:25
We support the Stream interface for the I2S access. In addition we allow a separate mute pin which mi...
Definition I2SStream.h:33
virtual size_t readBytes(uint8_t *data, size_t len) override
Reads the audio data.
Definition I2SStream.h:125
virtual int availableForWrite() override
Provides the available audio data.
Definition I2SStream.h:133
I2SConfig defaultConfig(RxTxMode mode=TX_MODE)
Provides the default configuration.
Definition I2SStream.h:50
I2SDriver * driver()
Provides access to the driver.
Definition I2SStream.h:138
virtual void setAudioInfo(AudioInfo info)
updates the sample rate dynamically
Definition I2SStream.h:95
virtual size_t write(const uint8_t *data, size_t len)
Writes the audio data to I2S.
Definition I2SStream.h:118
void end()
Stops the I2S interface.
Definition I2SStream.h:85
virtual int available() override
Provides the available audio data.
Definition I2SStream.h:130
Supports the setting and getting of the volume.
Definition AudioTypes.h:191
virtual float volume()
provides the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:194
virtual bool setVolume(float volume)
define the actual volume in the range of 0.0f to 1.0f
Definition AudioTypes.h:196
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition AudioCodecsBase.h:10
I2SFormat
I2S Formats.
Definition AudioTypes.h:420
Basic Audio information which drives e.g. I2S.
Definition AudioTypes.h:55
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition AudioTypes.h:57
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition AudioTypes.h:59
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition AudioTypes.h:61
Configuration for I2SCodecStream.
Definition I2SCodecStream.h:24