M5Unified
Speaker_Class.hpp
Go to the documentation of this file.
1 // Copyright (c) M5Stack. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 
4 #ifndef __M5_Speaker_Class_H__
5 #define __M5_Speaker_Class_H__
6 
7 #include "m5unified_common.h"
8 
9 #if defined ( ESP_PLATFORM )
10 
11 #include <freertos/FreeRTOS.h>
12 #include <freertos/task.h>
13 #include <driver/i2s.h>
14 
15 #endif
16 
17 #include <atomic>
18 
19 #ifndef I2S_PIN_NO_CHANGE
20 #define I2S_PIN_NO_CHANGE (-1)
21 #endif
22 
23 namespace m5
24 {
25  class M5Unified;
26 
28  {
31 
34 
37 
39  uint32_t sample_rate = 64000;
40 
42  bool stereo = false;
43 
45  bool buzzer = false;
46 
49  bool use_dac = false;
50 
52  uint8_t dac_zero_level = 0;
53 
55  uint8_t magnification = 16;
56 
58  size_t dma_buf_len = 256;
59 
61  size_t dma_buf_count = 8;
62 
64  uint8_t task_priority = 2;
65 
67  uint8_t task_pinned_core = ~0;
68 
70  i2s_port_t i2s_port = i2s_port_t::I2S_NUM_0;
71  };
72 
74  {
75  friend M5Unified;
76  public:
77  virtual ~Speaker_Class(void) {}
78 
79  speaker_config_t config(void) const { return _cfg; }
80  void config(const speaker_config_t& cfg) { _cfg = cfg; }
81 
82  bool begin(void);
83 
84  void end(void);
85 
86  bool isRunning(void) const { return _task_running; }
87 
88  bool isEnabled(void) const
89  {
90 #if defined (ESP_PLATFORM)
91  return _cfg.pin_data_out >= 0;
92 #else
93  return true;
94 #endif
95  }
96 
99  bool isPlaying(void) const volatile { return _play_channel_bits.load(); }
100 
104  size_t isPlaying(uint8_t channel) const volatile { return (channel < sound_channel_max) ? ((bool)_ch_info[channel].wavinfo[0].repeat) + ((bool)_ch_info[channel].wavinfo[1].repeat) : 0; }
105 
108  size_t getPlayingChannels(void) const volatile { return __builtin_popcount(_play_channel_bits.load()); }
109 
112  void setVolume(uint8_t master_volume) { _master_volume = master_volume; }
113 
116  uint8_t getVolume(void) const { return _master_volume; }
117 
120  void setAllChannelVolume(uint8_t volume) { for (size_t ch = 0; ch < sound_channel_max; ++ch) { _ch_info[ch].volume = volume; } }
121 
125  void setChannelVolume(uint8_t channel, uint8_t volume) { if (channel < sound_channel_max) { _ch_info[channel].volume = volume; } }
126 
130  uint8_t getChannelVolume(uint8_t channel) const { return (channel < sound_channel_max) ? _ch_info[channel].volume : 0; }
131 
133  void stop(void);
134 
137  void stop(uint8_t channel);
138 
147  bool tone(float frequency, uint32_t duration, int channel, bool stop_current_sound, const uint8_t* raw_data, size_t array_len, bool stereo = false)
148  {
149  return _play_raw(raw_data, array_len, false, false, frequency * (array_len >> stereo), stereo, (duration != UINT32_MAX) ? (uint32_t)(duration * frequency / 1000) : UINT32_MAX, channel, stop_current_sound, true);
150  }
151 
156  bool tone(float frequency, uint32_t duration = UINT32_MAX, int channel = -1, bool stop_current_sound = true) { return tone(frequency, duration, channel, stop_current_sound, _default_tone_wav, sizeof(_default_tone_wav), false); }
157 
168  bool playRaw(const int8_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false)
169  {
170  return _play_raw(static_cast<const void* >(raw_data), array_len, false, true, sample_rate, stereo, repeat, channel, stop_current_sound, false);
171  }
172  [[deprecated("The playRAW function has been renamed to playRaw")]]
173  bool playRAW(const int8_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false)
174  {
175  return _play_raw(static_cast<const void* >(raw_data), array_len, false, true, sample_rate, stereo, repeat, channel, stop_current_sound, false);
176  }
177 
188  bool playRaw(const uint8_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false)
189  {
190  return _play_raw(static_cast<const void* >(raw_data), array_len, false, false, sample_rate, stereo, repeat, channel, stop_current_sound, false);
191  }
192  [[deprecated("The playRAW function has been renamed to playRaw")]]
193  bool playRAW(const uint8_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false)
194  {
195  return _play_raw(static_cast<const void* >(raw_data), array_len, false, false, sample_rate, stereo, repeat, channel, stop_current_sound, false);
196  }
197 
208  bool playRaw(const int16_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false)
209  {
210  return _play_raw(static_cast<const void* >(raw_data), array_len, true, true, sample_rate, stereo, repeat, channel, stop_current_sound, false);
211  }
212 
214  [[deprecated("The playRAW function has been renamed to playRaw")]]
215  bool playRAW(const int16_t* raw_data, size_t array_len, uint32_t sample_rate = 44100, bool stereo = false, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false)
216  {
217  return _play_raw(static_cast<const void* >(raw_data), array_len, true, true, sample_rate, stereo, repeat, channel, stop_current_sound, false);
218  }
219 
225  bool playWav(const uint8_t* wav_data, size_t data_len = ~0u, uint32_t repeat = 1, int channel = -1, bool stop_current_sound = false);
226 
227  protected:
228 
229  static constexpr const size_t sound_channel_max = 8;
230 
231  static const uint8_t _default_tone_wav[16];
232 
233  void setCallback(void* args, bool(*func)(void*, bool)) { _cb_set_enabled = func; _cb_set_enabled_args = args; }
234 
235  struct wav_info_t
236  {
237  volatile uint32_t repeat = 0;
238  uint32_t sample_rate_x256 = 0;
239  const void* data = nullptr;
240  size_t length = 0;
241  union
242  {
243  volatile uint8_t flg = 0;
244  struct
245  {
246  uint8_t is_stereo : 1;
247  uint8_t is_16bit : 1;
248  uint8_t is_signed : 1;
249  uint8_t stop_current : 1;
250  uint8_t no_clear_index : 1;
251  };
252  };
253  void clear(void);
254  };
255 
257  {
258  wav_info_t wavinfo[2]; // current/next flip info.
259  size_t index = 0;
260  int diff = 0;
261  volatile uint8_t volume = 255; // channel volume (not master volume)
262  volatile bool flip = false;
263 
264  float liner_buf[2][2] = { { 0, 0 }, { 0, 0 } };
265  };
266 
268 
269  static void spk_task(void* args);
270 
271  esp_err_t _setup_i2s(void);
272  bool _play_raw(const void* wav, size_t array_len, bool flg_16bit, bool flg_signed, float sample_rate, bool flg_stereo, uint32_t repeat_count, int channel, bool stop_current_sound, bool no_clear_index);
273  bool _set_next_wav(size_t ch, const wav_info_t& wav);
274 
276  volatile uint8_t _master_volume = 64;
277 
278  bool (*_cb_set_enabled)(void* args, bool enabled) = nullptr;
279  void* _cb_set_enabled_args = nullptr;
280 
281  volatile bool _task_running = false;
282  std::atomic<uint16_t> _play_channel_bits = { 0 };
283 #if defined (SDL_h_)
284  SDL_Thread* _task_handle = nullptr;
285 #else
286  TaskHandle_t _task_handle = nullptr;
287  volatile SemaphoreHandle_t _task_semaphore = nullptr;
288 #endif
289  };
290 }
291 
292 #endif
#define I2S_PIN_NO_CHANGE
bool(* _cb_set_enabled)(void *args, bool enabled)
void setAllChannelVolume(uint8_t volume)
bool isEnabled(void) const
volatile bool _task_running
bool playRAW(const int8_t *raw_data, size_t array_len, uint32_t sample_rate=44100, bool stereo=false, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
void stop(void)
stop sound output.
bool playRaw(const int16_t *raw_data, size_t array_len, uint32_t sample_rate=44100, bool stereo=false, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
size_t isPlaying(uint8_t channel) const volatile
bool playRAW(const int16_t *raw_data, size_t array_len, uint32_t sample_rate=44100, bool stereo=false, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
bool tone(float frequency, uint32_t duration=UINT32_MAX, int channel=-1, bool stop_current_sound=true)
speaker_config_t config(void) const
bool _set_next_wav(size_t ch, const wav_info_t &wav)
TaskHandle_t _task_handle
void config(const speaker_config_t &cfg)
bool playRAW(const uint8_t *raw_data, size_t array_len, uint32_t sample_rate=44100, bool stereo=false, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
channel_info_t _ch_info[sound_channel_max]
bool isRunning(void) const
volatile uint8_t _master_volume
bool playWav(const uint8_t *wav_data, size_t data_len=~0u, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
bool _play_raw(const void *wav, size_t array_len, bool flg_16bit, bool flg_signed, float sample_rate, bool flg_stereo, uint32_t repeat_count, int channel, bool stop_current_sound, bool no_clear_index)
esp_err_t _setup_i2s(void)
static void spk_task(void *args)
uint8_t getVolume(void) const
bool isPlaying(void) const volatile
size_t getPlayingChannels(void) const volatile
static const uint8_t _default_tone_wav[16]
virtual ~Speaker_Class(void)
std::atomic< uint16_t > _play_channel_bits
void setVolume(uint8_t master_volume)
static constexpr const size_t sound_channel_max
bool playRaw(const uint8_t *raw_data, size_t array_len, uint32_t sample_rate=44100, bool stereo=false, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
uint8_t getChannelVolume(uint8_t channel) const
bool tone(float frequency, uint32_t duration, int channel, bool stop_current_sound, const uint8_t *raw_data, size_t array_len, bool stereo=false)
volatile SemaphoreHandle_t _task_semaphore
void setCallback(void *args, bool(*func)(void *, bool))
bool playRaw(const int8_t *raw_data, size_t array_len, uint32_t sample_rate=44100, bool stereo=false, uint32_t repeat=1, int channel=-1, bool stop_current_sound=false)
void setChannelVolume(uint8_t channel, uint8_t volume)
speaker_config_t _cfg
Definition: M5Unified.cpp:48
uint32_t sample_rate_x256
-1 mean infinity repeat
uint8_t task_pinned_core
background task pinned core
uint8_t magnification
multiplier for output value
uint8_t dac_zero_level
Zero level reference value when using DAC ( 0=Dynamic change )
bool buzzer
use single gpio buzzer, ( need only pin_data_out )
bool stereo
use stereo output
int pin_ws
i2s_ws (lrck)
int pin_data_out
i2s_data_out (for spk)
uint8_t task_priority
background task priority
uint32_t sample_rate
output sampling rate (Hz)
i2s_port_t i2s_port
I2S port.
size_t dma_buf_count
for I2S dma_buf_count
size_t dma_buf_len
for I2S dma_buf_len (max 1024)