11 #define MINIAUDIO_IMPLEMENTATION
12 #include "miniaudio.h"
14 #define MA_BUFFER_COUNT 100
15 #define MA_START_COUNT MA_BUFFER_COUNT - 2
39 bool is_input =
false;
40 bool is_output =
true;
41 int delay_ms_if_buffer_full = MA_DELAY;
42 int buffer_count = MA_BUFFER_COUNT;
43 int buffer_start_count = MA_START_COUNT;
65 info.is_output =
false;
68 info.is_input =
false;
69 info.is_output =
true;
73 info.is_output =
true;
76 info.is_input =
false;
77 info.is_output =
false;
93 ma_device_uninit(&device_ma);
106 bool begin()
override {
108 if (config.is_output && !config.is_input)
109 config_ma = ma_device_config_init(ma_device_type_playback);
110 else if (!config.is_output && config.is_input)
111 config_ma = ma_device_config_init(ma_device_type_capture);
112 else if (config.is_output && config.is_input)
113 config_ma = ma_device_config_init(ma_device_type_duplex);
114 else if (!config.is_output && !config.is_input)
115 config_ma = ma_device_config_init(ma_device_type_loopback);
117 config_ma.pUserData =
this;
118 config_ma.playback.channels = config.
channels;
120 config_ma.dataCallback = data_callback;
123 config_ma.playback.format = ma_format_u8;
126 config_ma.playback.format = ma_format_s16;
129 config_ma.playback.format = ma_format_s24;
132 config_ma.playback.format = ma_format_s32;
135 LOGE(
"Invalid format");
139 if (ma_device_init(NULL, &config_ma, &device_ma) != MA_SUCCESS) {
145 if (ma_device_start(&device_ma) != MA_SUCCESS) {
154 void end()
override {
158 ma_device_uninit(&device_ma);
161 buffer_out.resize(0);
164 int availableForWrite()
override {
165 return buffer_out.
size() == 0 ? 0 : DEFAULT_BUFFER_SIZE;
168 size_t write(
const uint8_t *data,
size_t len)
override {
169 if (buffer_out.
size() == 0)
return 0;
170 LOGD(
"write: %zu", len);
178 std::lock_guard<std::mutex> guard(write_mtx);
179 result = buffer_out.
writeArray(data + written, open);
184 if (result != len) doWait();
189 if (!is_playing && buffer_out.
available() >= config.buffer_start_count * buffer_size) {
190 LOGI(
"starting audio");
197 int available()
override {
201 size_t readBytes(uint8_t *data,
size_t len)
override {
202 if (buffer_in.
size() == 0)
return 0;
203 LOGD(
"write: %zu", len);
204 std::lock_guard<std::mutex> guard(read_mtx);
209 MiniAudioConfig config;
210 ma_device_config config_ma;
212 bool is_playing =
false;
213 bool is_active =
false;
214 bool is_buffers_setup =
false;
215 RingBuffer<uint8_t> buffer_out{0};
216 RingBuffer<uint8_t> buffer_in{0};
217 std::mutex write_mtx;
226 void setupBuffers(
int size) {
227 if (is_buffers_setup)
return;
229 int buffer_count = config.buffer_count;
230 LOGI(
"setupBuffers: %d * %d", size, buffer_count);
231 if (buffer_out.
size() == 0 && config.is_output)
232 buffer_out.resize(size * buffer_count);
233 if (buffer_in.
size() == 0 && config.is_input)
234 buffer_in.resize(size * buffer_count);
235 is_buffers_setup =
true;
240 delay(config.delay_ms_if_buffer_full);
244 static void data_callback(ma_device *pDevice,
void *pOutput,
245 const void *pInput, ma_uint32 frameCount) {
246 MiniAudioStream *
self = (MiniAudioStream *)pDevice->pUserData;
247 AudioInfo cfg = self->audioInfo();
249 int bytes = frameCount * cfg.channels * cfg.bits_per_sample / 8;
250 self->setupBuffers(bytes);
258 std::unique_lock<mutex> guard(self->read_mtx);
260 self->buffer_in.writeArray((uint8_t *)pInput + processed, open);
264 if (len == 0)
self->doWait();
269 memset(pOutput, 0, bytes);
270 if (self->is_playing) {
276 std::lock_guard<std::mutex> guard(self->write_mtx);
277 len =
self->buffer_out.readArray((uint8_t *)pOutput + processed,
282 if (len != bytes)
self->doWait();
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28