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);
102 setValue(buffer, buffer_size, memoryType);
103 is_active = isActive;
112 setValue(source.buffer, source.buffer_size, source.memory_type);
114 source.setValue(
nullptr, 0, source.memory_type);
119 if (memoryCanChange() && owns_memory && buffer !=
nullptr) free(buffer);
129 operator bool()
override {
return available() > 0; }
140 write_pos = memoryCanChange() ? 0 : buffer_size;
141 if (this->buffer ==
nullptr && owns_memory && memoryCanChange()) {
145 is_active = this->buffer !=
nullptr;
149 virtual size_t write(uint8_t
byte)
override {
150 if (!is_active)
return 0;
151 if (memory_type == FLASH_RAM)
return 0;
152 if (buffer ==
nullptr)
return 0;
154 if (write_pos < buffer_size) {
156 buffer[write_pos] = byte;
162 virtual size_t write(
const uint8_t *
data,
size_t len)
override {
163 if (!is_active)
return 0;
164 if (memory_type == FLASH_RAM)
return 0;
166 for (
size_t j = 0; j < len; j++) {
167 if (!write(
data[j])) {
175 virtual int available()
override {
176 if (!is_active)
return 0;
177 if (buffer ==
nullptr)
return 0;
178 int result = write_pos - read_pos;
179 if (result <= 0 && is_loop) {
181 read_pos = rewind_pos;
182 result = write_pos - read_pos;
184 if (rewind !=
nullptr) rewind();
186 return is_loop ? DEFAULT_BUFFER_SIZE : result;
189 virtual int availableForWrite()
override {
190 if (!is_active)
return 0;
191 if (memory_type == FLASH_RAM)
return 0;
192 return buffer_size - write_pos;
195 virtual int read()
override {
203 virtual size_t readBytes(uint8_t *
data,
size_t len)
override {
204 if (!is_active)
return 0;
206 while (count < len) {
215 virtual int peek()
override {
216 if (!is_active)
return -1;
218 if (available() > 0) {
219 result = buffer[read_pos];
224 virtual void flush()
override {}
226 virtual void end()
override {
232 virtual void clear(
bool reset =
false) {
233 if (memoryCanChange()) {
236 if (owns_memory && buffer ==
nullptr) {
241 memset(buffer, 0, buffer_size);
245 LOGW(
"data is read only");
254 if (buffer !=
nullptr && buffer_size > 12) {
255 if (memcmp(
"WAVE", buffer + 8, 4) == 0) {
262 virtual void setLoop(
bool loop,
int rewindPos) {
264 rewind_pos = rewindPos;
270 if (!memoryCanChange())
return false;
271 if (!owns_memory)
return false;
274 switch (memory_type) {
275#if defined(USE_PSRAM) && defined(ARDUINO)
277 buffer = (buffer ==
nullptr) ? (uint8_t *)ps_calloc(size, 1)
278 : (uint8_t *)ps_realloc(buffer, size);
282 buffer = (buffer ==
nullptr) ? (uint8_t *)calloc(size, 1)
283 : (uint8_t *)realloc(buffer, size);
286 return buffer !=
nullptr;
290 virtual uint8_t *
data() {
return buffer; }
299 void setValue(
const uint8_t *buffer,
int buffer_size,
301 this->buffer_size = buffer_size;
303 this->write_pos = buffer_size;
304 this->buffer = (uint8_t *)buffer;
305 this->memory_type = memoryType;
313 uint8_t *buffer =
nullptr;
315 bool is_loop =
false;
316 void (*rewind)() =
nullptr;
317 bool is_active =
false;
318 bool owns_memory =
true;
320 bool memoryCanChange() {
return memory_type != FLASH_RAM; }
322 void copy(MemoryStream &source) {
323 if (
this == &source)
return;
324 if (source.memory_type == FLASH_RAM) {
325 setValue(source.buffer, source.buffer_size, source.memory_type);
327 setValue(
nullptr, source.buffer_size, source.memory_type);
329 memcpy(buffer, source.buffer, buffer_size);
345 virtual int available()
override {
347 return buffer.available();
350 virtual int availableForWrite()
override {
351 return buffer.availableForWrite();
354 virtual void flush()
override {}
355 virtual int peek()
override {
357 if (!buffer.peek(data))
return -1;
360 virtual int read()
override {
362 if (!buffer.read(data))
return -1;
366 virtual size_t readBytes(uint8_t *data,
size_t len)
override {
367 return buffer.readArray(data, len);
370 virtual size_t write(
const uint8_t *data,
size_t len)
override {
372 return buffer.writeArray(data, len);
375 virtual size_t write(uint8_t c)
override {
return buffer.write(c); }
377 void resize(
int size) { buffer.resize(size); }
379 size_t size() {
return buffer.size(); }
396template <
class T =
int16_t>
407 this->generator_ptr = &generator;
422 if (generator_ptr ==
nullptr) {
423 LOGE(
"%s", source_not_defined_error);
426 generator_ptr->begin();
427 notifyAudioChange(generator_ptr->
audioInfo());
435 if (generator_ptr ==
nullptr) {
436 LOGE(
"%s", source_not_defined_error);
439 generator_ptr->begin(cfg);
440 notifyAudioChange(generator_ptr->
audioInfo());
448 generator_ptr->
end();
455 virtual int available()
override {
return active ? buffer_size : 0; }
459 if (!active)
return 0;
460 LOGD(
"GeneratedSoundStream::readBytes: %u", (
unsigned int)len);
461 return generator_ptr->
readBytes(data, len);
464 bool isActive() {
return active && generator_ptr->
isActive(); }
466 operator bool()
override {
return isActive(); }
468 void flush()
override {}
471 void resize(
int maxReadSize) { buffer_size = maxReadSize; }
477 DEFAULT_BUFFER_SIZE * 100;
478 const char *source_not_defined_error =
"Source not defined";
493 if (buffer_size > 0)
resize(buffer_size);
499 if (buffer_size > 0)
resize(buffer_size);
505 if (buffer_size > 0)
resize(buffer_size);
511 if (buffer_size > 0)
resize(buffer_size);
517 if (buffer_size > 0)
resize(buffer_size);
529 if (buffer.isFull()) {
532 return buffer.write(c);
536 size_t write(
const uint8_t *data,
size_t len)
override {
537 LOGD(
"%s: %zu", LOG_METHOD, len);
539 for (
int j = 0; j < len; j++) {
540 result +=
write(data[j]);
548 if (buffer.available() > 0) {
549 writeExt(buffer.address(), buffer.available());
556 if (buffer.isEmpty()) {
560 if (!buffer.read(result))
return -1;
566 if (buffer.isEmpty()) {
570 if (!buffer.peek(result))
return -1;
576 if (buffer.isEmpty() && len >= minReadBufferSize) {
577 return readExt(data, len);
580 return buffer.readArray(data, len);
586 if (buffer.isEmpty()) {
589 return buffer.peekArray(data, len);
594 if (p_in ==
nullptr)
return 0;
595 return buffer.available() + p_in->available();
602 void resize(
int size) { buffer.resize(size); }
610 Print *p_out =
nullptr;
611 Stream *p_in =
nullptr;
612 size_t minReadBufferSize = 1024;
618 size_t already_available = buffer.available();
619 size_t free_space = buffer.availableForWrite();
620 if (free_space == 0) {
625 size_t added = readExt(buffer.address() + already_available, free_space);
626 buffer.setAvailable(already_available + added);
631 if (buffer.available() >= len)
return;
635 virtual size_t writeExt(
const uint8_t *data,
size_t len) {
636 return p_out ==
nullptr ? 0 : p_out->write(data, len);
638 virtual size_t readExt(uint8_t *data,
size_t len) {
639 return p_in ==
nullptr ? 0 : p_in->readBytes(data, len);
651template <
typename T =
int16_t>
659 setConverter(converter);
664 setConverter(converter);
679 void setConverter(
BaseConverter &cnv) { p_converter = &cnv; }
681 virtual int availableForWrite() {
return p_out->availableForWrite(); }
683 virtual size_t write(
const uint8_t *data,
size_t len) {
684 size_t result = p_converter->convert((uint8_t *)data, len);
686 size_t result_written = p_out->write(data, result);
687 return len * result_written / result;
692 size_t readBytes(uint8_t *data,
size_t len)
override {
693 if (p_stream ==
nullptr)
return 0;
694 size_t result = p_stream->readBytes(data, len);
695 return p_converter->convert(data, result);
700 if (p_stream ==
nullptr)
return 0;
701 return p_stream->available();
705 Stream *p_stream =
nullptr;
706 Print *p_out =
nullptr;
720 this->max_count = count;
729 this->max_count = count;
737 this->max_count = count;
757 total_bytes_since_begin += len;
758 return measure(p_stream->readBytes(data, len));
761 int available()
override {
return p_stream->available(); }
764 virtual size_t write(
const uint8_t *data,
size_t len)
override {
765 total_bytes_since_begin += len;
766 return measure(p_print->write(data, len));
771 return p_print->availableForWrite();
779 if (frame_size == 0)
return 0;
780 return bytes_per_second / frame_size;
787 AudioStream::info = info;
791 bool begin()
override {
792 total_bytes_since_begin = 0;
794 return AudioStream::begin();
797 bool begin(AudioInfo info) {
808 void setName(
const char *name) { this->name = name; }
832 bool is_regular_update =
true;
833 if (pos < total_bytes_since_begin) {
835 is_regular_update =
false;
837 total_bytes_since_begin = pos;
838 return is_regular_update;
844 Stream *p_stream =
nullptr;
845 Print *p_print =
nullptr;
848 int bytes_per_second = 0;
851 Print *p_logout =
nullptr;
852 bool report_bytes =
false;
853 const char *name =
"";
854 uint32_t ms_at_begin = 0;
855 uint32_t total_bytes_since_begin = 0;
857 size_t measure(
size_t len) {
862 uint32_t end_time =
millis();
863 int time_diff = end_time - start_time;
865 bytes_per_second = total_bytes / time_diff * 1000;
869 start_time = end_time;
877 if (report_bytes || frame_size == 0) {
878 snprintf(msg, 70,
"%s ==> Bytes per second: %d", name, bytes_per_second);
880 snprintf(msg, 70,
"%s ==> Samples per second: %d", name,
881 bytes_per_second / frame_size);
883 if (p_logout !=
nullptr) {
884 p_logout->println(msg);
899 size_t total_size = 0;
918 p_info_from = &stream;
935 void setPrint(Print &print) { p_print = &print; }
937 bool begin()
override {
938 if (p_info_from !=
nullptr) {
941 return AudioStream::begin();
952 progress_info = info;
960 progress_info.total_size = len;
964 size_t size() {
return progress_info.total_size; }
980 if (progress_info.total_size == 0)
return 0;
981 return 100.0 * total_processed / progress_info.total_size;
986 if (p_stream ==
nullptr)
return 0;
987 return measure(p_stream->readBytes(data, len));
990 int available()
override {
991 if (p_stream ==
nullptr)
return 0;
992 return p_stream->available();
996 virtual size_t write(
const uint8_t *data,
size_t len)
override {
997 if (p_print ==
nullptr)
return 0;
998 return measure(p_print->write(data, len));
1003 if (p_print ==
nullptr)
return 0;
1004 return p_print->availableForWrite();
1009 Stream *p_stream =
nullptr;
1010 Print *p_print =
nullptr;
1012 size_t total_processed = 0;
1014 size_t measure(
size_t len) {
1015 total_processed += len;
1021 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1022 if (byte_rate == 0) {
1023 LOGE(
"Audio Info not defined");
1041 int correction_us = 0;
1070 bool begin(ThrottleConfig cfg) {
1071 LOGI(
"begin sample_rate: %d, channels: %d, bits: %d", (
int)info.
sample_rate,
1078 bool begin(AudioInfo info) {
1079 LOGI(
"begin sample_rate: %d, channels: %d, bits: %d", (
int)info.sample_rate,
1080 (
int)info.channels, (
int)info.bits_per_sample);
1082 this->cfg.copyFrom(info);
1086 bool begin()
override {
1087 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1094 start_time = micros();
1098 int availableForWrite()
override {
1100 return p_out->availableForWrite();
1102 return DEFAULT_BUFFER_SIZE;
1105 size_t write(
const uint8_t *data,
size_t len)
override {
1106 size_t result = p_out->write(data, len);
1111 int available()
override {
1112 if (p_in ==
nullptr)
return 0;
1113 return p_in->available();
1116 size_t readBytes(uint8_t *data,
size_t len)
override {
1117 if (p_in ==
nullptr) {
1121 size_t result = p_in->readBytes(data, len);
1127 void delayBytes(
size_t bytes) { delayFrames(bytes / frame_size); }
1130 void delayFrames(
size_t frames) {
1131 sum_frames += frames;
1132 uint64_t durationUsEff = micros() - start_time;
1133 uint64_t durationUsToBe = getDelayUs(sum_frames);
1134 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1135 LOGD(
"wait us: %ld",
static_cast<long>(waitUs));
1137 int64_t waitMs = waitUs / 1000;
1138 if (waitMs > 0) delay(waitMs);
1139 delayMicroseconds(waitUs - (waitMs * 1000));
1141 LOGD(
"negative delay!")
1145 inline int64_t getDelayUs(uint64_t frames) {
1146 return (frames * 1000000) / cfg.sample_rate;
1149 inline int64_t getDelayMs(uint64_t frames) {
1150 return getDelayUs(frames) / 1000;
1153 inline int64_t getDelaySec(uint64_t frames) {
1154 return getDelayUs(frames) / 1000000l;
1158 uint32_t start_time = 0;
1159 uint32_t sum_frames = 0;
1162 Print *p_out =
nullptr;
1163 Stream *p_in =
nullptr;
1175template <
typename T>
1182 streams.push_back(&in);
1183 weights.push_back(weight);
1184 total_weights += weight;
1185 return streams.indexOf(&in);
1190 if (index <
size()) {
1191 streams[index] = ∈
1194 LOGE(
"Invalid index %d - max is %d", index,
size() - 1);
1202 LOGI(
"frame_size: %d", frame_size);
1203 return frame_size > 0;
1210 if (index < streams.size()) {
1211 weights[index] = weight;
1214 LOGE(
"Invalid index %d - max is %d", index,
size() - 1);
1222 result_vect.clear();
1223 current_vect.clear();
1224 total_weights = 0.0;
1228 int size() {
return streams.size(); }
1232 if (total_weights == 0 || frame_size == 0 || len == 0) {
1233 LOGW(
"readBytes: %d", (
int)len);
1237 if (limit_available_data) {
1245 result_len = len * frame_size / frame_size;
1263 if (idx < 0 || idx >=
size()) {
1291 if (idx < 0 || idx >=
size())
return nullptr;
1292 return streams[idx];
1297 for (
int i = 0; i < streams.size(); i++) {
1298 if (streams[i]->available() == 0) {
1307 Vector<int> weights{0};
1308 int total_weights = 0;
1310 bool limit_available_data =
false;
1311 int retry_count = 5;
1312 Vector<int> result_vect;
1313 Vector<T> current_vect;
1318 for (
int j = 0; j < weights.size(); j++) {
1319 total += weights[j];
1321 total_weights = total;
1326 int samples = byteCount /
sizeof(T);
1327 result_vect.resize(samples);
1328 current_vect.resize(samples);
1329 int stream_count =
size();
1331 int samples_eff_max = 0;
1332 for (
int j = 0; j < stream_count; j++) {
1333 if (weights[j] > 0) {
1335 readSamples(streams[j], current_vect.data(), samples, retry_count);
1336 if (samples_eff > samples_eff_max) samples_eff_max = samples_eff;
1338 float factor = total_weights == 0.0f
1340 :
static_cast<float>(weights[j]) / total_weights;
1345 for (
int j = 0; j < samples; j++) {
1346 p_data[j] = result_vect[j];
1348 return samples_eff_max *
sizeof(T);
1353 int result = DEFAULT_BUFFER_SIZE;
1354 for (
int j = 0; j <
size(); j++) {
1355 result = min(result, streams[j]->available());
1360 void resultAdd(
float fact) {
1361 for (
int j = 0; j < current_vect.size(); j++) {
1362 current_vect[j] *= fact;
1363 result_vect[j] += current_vect[j];
1367 void resultClear() {
1368 memset(result_vect.data(), 0,
sizeof(
int) * result_vect.size());
1381template <
typename T>
1398 info.
channels = total_channel_count;
1407 virtual bool begin()
override {
1410 return AudioStream::begin();
1415 LOGD(
"readBytes: %d", (
int)len);
1416 T *p_data = (T *)data;
1418 int frames = result_len / (
sizeof(T) * total_channel_count);
1420 for (
int j = 0; j < frames; j++) {
1421 for (
int i = 0; i < records.size(); i++) {
1422 for (
int ch = 0; ch < records[i].channels; ch++) {
1423 p_data[result_idx++] =
1424 records[i].weight * readSample<T>(records[i].stream);
1428 return result_idx *
sizeof(T);
1434 records.push_back(rec);
1442 records[channel].weight = weight;
1444 LOGE(
"Invalid channel %d - max is %d", channel,
channelCount() - 1);
1449 void end()
override { records.clear(); }
1456 int result = records[0].stream->available();
1458 int tmp = records[j].stream->available();
1468 Stream *stream =
nullptr;
1479 int total_channel_count = 0;
1500 setUpdateCallback(cb_update);
1506 setUpdateCallback(cb_update);
1510 size_t (*cb_write)(
const uint8_t *data,
size_t len)) {
1511 setWriteCallback(cb_write);
1512 setReadCallback(cb_read);
1515 void setWriteCallback(
size_t (*cb_write)(
const uint8_t *data,
size_t len)) {
1516 this->cb_write = cb_write;
1519 void setReadCallback(
size_t (*cb_read)(uint8_t *data,
size_t len)) {
1520 this->cb_read = cb_read;
1523 void setUpdateCallback(
size_t (*cb_update)(uint8_t *data,
size_t len)) {
1524 this->cb_update = cb_update;
1529 void setAvailableCallback(
int (*cb)()) { this->cb_available = cb; }
1533 this->cb_audio_info = cb;
1539 if (cb_audio_info !=
nullptr) {
1540 cb_audio_info(info);
1548 virtual bool begin()
override {
1553 void end()
override { active =
false; }
1555 int available()
override {
1556 int result = AudioStream::available();
1558 if (available_bytes >= 0)
return available_bytes;
1560 if (cb_available ==
nullptr)
return result;
1562 int tmp_available = cb_available();
1563 if (tmp_available < 0)
return result;
1565 return tmp_available;
1568 size_t readBytes(uint8_t *data,
size_t len)
override {
1569 if (!active)
return 0;
1572 return cb_read(data, len);
1577 result = p_stream->readBytes(data, len);
1580 result = cb_update(data, result);
1585 size_t write(
const uint8_t *data,
size_t len)
override {
1586 if (!active)
return 0;
1589 return cb_write(data, len);
1593 size_t result = len;
1595 result = cb_update((uint8_t *)data, len);
1597 return p_out->write(data, result);
1626 size_t (*cb_write)(
const uint8_t *data,
size_t len) =
nullptr;
1627 size_t (*cb_read)(uint8_t *data,
size_t len) =
nullptr;
1628 size_t (*cb_update)(uint8_t *data,
size_t len) =
nullptr;
1629 void (*cb_audio_info)(
AudioInfo info) =
nullptr;
1630 int (*cb_available)() =
nullptr;
1631 Stream *p_stream =
nullptr;
1632 Print *p_out =
nullptr;
1633 int available_bytes = -1;
1643template <
typename T =
int16_t,
class TF =
float>
1649 this->channels = channels;
1655 this->channels = channels;
1672 if (p_converter !=
nullptr && p_converter->getChannels() != channels) {
1673 LOGE(
"Inconsistent number of channels");
1679 bool begin()
override {
1680 if (channels == 0) {
1681 LOGE(
"channels must not be 0");
1684 if (p_converter ==
nullptr) {
1685 p_converter =
new ConverterNChannels<T, TF>(channels);
1687 return AudioStream::begin();
1690 void end()
override {
1691 ModifyingStream::end();
1692 if (p_converter !=
nullptr) {
1694 p_converter =
nullptr;
1698 virtual size_t write(
const uint8_t *data,
size_t len)
override {
1699 if (p_converter ==
nullptr)
return 0;
1700 size_t result = p_converter->convert((uint8_t *)data, len);
1701 return p_print->write(data, result);
1704 size_t readBytes(uint8_t *data,
size_t len)
override {
1705 if (p_converter ==
nullptr)
return 0;
1706 if (p_stream ==
nullptr)
return 0;
1707 size_t result = p_stream->readBytes(data, len);
1708 result = p_converter->convert(data, result);
1712 virtual int available()
override {
1713 if (p_stream ==
nullptr)
return 0;
1714 return p_stream->available();
1717 virtual int availableForWrite()
override {
1718 return p_print->availableForWrite();
1725 if (p_converter !=
nullptr) {
1726 p_converter->setFilter(channel, filter);
1728 LOGE(
"p_converter is null");
1741 Stream *p_stream =
nullptr;
1742 Print *p_print =
nullptr;
1771 bool begin()
override {
1778 LOGI(
"VolumeMeter::setAudioInfo: channels %d", channels);
1781 volumes.resize(channels);
1782 volumes_tmp.resize(channels);
1783 sum.resize(channels);
1784 sum_tmp.resize(channels);
1788 size_t write(
const uint8_t *data,
size_t len)
override {
1789 updateVolumes(data, len);
1790 size_t result = len;
1791 if (p_out !=
nullptr) {
1792 result = p_out->write(data, len);
1797 size_t readBytes(uint8_t *data,
size_t len)
override {
1798 if (p_stream ==
nullptr)
return 0;
1799 size_t result = p_stream->readBytes(data, len);
1800 updateVolumes((
const uint8_t *)data, len);
1811 if (volumes.size() == 0) {
1812 LOGE(
"begin not called!");
1815 if (channel >= volumes.size()) {
1816 LOGE(
"invalid channel %d", channel);
1819 return volumes[channel];
1856 for (
int j = 0; j < info.
channels; j++) {
1858 count += sample_count_per_channel;
1860 return total / count;
1865 return sum[channel] / sample_count_per_channel;
1871 for (
int j = 0; j < info.
channels; j++) {
1882 activity_callback = callback;
1883 activity_threshold = threshold;
1884 activity_duration_ms = duration_ms;
1885 activity_monitoring_enabled = (callback !=
nullptr);
1896 setOutput((
Print &)out);
1898 void setStream(AudioStream &io) {
1900 setStream((Stream &)io);
1909 float f_volume_tmp = 0;
1912 Vector<float> volumes_tmp{0};
1913 Vector<float> sum{0};
1914 Vector<float> sum_tmp{0};
1915 Print *p_out =
nullptr;
1916 Stream *p_stream =
nullptr;
1917 size_t sample_count_per_channel = 0;
1921 float activity_threshold = 0.0f;
1922 unsigned long activity_duration_ms = 0;
1923 bool activity_monitoring_enabled =
false;
1924 bool is_active =
false;
1925 unsigned long inactive_start_time = 0;
1927 void updateVolumes(
const uint8_t *data,
size_t len) {
1928 if (data ==
nullptr || len == 0)
return;
1932 updateVolumesT<int8_t>(data, len);
1935 updateVolumesT<int16_t>(data, len);
1938 updateVolumesT<int24_t>(data, len);
1941 updateVolumesT<int32_t>(data, len);
1949 template <
typename T>
1950 void updateVolumesT(
const uint8_t *buffer,
size_t size) {
1951 T *bufferT = (T *)buffer;
1952 int samplesCount = size /
sizeof(T);
1953 sample_count_per_channel = samplesCount / info.
channels;
1954 for (
int j = 0; j < samplesCount; j++) {
1955 float tmp = abs(
static_cast<float>(bufferT[j]));
1956 updateVolume(tmp, j);
1961 void updateVolume(
float tmp,
int j) {
1962 if (tmp > f_volume_tmp) {
1965 if (volumes_tmp.size() > 0 && info.
channels > 0) {
1967 if (tmp > volumes_tmp[ch]) {
1968 volumes_tmp[ch] = tmp;
1975 f_volume = f_volume_tmp;
1976 for (
int j = 0; j < info.
channels; j++) {
1977 volumes[j] = volumes_tmp[j];
1978 sum[j] = sum_tmp[j];
1980 updateActivityState();
1983 void updateActivityState() {
1984 if (!activity_monitoring_enabled || activity_callback ==
nullptr)
return;
1987 bool above_threshold = current_volume_ratio > activity_threshold;
1988 unsigned long current_time =
millis();
1990 if (above_threshold) {
1994 activity_callback(
true);
1996 inactive_start_time = 0;
2001 if (inactive_start_time == 0) {
2003 inactive_start_time = current_time;
2004 }
else if (current_time - inactive_start_time >= activity_duration_ms) {
2007 activity_callback(
false);
2008 inactive_start_time = 0;
2128 size_t write(
const uint8_t *data,
size_t len)
override {
2200 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
2201 bool use_timer =
true;
2203 TimerFunction timer_function = DirectTimerCallback;
2204 bool adapt_sample_rate =
false;
2205 uint16_t (*callback)(uint8_t *data, uint16_t len) =
nullptr;
2209static void timerCallback(
void *obj);
2220 friend void timerCallback(
void *obj);
2227 if (timer !=
nullptr)
delete timer;
2228 if (buffer !=
nullptr)
delete buffer;
2229 if (frame !=
nullptr)
delete[] frame;
2243 bool do_restart = active;
2244 if (do_restart)
end();
2248 if (do_restart)
begin(cfg);
2257 LOGD(
"%s: %s", LOG_METHOD,
2258 config.rx_tx_mode == RX_MODE ?
"RX_MODE" :
"TX_MODE");
2260 this->frameCallback = config.callback;
2261 if (cfg.use_timer) {
2262 frameSize = cfg.bits_per_sample * cfg.channels / 8;
2263 frame =
new uint8_t[frameSize];
2266 timer->setTimerFunction(cfg.timer_function);
2267 if (cfg.timer_id >= 0) {
2268 timer->setTimer(cfg.timer_id);
2271 LOGI(
"sample_rate: %u -> time: %u milliseconds",
2272 (
unsigned int)cfg.sample_rate, (
unsigned int)time);
2273 timer->setCallbackParameter(
this);
2274 timer->begin(timerCallback, time, TimeUnit::US);
2277 notifyAudioChange(cfg);
2284 if (this->frameCallback !=
nullptr) {
2285 if (cfg.use_timer) {
2286 timer->begin(timerCallback, time, TimeUnit::US);
2296 if (cfg.use_timer) {
2307 bool active =
false;
2308 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
2312 uint8_t *frame =
nullptr;
2313 uint16_t frameSize = 0;
2315 unsigned long lastTimestamp = 0u;
2316 uint32_t currentRateValue = 0;
2317 uint32_t printCount = 0;
2320 virtual size_t writeExt(
const uint8_t *data,
size_t len)
override {
2321 if (!active)
return 0;
2324 if (!cfg.use_timer) {
2325 result = frameCallback((uint8_t *)data, len);
2327 result = buffer->
writeArray((uint8_t *)data, len);
2334 virtual size_t readExt(uint8_t *data,
size_t len)
override {
2335 if (!active)
return 0;
2339 if (!cfg.use_timer) {
2340 result = frameCallback(data, len);
2350 unsigned long ms =
millis();
2351 if (lastTimestamp > 0u) {
2352 uint32_t diff = ms - lastTimestamp;
2354 uint16_t rate = 1 * 1000 / diff;
2356 if (currentRateValue == 0) {
2357 currentRateValue = rate;
2359 currentRateValue = (currentRateValue + rate) / 2;
2368 LOGI(
"effective sample rate: %u", (
unsigned int)currentRateValue);
2369 if (cfg.adapt_sample_rate &&
2370 abs((
int)currentRateValue - (
int)cfg.
sample_rate) > 200) {
2372 notifyAudioChange(cfg);
2378void IRAM_ATTR timerCallback(
void *obj) {
2379 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2380 if (src !=
nullptr) {
2383 if (src->cfg.rx_tx_mode == RX_MODE) {
2385 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2386 uint16_t buffer_available = src->buffer->availableForWrite();
2387 if (buffer_available < available_bytes) {
2389 uint16_t to_clear = available_bytes - buffer_available;
2390 uint8_t tmp[to_clear];
2391 src->buffer->readArray(tmp, to_clear);
2393 if (src->buffer->writeArray(src->frame, available_bytes) !=
2399 if (src->buffer !=
nullptr && src->frame !=
nullptr &&
2400 src->frameSize > 0) {
2401 uint16_t available_bytes =
2402 src->buffer->readArray(src->frame, src->frameSize);
2403 if (available_bytes !=
2404 src->frameCallback(src->frame, available_bytes)) {
2405 LOGE(
"data underflow");
2409 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