arduino-audio-tools
WM8960Stream.h
1 #pragma once
2 
3 #include "AudioTools/CoreAudio/AudioStreams.h"
4 #include "AudioTools/CoreAudio/AudioI2S/I2SStream.h"
5 #include "mtb_wm8960.h" // https://github.com/pschatzmann/arduino-wm8960
6 
7 namespace audio_tools {
8 
14 class WM8960Config : public I2SConfig {
15  public:
16  WM8960Config() : I2SConfig() {}
17  WM8960Config(RxTxMode mode):I2SConfig(mode){
18  sample_rate = 44100;
19  channels = 2;
20  bits_per_sample = 16;
21  }
23  float default_volume = 0.6;
25  bool vs1053_enable_pll = true;
27  uint32_t vs1053_mclk_hz = 0;
29  TwoWire *wire=nullptr;
31  bool vs1053_dump = false;
33  uint32_t i2c_retry_count = 0;
34  // optional features: use bitmask with WM8960_FEATURE_MICROPHONE,WM8960_FEATURE_HEADPHONE,WM8960_FEATURE_SPEAKER
35  int8_t features = -1;
36 
37 };
38 
46 class WM8960Stream : public AudioStream {
47 
48 public:
49 
50  WM8960Stream() = default;
51 
52  WM8960Config defaultConfig(RxTxMode mode=TX_MODE) {
53  TRACED();
54  WM8960Config c(mode);
55  return c;
56  }
57 
60  cfg = c;
61  begin(c);
62  }
63 
65  cfg.copyFrom(c);
66  begin(cfg);
67  }
68 
70  bool begin() {
71  return begin(cfg);
72  }
73 
75  bool begin(WM8960Config config) {
76  TRACEI();
77  cfg = config;
78 
79  // setup wm8960
80  if (!init(cfg.rx_tx_mode)){
81  LOGE("init");
82  return false;
83  }
85  if (!mtb_wm8960_activate()){
86  LOGE("mtb_wm8960_activate");
87  return false;
88  }
89  if (!configure_clocking()){
90  LOGE("configure_clocking");
91  return false;
92  }
93  if (config.vs1053_dump){
94  mtb_wm8960_dump();
95  }
96 
97  // setup output
98  i2s.begin(cfg);
99 
100  return true;
101  }
102 
104  void end(){
105  TRACEI();
106  i2s.end();
107  mtb_wm8960_deactivate();
108  mtb_wm8960_free();
109  }
110 
112  bool setVolume(float vol){
113  // make sure that value is between 0 and 1
114  setVolumeIn(vol);
115  setVolumeOut(vol);
116  return true;
117  }
118 
119  void setVolumeIn(float vol){
120  adjustInputVolume(vol);
121  }
122 
123  void setVolumeOut(float vol){
124  setOutputVolume(vol);
125  }
126 
128  float volumeIn() {
129  return volume_in;
130  }
131 
132  float volumeOut() {
133  return volume_out;
134  }
135 
136  size_t readBytes (uint8_t *data, size_t size) override{
137  return i2s.readBytes(data, size);
138  }
139 
140  size_t write (const uint8_t *data, size_t size) override {
141  return i2s.write(data, size);
142  }
143 
144 protected:
145  WM8960Config cfg;
146  I2SStream i2s;
147  float volume_in;
148  float volume_out;
149 
150  void adjustInputVolume(float vol){
151  if (vol>1.0f) {
152  volume_in = 1.0f;
153  volumeError(vol);
154  } else if (vol<0.0f){
155  volume_in = 0.0f;
156  volumeError(vol);
157  } else {
158  volume_in = vol;
159  }
160  int vol_int = map(volume_in*100, 0, 100, 0 ,30);
161  mtb_wm8960_adjust_input_volume(vol_int);
162  }
163 
164  void setOutputVolume(float vol){
165  if (vol>1.0f) {
166  volume_out = 1.0f;
167  volumeError(vol);
168  } else if (vol<0.0f){
169  volume_out = 0.0f;
170  volumeError(vol);
171  } else {
172  volume_out = vol;
173  }
174  int vol_int = volume_out==0.0? 0 : map(volume_out*100, 0, 100, 30 ,0x7F);
175  mtb_wm8960_set_output_volume(vol_int);
176  }
177 
178  bool init(RxTxMode mode){
179  mtb_wm8960_set_write_retry_count(cfg.i2c_retry_count);
180  // define wire object
181  mtb_wm8960_set_wire(cfg.wire);
182 
183  // init features if not defined depending on mode
184  if (cfg.features==-1){
185  switch(mode){
186  case RX_MODE:
187  cfg.features = WM8960_FEATURE_MICROPHONE1;
188  break;
189  case TX_MODE:
190  cfg.features = WM8960_FEATURE_HEADPHONE | WM8960_FEATURE_SPEAKER;
191  break;
192  case RXTX_MODE:
193  cfg.features = WM8960_FEATURE_MICROPHONE1 | WM8960_FEATURE_HEADPHONE | WM8960_FEATURE_SPEAKER;
194  break;
195  }
196  LOGW("Setup features: %d", cfg.features);
197  }
198  return mtb_wm8960_init(cfg.features);
199  }
200 
201  bool configure_clocking(){
202  if (cfg.vs1053_mclk_hz==0){
203  // just pick a multiple of the sample rate
204  cfg.vs1053_mclk_hz = 512 * cfg.sample_rate;
205  }
206  if (!mtb_wm8960_configure_clocking(cfg.vs1053_mclk_hz, cfg.vs1053_enable_pll, sampleRate(cfg.sample_rate), wordLength(cfg.bits_per_sample), modeMasterSlave(cfg.is_master))){
207  LOGE("mtb_wm8960_configure_clocking");
208  return false;
209  }
210  return true;
211  }
212 
213  mtb_wm8960_adc_dac_sample_rate_t sampleRate(int rate){
214  switch(rate){
215  case 48000:
216  return WM8960_ADC_DAC_SAMPLE_RATE_48_KHZ;
217  case 44100:
218  return WM8960_ADC_DAC_SAMPLE_RATE_44_1_KHZ;
219  case 32000:
220  return WM8960_ADC_DAC_SAMPLE_RATE_32_KHZ;
221  case 24000:
222  return WM8960_ADC_DAC_SAMPLE_RATE_24_KHZ;
223  case 22050:
224  return WM8960_ADC_DAC_SAMPLE_RATE_22_05_KHZ;
225  case 16000:
226  return WM8960_ADC_DAC_SAMPLE_RATE_16_KHZ;
227  case 12000:
228  return WM8960_ADC_DAC_SAMPLE_RATE_12_KHZ;
229  case 11025:
230  return WM8960_ADC_DAC_SAMPLE_RATE_11_025_KHZ;
231  case 8018:
232  return WM8960_ADC_DAC_SAMPLE_RATE_8_018_KHZ;
233  case 8000:
234  return WM8960_ADC_DAC_SAMPLE_RATE_8_KHZ;
235  default:
236  LOGE("Unsupported rate: %d",rate);
237  return WM8960_ADC_DAC_SAMPLE_RATE_44_1_KHZ;
238  }
239  }
240 
241  mtb_wm8960_word_length_t wordLength(int bits){
242  switch(bits){
243  case 16:
244  return WM8960_WL_16BITS;
245  case 20:
246  return WM8960_WL_20BITS;
247  case 24:
248  return WM8960_WL_24BITS;
249  case 32:
250  return WM8960_WL_32BITS;
251  default:
252  LOGE("Unsupported bits: %d", bits);
253  return WM8960_WL_16BITS;
254  }
255  }
256 
258  mtb_wm8960_mode_t modeMasterSlave(bool microcontroller_is_master){
259  return microcontroller_is_master ? WM8960_MODE_SLAVE : WM8960_MODE_MASTER;
260  }
261 
262  void volumeError(float vol){
263  LOGE("Invalid volume %f", vol);
264  }
265 };
266 
267 }
Base class for all Audio Streams. It support the boolean operator to test if the object is ready with...
Definition: BaseStream.h:109
Configuration for ESP32 legacy i2s.
Definition: I2SConfigESP32.h:23
RxTxMode rx_tx_mode
public settings
Definition: I2SConfigESP32.h:59
virtual size_t readBytes(uint8_t *data, size_t len) override
Reads the audio data.
Definition: I2SStream.h:122
virtual size_t write(const uint8_t *data, size_t len)
Writes the audio data to I2S.
Definition: I2SStream.h:115
void end()
Stops the I2S interface.
Definition: I2SStream.h:84
Configuration for WM8960.
Definition: WM8960Stream.h:14
bool vs1053_enable_pll
enalbel pll for wm8960 - default is true
Definition: WM8960Stream.h:25
TwoWire * wire
Define wire if we do not use the default Wire object.
Definition: WM8960Stream.h:29
uint32_t i2c_retry_count
Number of i2c write retry on fail: 0 = endless until success.
Definition: WM8960Stream.h:33
bool vs1053_dump
Dump registers.
Definition: WM8960Stream.h:31
uint32_t vs1053_mclk_hz
masterclock rate for wm8960 - default is 0
Definition: WM8960Stream.h:27
float default_volume
Volume that is used on start (range 0.0 to 1.0)
Definition: WM8960Stream.h:23
Stream for reading and writing audio data using the WM8960 Codec Chip You need to install https://git...
Definition: WM8960Stream.h:46
mtb_wm8960_mode_t modeMasterSlave(bool microcontroller_is_master)
if microcontroller is master then module is slave
Definition: WM8960Stream.h:258
float volumeIn()
provides the volume
Definition: WM8960Stream.h:128
void setAudioInfo(AudioInfo c)
Defines the input AudioInfo.
Definition: WM8960Stream.h:64
bool begin()
Starts with the default config or restarts.
Definition: WM8960Stream.h:70
bool begin(WM8960Config config)
Starts with the indicated configuration.
Definition: WM8960Stream.h:75
void setAudioInfo(WM8960Config c)
defines the default configuration that is used with the next begin()
Definition: WM8960Stream.h:59
void end()
Stops the processing and releases the memory.
Definition: WM8960Stream.h:104
bool setVolume(float vol)
Sets both input and output volume value (from 0 to 1.0)
Definition: WM8960Stream.h:112
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28
Generic Implementation of sound input and output for desktop environments using portaudio.
Definition: AudioConfig.h:858
long map(long x, long in_min, long in_max, long out_min, long out_max)
Maps input to output values.
Definition: NoArduino.h:162
Basic Audio information which drives e.g. I2S.
Definition: AudioTypes.h:52
void copyFrom(AudioInfo info)
Same as set.
Definition: AudioTypes.h:107
sample_rate_t sample_rate
Sample Rate: e.g 44100.
Definition: AudioTypes.h:55
uint16_t channels
Number of channels: 2=stereo, 1=mono.
Definition: AudioTypes.h:57
uint8_t bits_per_sample
Number of bits per sample (int16_t = 16 bits)
Definition: AudioTypes.h:59