2#include "AudioTools/CoreAudio/AudioEffects/SoundGenerator.h"
3#include "AudioTools/CoreAudio/AudioLogger.h"
4#include "AudioTools/CoreAudio/AudioOutput.h"
5#include "AudioTools/CoreAudio/AudioTimer/AudioTimer.h"
6#include "AudioTools/CoreAudio/AudioTypes.h"
7#include "AudioTools/CoreAudio/BaseConverter.h"
8#include "AudioTools/CoreAudio/BaseStream.h"
9#include "AudioTools/CoreAudio/Buffers.h"
10#include "AudioToolsConfig.h"
28 p_stream->setTimeout(clientTimeout);
31 virtual bool begin() {
return true; }
34 virtual size_t readBytes(uint8_t *data,
size_t len) {
37 return p_stream->readBytes(data, len);
40 int read() {
return p_stream->read(); }
42 int peek() {
return p_stream->peek(); }
44 int available() {
return p_stream->available(); }
46 virtual size_t write(uint8_t c) {
return p_stream->write(c); }
48 virtual size_t write(
const uint8_t *data,
size_t len) {
49 return p_stream->write(data, len);
52 virtual int availableForWrite() {
return p_stream->availableForWrite(); }
54 virtual void flush() { p_stream->flush(); }
58 int32_t clientTimeout = URL_CLIENT_TIMEOUT;
89 LOGD(
"MemoryStream: %d", buffer_size);
90 this->buffer_size = buffer_size;
91 this->memory_type = memoryType;
98 MemoryStream(
const uint8_t *buffer,
int buffer_size,
bool isActive =
true,
100 LOGD(
"MemoryStream: %d", buffer_size);
101 setValue(buffer, buffer_size, memoryType);
102 is_active = isActive;
111 setValue(source.buffer, source.buffer_size, source.memory_type);
113 source.setValue(
nullptr, 0, source.memory_type);
118 if (memoryCanChange() && buffer !=
nullptr) free(buffer);
128 operator bool()
override {
return available() > 0; }
139 write_pos = memoryCanChange() ? 0 : buffer_size;
140 if (this->buffer ==
nullptr && memoryCanChange()) {
148 virtual size_t write(uint8_t
byte)
override {
149 if (!is_active)
return 0;
150 if (memory_type == FLASH_RAM)
return 0;
151 if (buffer ==
nullptr)
return 0;
153 if (write_pos < buffer_size) {
155 buffer[write_pos] = byte;
161 virtual size_t write(
const uint8_t *
data,
size_t len)
override {
162 if (!is_active)
return 0;
163 if (memory_type == FLASH_RAM)
return 0;
165 for (
size_t j = 0; j < len; j++) {
166 if (!write(
data[j])) {
174 virtual int available()
override {
175 if (!is_active)
return 0;
176 if (buffer ==
nullptr)
return 0;
177 int result = write_pos - read_pos;
178 if (result <= 0 && is_loop) {
180 read_pos = rewind_pos;
181 result = write_pos - read_pos;
183 if (rewind !=
nullptr) rewind();
185 return is_loop ? DEFAULT_BUFFER_SIZE : result;
188 virtual int availableForWrite()
override {
189 if (!is_active)
return 0;
190 if (memory_type == FLASH_RAM)
return 0;
191 return buffer_size - write_pos;
194 virtual int read()
override {
202 virtual size_t readBytes(uint8_t *
data,
size_t len)
override {
203 if (!is_active)
return 0;
205 while (count < len) {
214 virtual int peek()
override {
215 if (!is_active)
return -1;
217 if (available() > 0) {
218 result = buffer[read_pos];
223 virtual void flush()
override {}
225 virtual void end()
override {
231 virtual void clear(
bool reset =
false) {
232 if (memoryCanChange()) {
235 if (buffer ==
nullptr) {
240 memset(buffer, 0, buffer_size);
244 LOGW(
"data is read only");
253 if (buffer !=
nullptr && buffer_size > 12) {
254 if (memcmp(
"WAVE", buffer + 8, 4) == 0) {
261 virtual void setLoop(
bool loop,
int rewindPos) {
263 rewind_pos = rewindPos;
269 if (!memoryCanChange())
return false;
272 switch (memory_type) {
273#if defined(ESP32) && defined(ARDUINO)
275 buffer = (buffer ==
nullptr) ? (uint8_t *)ps_calloc(size, 1)
276 : (uint8_t *)ps_realloc(buffer, size);
280 buffer = (buffer ==
nullptr) ? (uint8_t *)calloc(size, 1)
281 : (uint8_t *)realloc(buffer, size);
284 return buffer !=
nullptr;
288 virtual uint8_t *
data() {
return buffer; }
297 void setValue(
const uint8_t *buffer,
int buffer_size,
299 this->buffer_size = buffer_size;
301 this->write_pos = buffer_size;
302 this->buffer = (uint8_t *)buffer;
303 this->memory_type = memoryType;
311 uint8_t *buffer =
nullptr;
313 bool is_loop =
false;
314 void (*rewind)() =
nullptr;
315 bool is_active =
false;
317 bool memoryCanChange() {
return memory_type != FLASH_RAM; }
319 void copy(MemoryStream &source) {
320 if (
this == &source)
return;
321 if (source.memory_type == FLASH_RAM) {
322 setValue(source.buffer, source.buffer_size, source.memory_type);
324 setValue(
nullptr, source.buffer_size, source.memory_type);
326 memcpy(buffer, source.buffer, buffer_size);
342 virtual int available()
override {
344 return buffer.available();
347 virtual int availableForWrite()
override {
348 return buffer.availableForWrite();
351 virtual void flush()
override {}
352 virtual int peek()
override {
354 if (!buffer.peek(data))
return -1;
357 virtual int read()
override {
359 if (!buffer.read(data))
return -1;
363 virtual size_t readBytes(uint8_t *data,
size_t len)
override {
364 return buffer.readArray(data, len);
367 virtual size_t write(
const uint8_t *data,
size_t len)
override {
369 return buffer.writeArray(data, len);
372 virtual size_t write(uint8_t c)
override {
return buffer.write(c); }
374 void resize(
int size) { buffer.resize(size); }
376 size_t size() {
return buffer.size(); }
393template <
class T =
int16_t>
404 this->generator_ptr = &generator;
419 if (generator_ptr ==
nullptr) {
420 LOGE(
"%s", source_not_defined_error);
423 generator_ptr->begin();
424 notifyAudioChange(generator_ptr->
audioInfo());
432 if (generator_ptr ==
nullptr) {
433 LOGE(
"%s", source_not_defined_error);
436 generator_ptr->begin(cfg);
437 notifyAudioChange(generator_ptr->
audioInfo());
445 generator_ptr->
end();
452 virtual int available()
override {
return active ? buffer_size : 0; }
456 if (!active)
return 0;
457 LOGD(
"GeneratedSoundStream::readBytes: %u", (
unsigned int)len);
458 return generator_ptr->
readBytes(data, len);
461 bool isActive() {
return active && generator_ptr->
isActive(); }
463 operator bool()
override {
return isActive(); }
465 void flush()
override {}
468 void resize(
int maxReadSize) { buffer_size = maxReadSize; }
474 DEFAULT_BUFFER_SIZE * 100;
475 const char *source_not_defined_error =
"Source not defined";
490 if (buffer_size > 0)
resize(buffer_size);
496 if (buffer_size > 0)
resize(buffer_size);
502 if (buffer_size > 0)
resize(buffer_size);
508 if (buffer_size > 0)
resize(buffer_size);
514 if (buffer_size > 0)
resize(buffer_size);
526 if (buffer.isFull()) {
529 return buffer.write(c);
533 size_t write(
const uint8_t *data,
size_t len)
override {
534 LOGD(
"%s: %zu", LOG_METHOD, len);
536 for (
int j = 0; j < len; j++) {
537 result +=
write(data[j]);
545 if (buffer.available() > 0) {
546 writeExt(buffer.address(), buffer.available());
553 if (buffer.isEmpty()) {
557 if (!buffer.read(result))
return -1;
563 if (buffer.isEmpty()) {
567 if (!buffer.peek(result))
return -1;
573 if (buffer.isEmpty() && len >= minReadBufferSize) {
574 return readExt(data, len);
577 return buffer.readArray(data, len);
583 if (buffer.isEmpty()) {
586 return buffer.peekArray(data, len);
591 if (p_in ==
nullptr)
return 0;
592 return buffer.available() + p_in->available();
599 void resize(
int size) { buffer.resize(size); }
607 Print *p_out =
nullptr;
608 Stream *p_in =
nullptr;
609 size_t minReadBufferSize = 1024;
615 size_t already_available = buffer.available();
616 size_t free_space = buffer.availableForWrite();
617 if (free_space == 0) {
622 size_t added = readExt(buffer.address() + already_available, free_space);
623 buffer.setAvailable(already_available + added);
628 if (buffer.available() >= len)
return;
632 virtual size_t writeExt(
const uint8_t *data,
size_t len) {
633 return p_out ==
nullptr ? 0 : p_out->write(data, len);
635 virtual size_t readExt(uint8_t *data,
size_t len) {
636 return p_in ==
nullptr ? 0 : p_in->readBytes(data, len);
656 setConverter(converter);
661 setConverter(converter);
676 void setConverter(
BaseConverter &cnv) { p_converter = &cnv; }
678 virtual int availableForWrite() {
return p_out->availableForWrite(); }
680 virtual size_t write(
const uint8_t *data,
size_t len) {
681 size_t result = p_converter->convert((uint8_t *)data, len);
683 size_t result_written = p_out->write(data, result);
684 return len * result_written / result;
689 size_t readBytes(uint8_t *data,
size_t len)
override {
690 if (p_stream ==
nullptr)
return 0;
691 size_t result = p_stream->readBytes(data, len);
692 return p_converter->convert(data, result);
697 if (p_stream ==
nullptr)
return 0;
698 return p_stream->available();
702 Stream *p_stream =
nullptr;
703 Print *p_out =
nullptr;
717 this->max_count = count;
726 this->max_count = count;
734 this->max_count = count;
754 total_bytes_since_begin += len;
755 return measure(p_stream->readBytes(data, len));
758 int available()
override {
return p_stream->available(); }
761 virtual size_t write(
const uint8_t *data,
size_t len)
override {
762 total_bytes_since_begin += len;
763 return measure(p_print->write(data, len));
768 return p_print->availableForWrite();
776 if (frame_size == 0)
return 0;
777 return bytes_per_second / frame_size;
784 AudioStream::info = info;
788 bool begin()
override {
789 total_bytes_since_begin = 0;
791 return AudioStream::begin();
794 bool begin(AudioInfo info) {
805 void setName(
const char *name) { this->name = name; }
829 bool is_regular_update =
true;
830 if (pos < total_bytes_since_begin) {
832 is_regular_update =
false;
834 total_bytes_since_begin = pos;
835 return is_regular_update;
841 Stream *p_stream =
nullptr;
842 Print *p_print =
nullptr;
845 int bytes_per_second = 0;
848 Print *p_logout =
nullptr;
849 bool report_bytes =
false;
850 const char *name =
"";
851 uint32_t ms_at_begin = 0;
852 uint32_t total_bytes_since_begin = 0;
854 size_t measure(
size_t len) {
859 uint32_t end_time =
millis();
860 int time_diff = end_time - start_time;
862 bytes_per_second = total_bytes / time_diff * 1000;
866 start_time = end_time;
874 if (report_bytes || frame_size == 0) {
875 snprintf(msg, 70,
"%s ==> Bytes per second: %d", name, bytes_per_second);
877 snprintf(msg, 70,
"%s ==> Samples per second: %d", name,
878 bytes_per_second / frame_size);
880 if (p_logout !=
nullptr) {
881 p_logout->println(msg);
896 size_t total_size = 0;
915 p_info_from = &stream;
932 void setPrint(Print &print) { p_print = &print; }
934 bool begin()
override {
935 if (p_info_from !=
nullptr) {
938 return AudioStream::begin();
949 progress_info = info;
957 progress_info.total_size = len;
961 size_t size() {
return progress_info.total_size; }
977 if (progress_info.total_size == 0)
return 0;
978 return 100.0 * total_processed / progress_info.total_size;
983 if (p_stream ==
nullptr)
return 0;
984 return measure(p_stream->readBytes(data, len));
987 int available()
override {
988 if (p_stream ==
nullptr)
return 0;
989 return p_stream->available();
993 virtual size_t write(
const uint8_t *data,
size_t len)
override {
994 if (p_print ==
nullptr)
return 0;
995 return measure(p_print->write(data, len));
1000 if (p_print ==
nullptr)
return 0;
1001 return p_print->availableForWrite();
1006 Stream *p_stream =
nullptr;
1007 Print *p_print =
nullptr;
1009 size_t total_processed = 0;
1011 size_t measure(
size_t len) {
1012 total_processed += len;
1018 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1019 if (byte_rate == 0) {
1020 LOGE(
"Audio Info not defined");
1038 int correction_us = 0;
1067 bool begin(ThrottleConfig cfg) {
1068 LOGI(
"begin sample_rate: %d, channels: %d, bits: %d", (
int)info.
sample_rate,
1075 bool begin(AudioInfo info) {
1076 LOGI(
"begin sample_rate: %d, channels: %d, bits: %d", (
int)info.sample_rate,
1077 (
int)info.channels, (
int)info.bits_per_sample);
1079 this->cfg.copyFrom(info);
1083 bool begin()
override {
1084 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1091 start_time = micros();
1095 int availableForWrite()
override {
1097 return p_out->availableForWrite();
1099 return DEFAULT_BUFFER_SIZE;
1102 size_t write(
const uint8_t *data,
size_t len)
override {
1103 size_t result = p_out->write(data, len);
1108 int available()
override {
1109 if (p_in ==
nullptr)
return 0;
1110 return p_in->available();
1113 size_t readBytes(uint8_t *data,
size_t len)
override {
1114 if (p_in ==
nullptr) {
1118 size_t result = p_in->readBytes(data, len);
1124 void delayBytes(
size_t bytes) { delayFrames(bytes / frame_size); }
1127 void delayFrames(
size_t frames) {
1128 sum_frames += frames;
1129 uint64_t durationUsEff = micros() - start_time;
1130 uint64_t durationUsToBe = getDelayUs(sum_frames);
1131 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1132 LOGD(
"wait us: %ld",
static_cast<long>(waitUs));
1134 int64_t waitMs = waitUs / 1000;
1135 if (waitMs > 0) delay(waitMs);
1136 delayMicroseconds(waitUs - (waitMs * 1000));
1138 LOGD(
"negative delay!")
1142 inline int64_t getDelayUs(uint64_t frames) {
1143 return (frames * 1000000) / cfg.sample_rate;
1146 inline int64_t getDelayMs(uint64_t frames) {
1147 return getDelayUs(frames) / 1000;
1150 inline int64_t getDelaySec(uint64_t frames) {
1151 return getDelayUs(frames) / 1000000l;
1155 uint32_t start_time = 0;
1156 uint32_t sum_frames = 0;
1159 Print *p_out =
nullptr;
1160 Stream *p_in =
nullptr;
1172template <
typename T>
1179 streams.push_back(&in);
1180 weights.push_back(weight);
1181 total_weights += weight;
1182 return streams.indexOf(&in);
1187 if (index <
size()) {
1188 streams[index] = ∈
1191 LOGE(
"Invalid index %d - max is %d", index,
size() - 1);
1199 LOGI(
"frame_size: %d", frame_size);
1200 return frame_size > 0;
1207 if (index < streams.size()) {
1208 weights[index] = weight;
1211 LOGE(
"Invalid index %d - max is %d", index,
size() - 1);
1219 result_vect.clear();
1220 current_vect.clear();
1221 total_weights = 0.0;
1225 int size() {
return streams.size(); }
1229 if (total_weights == 0 || frame_size == 0 || len == 0) {
1230 LOGW(
"readBytes: %d", (
int)len);
1234 if (limit_available_data) {
1242 result_len = len * frame_size / frame_size;
1260 if (idx < 0 || idx >=
size()) {
1288 if (idx < 0 || idx >=
size())
return nullptr;
1289 return streams[idx];
1294 for (
int i = 0; i < streams.size(); i++) {
1295 if (streams[i]->available() == 0) {
1304 Vector<int> weights{0};
1305 int total_weights = 0;
1307 bool limit_available_data =
false;
1308 int retry_count = 5;
1309 Vector<int> result_vect;
1310 Vector<T> current_vect;
1315 for (
int j = 0; j < weights.size(); j++) {
1316 total += weights[j];
1318 total_weights = total;
1323 int samples = byteCount /
sizeof(T);
1324 result_vect.resize(samples);
1325 current_vect.resize(samples);
1326 int stream_count =
size();
1328 int samples_eff_max = 0;
1329 for (
int j = 0; j < stream_count; j++) {
1330 if (weights[j] > 0) {
1332 readSamples(streams[j], current_vect.data(), samples, retry_count);
1333 if (samples_eff > samples_eff_max) samples_eff_max = samples_eff;
1335 float factor = total_weights == 0.0f
1337 :
static_cast<float>(weights[j]) / total_weights;
1342 for (
int j = 0; j < samples; j++) {
1343 p_data[j] = result_vect[j];
1345 return samples_eff_max *
sizeof(T);
1350 int result = DEFAULT_BUFFER_SIZE;
1351 for (
int j = 0; j <
size(); j++) {
1352 result = min(result, streams[j]->available());
1357 void resultAdd(
float fact) {
1358 for (
int j = 0; j < current_vect.size(); j++) {
1359 current_vect[j] *= fact;
1360 result_vect[j] += current_vect[j];
1364 void resultClear() {
1365 memset(result_vect.data(), 0,
sizeof(
int) * result_vect.size());
1378template <
typename T>
1395 info.
channels = total_channel_count;
1404 virtual bool begin()
override {
1407 return AudioStream::begin();
1412 LOGD(
"readBytes: %d", (
int)len);
1413 T *p_data = (T *)data;
1415 int frames = result_len / (
sizeof(T) * total_channel_count);
1417 for (
int j = 0; j < frames; j++) {
1418 for (
int i = 0; i < records.size(); i++) {
1419 for (
int ch = 0; ch < records[i].channels; ch++) {
1420 p_data[result_idx++] =
1421 records[i].weight * readSample<T>(records[i].stream);
1425 return result_idx *
sizeof(T);
1431 records.push_back(rec);
1439 records[channel].weight = weight;
1441 LOGE(
"Invalid channel %d - max is %d", channel,
channelCount() - 1);
1446 void end()
override { records.clear(); }
1453 int result = records[0].stream->available();
1455 int tmp = records[j].stream->available();
1465 Stream *stream =
nullptr;
1476 int total_channel_count = 0;
1497 setUpdateCallback(cb_update);
1503 setUpdateCallback(cb_update);
1507 size_t (*cb_write)(
const uint8_t *data,
size_t len)) {
1508 setWriteCallback(cb_write);
1509 setReadCallback(cb_read);
1512 void setWriteCallback(
size_t (*cb_write)(
const uint8_t *data,
size_t len)) {
1513 this->cb_write = cb_write;
1516 void setReadCallback(
size_t (*cb_read)(uint8_t *data,
size_t len)) {
1517 this->cb_read = cb_read;
1520 void setUpdateCallback(
size_t (*cb_update)(uint8_t *data,
size_t len)) {
1521 this->cb_update = cb_update;
1526 void setAvailableCallback(
int (*cb)()) { this->cb_available = cb; }
1530 this->cb_audio_info = cb;
1536 if (cb_audio_info !=
nullptr) {
1537 cb_audio_info(info);
1545 virtual bool begin()
override {
1550 void end()
override { active =
false; }
1552 int available()
override {
1553 int result = AudioStream::available();
1555 if (available_bytes >= 0)
return available_bytes;
1557 if (cb_available ==
nullptr)
return result;
1559 int tmp_available = cb_available();
1560 if (tmp_available < 0)
return result;
1562 return tmp_available;
1565 size_t readBytes(uint8_t *data,
size_t len)
override {
1566 if (!active)
return 0;
1569 return cb_read(data, len);
1574 result = p_stream->readBytes(data, len);
1577 result = cb_update(data, result);
1582 size_t write(
const uint8_t *data,
size_t len)
override {
1583 if (!active)
return 0;
1586 return cb_write(data, len);
1590 size_t result = len;
1592 result = cb_update((uint8_t *)data, len);
1594 return p_out->write(data, result);
1623 size_t (*cb_write)(
const uint8_t *data,
size_t len) =
nullptr;
1624 size_t (*cb_read)(uint8_t *data,
size_t len) =
nullptr;
1625 size_t (*cb_update)(uint8_t *data,
size_t len) =
nullptr;
1626 void (*cb_audio_info)(
AudioInfo info) =
nullptr;
1627 int (*cb_available)() =
nullptr;
1628 Stream *p_stream =
nullptr;
1629 Print *p_out =
nullptr;
1630 int available_bytes = -1;
1640template <
typename T,
class TF>
1646 this->channels = channels;
1652 this->channels = channels;
1669 if (p_converter !=
nullptr && p_converter->getChannels() != channels) {
1670 LOGE(
"Inconsistent number of channels");
1676 bool begin()
override {
1677 if (channels == 0) {
1678 LOGE(
"channels must not be 0");
1681 if (p_converter ==
nullptr) {
1682 p_converter =
new ConverterNChannels<T, TF>(channels);
1684 return AudioStream::begin();
1687 void end()
override {
1688 ModifyingStream::end();
1689 if (p_converter !=
nullptr) {
1691 p_converter =
nullptr;
1695 virtual size_t write(
const uint8_t *data,
size_t len)
override {
1696 if (p_converter ==
nullptr)
return 0;
1697 size_t result = p_converter->convert((uint8_t *)data, len);
1698 return p_print->write(data, result);
1701 size_t readBytes(uint8_t *data,
size_t len)
override {
1702 if (p_converter ==
nullptr)
return 0;
1703 if (p_stream ==
nullptr)
return 0;
1704 size_t result = p_stream->readBytes(data, len);
1705 result = p_converter->convert(data, result);
1709 virtual int available()
override {
1710 if (p_stream ==
nullptr)
return 0;
1711 return p_stream->available();
1714 virtual int availableForWrite()
override {
1715 return p_print->availableForWrite();
1722 if (p_converter !=
nullptr) {
1723 p_converter->
setFilter(channel, filter);
1725 LOGE(
"p_converter is null");
1738 Stream *p_stream =
nullptr;
1739 Print *p_print =
nullptr;
1764 bool begin()
override {
1771 LOGI(
"VolumeMeter::setAudioInfo: channels %d", channels);
1774 volumes.resize(channels);
1775 volumes_tmp.resize(channels);
1776 sum.resize(channels);
1777 sum_tmp.resize(channels);
1781 size_t write(
const uint8_t *data,
size_t len)
override {
1782 updateVolumes(data, len);
1783 size_t result = len;
1784 if (p_out !=
nullptr) {
1785 result = p_out->write(data, len);
1790 size_t readBytes(uint8_t *data,
size_t len)
override {
1791 if (p_stream ==
nullptr)
return 0;
1792 size_t result = p_stream->readBytes(data, len);
1793 updateVolumes((
const uint8_t *)data, len);
1804 if (volumes.size() == 0) {
1805 LOGE(
"begin not called!");
1808 if (channel >= volumes.size()) {
1809 LOGE(
"invalid channel %d", channel);
1812 return volumes[channel];
1849 for (
int j = 0; j < info.
channels; j++) {
1851 count += sample_count_per_channel;
1853 return total / count;
1858 return sum[channel] / sample_count_per_channel;
1864 for (
int j = 0; j < info.
channels; j++) {
1872 setOutput((
Print &)out);
1874 void setStream(AudioStream &io) {
1876 setStream((Stream &)io);
1885 float f_volume_tmp = 0;
1888 Vector<float> volumes_tmp{0};
1889 Vector<float> sum{0};
1890 Vector<float> sum_tmp{0};
1891 Print *p_out =
nullptr;
1892 Stream *p_stream =
nullptr;
1893 size_t sample_count_per_channel = 0;
1895 void updateVolumes(
const uint8_t *data,
size_t len) {
1896 if (data ==
nullptr || len == 0)
return;
1900 updateVolumesT<int8_t>(data, len);
1903 updateVolumesT<int16_t>(data, len);
1906 updateVolumesT<int24_t>(data, len);
1909 updateVolumesT<int32_t>(data, len);
1917 template <
typename T>
1918 void updateVolumesT(
const uint8_t *buffer,
size_t size) {
1919 T *bufferT = (T *)buffer;
1920 int samplesCount = size /
sizeof(T);
1921 sample_count_per_channel = samplesCount / info.
channels;
1922 for (
int j = 0; j < samplesCount; j++) {
1923 float tmp = abs(
static_cast<float>(bufferT[j]));
1924 updateVolume(tmp, j);
1929 void updateVolume(
float tmp,
int j) {
1930 if (tmp > f_volume_tmp) {
1933 if (volumes_tmp.size() > 0 && info.
channels > 0) {
1935 if (tmp > volumes_tmp[ch]) {
1936 volumes_tmp[ch] = tmp;
1943 f_volume = f_volume_tmp;
1944 for (
int j = 0; j < info.
channels; j++) {
1945 volumes[j] = volumes_tmp[j];
1946 sum[j] = sum_tmp[j];
2064 size_t write(
const uint8_t *data,
size_t len)
override {
2136 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
2137 bool use_timer =
true;
2139 TimerFunction timer_function = DirectTimerCallback;
2140 bool adapt_sample_rate =
false;
2141 uint16_t (*callback)(uint8_t *data, uint16_t len) =
nullptr;
2145static void timerCallback(
void *obj);
2156 friend void timerCallback(
void *obj);
2163 if (timer !=
nullptr)
delete timer;
2164 if (buffer !=
nullptr)
delete buffer;
2165 if (frame !=
nullptr)
delete[] frame;
2179 bool do_restart = active;
2180 if (do_restart)
end();
2184 if (do_restart)
begin(cfg);
2193 LOGD(
"%s: %s", LOG_METHOD,
2194 config.rx_tx_mode == RX_MODE ?
"RX_MODE" :
"TX_MODE");
2196 this->frameCallback = config.callback;
2197 if (cfg.use_timer) {
2198 frameSize = cfg.bits_per_sample * cfg.channels / 8;
2199 frame =
new uint8_t[frameSize];
2202 timer->setTimerFunction(cfg.timer_function);
2203 if (cfg.timer_id >= 0) {
2204 timer->setTimer(cfg.timer_id);
2207 LOGI(
"sample_rate: %u -> time: %u milliseconds",
2208 (
unsigned int)cfg.sample_rate, (
unsigned int)time);
2209 timer->setCallbackParameter(
this);
2210 timer->begin(timerCallback, time, TimeUnit::US);
2213 notifyAudioChange(cfg);
2220 if (this->frameCallback !=
nullptr) {
2221 if (cfg.use_timer) {
2222 timer->begin(timerCallback, time, TimeUnit::US);
2232 if (cfg.use_timer) {
2243 bool active =
false;
2244 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
2248 uint8_t *frame =
nullptr;
2249 uint16_t frameSize = 0;
2251 unsigned long lastTimestamp = 0u;
2252 uint32_t currentRateValue = 0;
2253 uint32_t printCount = 0;
2256 virtual size_t writeExt(
const uint8_t *data,
size_t len)
override {
2257 if (!active)
return 0;
2260 if (!cfg.use_timer) {
2261 result = frameCallback((uint8_t *)data, len);
2263 result = buffer->
writeArray((uint8_t *)data, len);
2270 virtual size_t readExt(uint8_t *data,
size_t len)
override {
2271 if (!active)
return 0;
2275 if (!cfg.use_timer) {
2276 result = frameCallback(data, len);
2286 unsigned long ms =
millis();
2287 if (lastTimestamp > 0u) {
2288 uint32_t diff = ms - lastTimestamp;
2290 uint16_t rate = 1 * 1000 / diff;
2292 if (currentRateValue == 0) {
2293 currentRateValue = rate;
2295 currentRateValue = (currentRateValue + rate) / 2;
2304 LOGI(
"effective sample rate: %u", (
unsigned int)currentRateValue);
2305 if (cfg.adapt_sample_rate &&
2306 abs((
int)currentRateValue - (
int)cfg.
sample_rate) > 200) {
2308 notifyAudioChange(cfg);
2314void IRAM_ATTR timerCallback(
void *obj) {
2315 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2316 if (src !=
nullptr) {
2319 if (src->cfg.rx_tx_mode == RX_MODE) {
2321 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2322 uint16_t buffer_available = src->buffer->availableForWrite();
2323 if (buffer_available < available_bytes) {
2325 uint16_t to_clear = available_bytes - buffer_available;
2326 uint8_t tmp[to_clear];
2327 src->buffer->readArray(tmp, to_clear);
2329 if (src->buffer->writeArray(src->frame, available_bytes) !=
2335 if (src->buffer !=
nullptr && src->frame !=
nullptr &&
2336 src->frameSize > 0) {
2337 uint16_t available_bytes =
2338 src->buffer->readArray(src->frame, src->frameSize);
2339 if (available_bytes !=
2340 src->frameCallback(src->frame, available_bytes)) {
2341 LOGE(
"data underflow");
2345 src->measureSampleRate();
MemoryType
Memory types.
Definition AudioTypes.h:37
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:30