arduino-audio-tools
I2SESP8266.h
1 #pragma once
2 
3 #ifdef ESP8266
4 #include <I2S.h>
5 
6 #include "AudioI2S/I2SConfig.h"
7 #include "AudioTools/AudioLogger.h"
8 
9 namespace audio_tools {
10 
19  friend class I2SStream;
20 
21  public:
24  I2SConfigStd c(mode);
25  return c;
26  }
27 
29  bool setAudioInfo(AudioInfo) { return false; }
30 
32  bool begin(RxTxMode mode = TX_MODE) { return begin(defaultConfig(mode)); }
33 
35  bool begin(I2SConfigStd cfg) {
36  this->cfg = cfg;
37  i2s_set_rate(cfg.sample_rate);
38  cfg.bits_per_sample = 16;
39  if (!i2s_rxtx_begin(cfg.rx_tx_mode == RX_MODE, cfg.rx_tx_mode == TX_MODE)) {
40  LOGE("i2s_rxtx_begin failed");
41  return false;
42  }
43  return true;
44  }
45 
47  void end() { i2s_end(); }
48 
50  int available() { return I2S_BUFFER_COUNT * I2S_BUFFER_SIZE; }
51 
53  int availableForWrite() { return I2S_BUFFER_COUNT * I2S_BUFFER_SIZE; }
54 
56  I2SConfigStd config() { return cfg; }
57 
58  protected:
59  I2SConfigStd cfg;
60 
62  size_t writeBytes(const void *src, size_t size_bytes) {
63  size_t result = 0;
64  size_t frame_size = cfg.channels * (cfg.bits_per_sample / 8);
65  uint16_t frame_count = size_bytes / frame_size;
66  if (cfg.channels == 2 && cfg.bits_per_sample == 16) {
67  result = i2s_write_buffer((int16_t *)src, frame_count) * frame_size;
68  } else {
69  result = writeExt(src, size_bytes);
70  }
71  return result;
72  }
73 
75  size_t writeExt(const void *src, size_t size_bytes) {
76  size_t result = 0;
77  int j;
78 
79  switch (cfg.bits_per_sample) {
80  case 8:
81  for (j = 0; j < size_bytes; j += cfg.channels) {
82  int8_t *data = (int8_t *)src;
83  int16_t frame[2];
84  frame[0] = data[j] * 256;
85  if (cfg.channels == 1) {
86  frame[1] = data[j] * 256;
87  } else {
88  frame[1] = data[j + 1] * 256;
89  }
90  uint32_t *frame_ptr = (uint32_t *)frame;
91  if (i2s_write_sample(*frame_ptr)) {
92  result += 2;
93  }
94  }
95  break;
96 
97  case 16:
98  for (j = 0; j < size_bytes / 2; j += cfg.channels) {
99  int16_t *data = (int16_t *)src;
100  int16_t frame[2];
101  frame[0] = data[j];
102  if (cfg.channels == 1) {
103  frame[1] = data[j];
104  } else {
105  frame[1] = data[j + 1];
106  }
107  uint32_t *frame_ptr = (uint32_t *)frame;
108  if (i2s_write_sample(*frame_ptr)) {
109  result += 2;
110  }
111  }
112  break;
113 
114  case 24:
115  for (j = 0; j < size_bytes / 3; j += cfg.channels) {
116  int24_t *data = (int24_t *)src;
117  int24_t frame[2];
118  int32_t value = data[j];
119  frame[0] = value;
120  if (cfg.channels == 1) {
121  frame[1] = value;
122  } else {
123  value = data[j + 1];
124  frame[1] = value / 256;
125  }
126  uint32_t *frame_ptr = (uint32_t *)frame;
127  if (i2s_write_sample(*frame_ptr)) {
128  result += 2;
129  }
130  }
131  break;
132 
133  case 32:
134  for (j = 0; j < size_bytes / 4; j += cfg.channels) {
135  int32_t *data = (int32_t *)src;
136  int32_t frame[2];
137  frame[0] = data[j] / 65538;
138  if (cfg.channels == 1) {
139  frame[1] = data[j] / 65538;
140  } else {
141  frame[1] = data[j + 1] / 65538;
142  }
143  uint32_t *frame_ptr = (uint32_t *)frame;
144  if (i2s_write_sample(*frame_ptr)) {
145  result += 2;
146  }
147  }
148  break;
149  }
150  return result;
151  }
152 
154  size_t readBytes(void *dest, size_t size_bytes) {
155  size_t result_bytes = 0;
156  uint16_t frame_size = cfg.channels * (cfg.bits_per_sample / 8);
157  size_t frames = size_bytes / frame_size;
158  int16_t *ptr = (int16_t *)dest;
159 
160  for (int j = 0; j < frames; j++) {
161  int16_t *left = ptr;
162  int16_t *right = ptr + 1;
163  bool ok = i2s_read_sample(
164  left, right, false); // RX data returned in both 16-bit outputs.
165  if (!ok) {
166  break;
167  }
168  ptr += 2;
169  result_bytes += frame_size;
170  }
171  return result_bytes;
172  }
173 };
174 
175 using I2SDriver = I2SDriverESP8266;
176 
177 } // namespace audio_tools
178 
179 #endif
Configuration for i2s.
Definition: I2SConfigStd.h:17
RxTxMode rx_tx_mode
public settings
Definition: I2SConfigStd.h:50
Basic I2S API - for the ESP8266 Only 16 bits are supported !
Definition: I2SESP8266.h:18
bool setAudioInfo(AudioInfo)
Potentially updates the sample rate (if supported)
Definition: I2SESP8266.h:29
I2SConfigStd config()
provides the actual configuration
Definition: I2SESP8266.h:56
int available()
we assume the data is already available in the buffer
Definition: I2SESP8266.h:50
I2SConfigStd defaultConfig(RxTxMode mode)
Provides the default configuration.
Definition: I2SESP8266.h:23
int availableForWrite()
We limit the write size to the buffer size.
Definition: I2SESP8266.h:53
size_t writeExt(const void *src, size_t size_bytes)
writes the data by making shure that we send 2 channels 16 bit data
Definition: I2SESP8266.h:75
bool begin(I2SConfigStd cfg)
starts the DAC
Definition: I2SESP8266.h:35
void end()
stops the I2C and unistalls the driver
Definition: I2SESP8266.h:47
size_t writeBytes(const void *src, size_t size_bytes)
writes the data to the I2S interface
Definition: I2SESP8266.h:62
size_t readBytes(void *dest, size_t size_bytes)
reads the data from the I2S interface
Definition: I2SESP8266.h:154
bool begin(RxTxMode mode=TX_MODE)
starts the DAC with the default config
Definition: I2SESP8266.h:32
We support the Stream interface for the I2S access. In addition we allow a separate mute pin which mi...
Definition: I2SStream.h:31
24bit integer which is used for I2S sound processing. The values are represented as int32_t,...
Definition: Int24_4bytes_t.h:16
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:26
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AnalogAudio.h:10
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:50
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