2 #include "AudioConfig.h"
3 #include "AudioTools/CoreAudio/AudioTimer/AudioTimer.h"
4 #include "AudioTools/CoreAudio/AudioTypes.h"
5 #include "AudioTools/CoreAudio/Buffers.h"
6 #include "AudioTools/CoreAudio/AudioLogger.h"
7 #include "AudioTools/CoreAudio/BaseConverter.h"
8 #include "AudioTools/CoreAudio/AudioEffects/SoundGenerator.h"
9 #include "AudioTools/CoreAudio/BaseStream.h"
10 #include "AudioTools/CoreAudio/AudioOutput.h"
29 p_stream->setTimeout(clientTimeout);
32 virtual bool begin(){
return true;}
35 virtual size_t readBytes(uint8_t *data,
size_t len) {
38 return p_stream->readBytes(data, len);
41 int read() {
return p_stream->read(); }
43 int peek() {
return p_stream->peek(); }
45 int available() {
return p_stream->available(); }
47 virtual size_t write(uint8_t c) {
return p_stream->write(c); }
49 virtual size_t write(
const uint8_t *data,
size_t len) {
50 return p_stream->write(data, len);
53 virtual int availableForWrite() {
return p_stream->availableForWrite(); }
55 virtual void flush() { p_stream->flush(); }
59 int32_t clientTimeout = URL_CLIENT_TIMEOUT;
90 LOGD(
"MemoryStream: %d", buffer_size);
91 this->buffer_size = buffer_size;
92 this->memory_type = memoryType;
99 LOGD(
"MemoryStream: %d", buffer_size);
100 setValue(buffer, buffer_size, memoryType);
101 is_active = isActive;
112 setValue(source.buffer, source.buffer_size, source.memory_type);
114 source.setValue(
nullptr, 0, source.memory_type);
119 if (memoryCanChange() && buffer!=
nullptr) free(buffer);
129 operator bool()
override {
return available() > 0; }
140 write_pos = memoryCanChange() ? 0 : buffer_size;
141 if (this->buffer==
nullptr && memoryCanChange()){
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 (buffer==
nullptr){
241 memset(buffer, 0, buffer_size);
245 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;
268 if (!memoryCanChange())
return false;
272 #if defined(ESP32) && defined(ARDUINO)
274 buffer = (buffer==
nullptr) ? (uint8_t*)ps_calloc(size,1) : (uint8_t*)ps_realloc(buffer, size);
278 buffer = (buffer==
nullptr) ? (uint8_t*)calloc(size,1) : (uint8_t*)realloc(buffer, size);
281 return buffer !=
nullptr;
291 this->write_pos = len;
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;
319 bool memoryCanChange() {
320 return memory_type!=FLASH_RAM;
323 void copy(MemoryStream& source) {
324 if (
this == &source)
return;
325 if (source.memory_type == FLASH_RAM){
326 setValue(source.buffer, source.buffer_size, source.memory_type);
328 setValue(
nullptr, source.buffer_size, source.memory_type);
330 memcpy(buffer, source.buffer, buffer_size);
346 virtual int available()
override {
348 return buffer.available();
351 virtual int availableForWrite()
override {
352 return buffer.availableForWrite();
355 virtual void flush()
override {}
356 virtual int peek()
override {
return buffer.peek(); }
357 virtual int read()
override {
return buffer.read(); }
359 virtual size_t readBytes(uint8_t *data,
size_t len)
override {
360 return buffer.readArray(data, len);
363 virtual size_t write(
const uint8_t *data,
size_t len)
override {
365 return buffer.writeArray(data, len);
368 virtual size_t write(uint8_t c)
override {
return buffer.write(c); }
370 void resize(
int size) { buffer.resize(size); }
372 size_t size() {
return buffer.size(); }
400 this->generator_ptr = &generator;
403 AudioInfo defaultConfig() {
return this->generator_ptr->defaultConfig(); }
415 if (generator_ptr==
nullptr){
416 LOGE(
"%s",source_not_defined_error);
419 generator_ptr->begin();
420 notifyAudioChange(generator_ptr->audioInfo());
428 if (generator_ptr==
nullptr){
429 LOGE(
"%s",source_not_defined_error);
432 generator_ptr->begin(cfg);
433 notifyAudioChange(generator_ptr->audioInfo());
441 generator_ptr->end();
446 return generator_ptr->audioInfo();
450 virtual int available()
override {
return active ? DEFAULT_BUFFER_SIZE*2 : 0; }
454 if (!active)
return 0;
455 LOGD(
"GeneratedSoundStream::readBytes: %u", (
unsigned int)len);
456 return generator_ptr->readBytes(data, len);
459 bool isActive() {
return active && generator_ptr->isActive();}
461 operator bool() {
return isActive(); }
463 void flush()
override {}
467 SoundGenerator<T> *generator_ptr;
468 const char* source_not_defined_error =
"Source not defined";
484 buffer.resize(buffer_size);
490 buffer.resize(buffer_size);
496 buffer.resize(buffer_size);
502 void setStream(
Print &out){
512 if (buffer.isFull()) {
515 return buffer.write(c);
519 size_t write(
const uint8_t *data,
size_t len)
override {
520 LOGD(
"%s: %zu", LOG_METHOD, len);
522 for (
int j=0;j<len;j++){
523 result +=
write(data[j]);
531 if (buffer.available() > 0) {
532 writeExt(buffer.address(), buffer.available());
539 if (buffer.isEmpty()) {
542 return buffer.read();
547 if (buffer.isEmpty()) {
550 return buffer.peek();
555 if (buffer.isEmpty()) {
556 return readExt(data, len);
559 return buffer.readArray(data, len);
565 if (buffer.isEmpty()) {
568 return buffer.available();
576 Print* p_out =
nullptr;
581 size_t result = readExt(buffer.
address(), buffer.size());
585 virtual size_t writeExt(
const uint8_t *data,
size_t len) {
586 return p_out ==
nullptr ? 0 : p_out->write(data, len);
588 virtual size_t readExt(uint8_t *data,
size_t len) {
589 return p_in ==
nullptr ? 0 : p_in->readBytes(data, len);
609 setConverter(converter);
613 setConverter(converter);
618 setConverter(converter);
637 virtual int availableForWrite() {
return p_out->availableForWrite(); }
639 virtual size_t write(
const uint8_t *data,
size_t len) {
640 size_t result = p_converter->convert((uint8_t *)data, len);
642 size_t result_written = p_out->write(data, result);
643 return len * result_written / result;
648 size_t readBytes(uint8_t *data,
size_t len)
override {
649 if (p_stream==
nullptr)
return 0;
650 size_t result = p_stream->readBytes(data, len);
651 return p_converter->convert(data, result);
656 if (p_stream==
nullptr)
return 0;
657 return p_stream->available();
661 Stream *p_stream =
nullptr;
662 Print *p_out =
nullptr;
677 this->max_count = count;
686 this->max_count = count;
694 this->max_count = count;
714 return measure(p_stream->readBytes(data, len));
717 int available()
override {
718 return p_stream->available();
722 virtual size_t write(
const uint8_t *data,
size_t len)
override {
723 return measure(p_print->write(data, len));
728 return p_print->availableForWrite();
733 return bytes_per_second;
742 AudioStream::info = info;
747 return AudioStream::begin();
750 bool begin(AudioInfo info){
769 Print *p_print=
nullptr;
772 int bytes_per_second = 0;
775 Print *p_logout=
nullptr;
776 bool report_bytes =
false;
778 size_t measure(
size_t len) {
783 uint32_t end_time =
millis();
784 int time_diff = end_time - start_time;
786 bytes_per_second = total_bytes / time_diff * 1000;
790 start_time = end_time;
798 if (report_bytes || frame_size==0){
799 snprintf(msg, 70,
"==> Bytes per second: %d", bytes_per_second);
801 snprintf(msg, 70,
"==> Samples per second: %d", bytes_per_second/frame_size);
803 if (p_logout!=
nullptr){
804 p_logout->println(msg);
819 size_t total_size = 0;
842 p_info_from = &stream;
846 return progress_info;
863 void setPrint(Print &print){
867 bool begin()
override {
868 if (p_info_from!=
nullptr){
871 return AudioStream::begin();
881 progress_info = info;
889 progress_info.total_size = len;
894 return progress_info.total_size;
899 return total_processed;
904 return total_processed / byteRate();
909 return progress_info.total_size;
919 if (progress_info.total_size==0)
return 0;
920 return 100.0 * total_processed / progress_info.total_size;
925 if (p_stream==
nullptr)
return 0;
926 return measure(p_stream->readBytes(data, len));
929 int available()
override {
930 if (p_stream==
nullptr)
return 0;
931 return p_stream->available();
935 virtual size_t write(
const uint8_t *data,
size_t len)
override {
936 if (p_print==
nullptr)
return 0;
937 return measure(p_print->write(data, len));
942 if (p_print==
nullptr)
return 0;
943 return p_print->availableForWrite();
949 Print *p_print=
nullptr;
951 size_t total_processed = 0;
953 size_t measure(
size_t len) {
954 total_processed += len;
960 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
962 LOGE(
"Audio Info not defined");
981 int correction_us = 0;
1012 bool begin(ThrottleConfig cfg) {
1019 bool begin(AudioInfo info) {
1020 LOGI(
"begin sample_rate: %d, channels: %d, bits: %d", (
int)info.sample_rate, (
int) info.channels, (
int)info.bits_per_sample);
1022 this->cfg.copyFrom(info);
1027 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1034 start_time = micros();
1038 int availableForWrite() {
1040 return p_out->availableForWrite();
1042 return DEFAULT_BUFFER_SIZE;
1045 size_t write(
const uint8_t* data,
size_t len){
1046 size_t result = p_out->write(data, len);
1052 if (p_in==
nullptr)
return 0;
1053 return p_in->available();
1056 size_t readBytes(uint8_t* data,
size_t len)
override{
1057 if (p_in==
nullptr) {
1061 size_t result = p_in->readBytes(data, len);
1067 void delayBytes(
size_t bytes) { delayFrames(bytes / frame_size); }
1070 void delayFrames(
size_t frames) {
1071 sum_frames += frames;
1072 uint64_t durationUsEff = micros() - start_time;
1073 uint64_t durationUsToBe = getDelayUs(sum_frames);
1074 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1075 LOGD(
"wait us: %ld",
static_cast<long>(waitUs));
1077 int64_t waitMs = waitUs / 1000;
1078 if (waitMs > 0) delay(waitMs);
1079 delayMicroseconds(waitUs - (waitMs * 1000));
1081 LOGD(
"negative delay!")
1085 inline int64_t getDelayUs(uint64_t frames){
1086 return (frames * 1000000) / cfg.sample_rate;
1089 inline int64_t getDelayMs(uint64_t frames){
1090 return getDelayUs(frames) / 1000;
1093 inline int64_t getDelaySec(uint64_t frames){
1094 return getDelayUs(frames) / 1000000l;
1098 uint32_t start_time = 0;
1099 uint32_t sum_frames = 0;
1102 Print *p_out =
nullptr;
1103 Stream *p_in =
nullptr;
1115 template<
typename T>
1122 streams.push_back(&in);
1123 weights.push_back(weight);
1124 total_weights += weight;
1129 if (channel<
size()){
1130 streams[channel] = ∈
1132 LOGE(
"Invalid channel %d - max is %d", channel,
size()-1);
1139 LOGI(
"frame_size: %d",frame_size);
1140 return frame_size>0;
1145 if (channel<
size()){
1146 weights[channel] = weight;
1148 for (
int j=0;j<weights.size();j++){
1149 total += weights[j];
1151 total_weights = total;
1153 LOGE(
"Invalid channel %d - max is %d", channel,
size()-1);
1161 result_vect.clear();
1162 current_vect.clear();
1163 total_weights = 0.0;
1168 return streams.size();
1173 if (total_weights==0 || frame_size==0 || len==0) {
1174 LOGW(
"readBytes: %d",(
int)len);
1178 if (limit_available_data){
1186 result_len = len * frame_size / frame_size;
1196 limit_available_data = flag;
1201 retry_count = retry;
1206 Vector<int> weights{0};
1207 int total_weights = 0;
1209 bool limit_available_data =
false;
1210 int retry_count = 5;
1211 Vector<int> result_vect;
1212 Vector<T> current_vect;
1216 int samples = byteCount /
sizeof(T);
1217 result_vect.resize(samples);
1218 current_vect.resize(samples);
1219 int stream_count =
size();
1221 int samples_eff_max = 0;
1222 for (
int j=0;j<stream_count;j++){
1224 int samples_eff =
readSamples(streams[j],current_vect.data(), samples, retry_count);
1225 if (samples_eff > samples_eff_max)
1226 samples_eff_max = samples_eff;
1228 float factor = total_weights == 0.0f ? 0.0f :
static_cast<float>(weights[j]) / total_weights;
1233 for (
int j=0;j<samples;j++){
1234 p_data[j] = result_vect[j];
1236 return samples_eff_max *
sizeof(T);
1241 int result = DEFAULT_BUFFER_SIZE;
1242 for (
int j=0;j<
size();j++){
1243 result = min(result, streams[j]->available());
1248 void resultAdd(
float fact){
1249 for (
int j=0;j<current_vect.size();j++){
1250 current_vect[j]*=fact;
1251 result_vect[j] += current_vect[j];
1256 memset(result_vect.data(), 0,
sizeof(
int)*result_vect.size());
1270 template<
typename T>
1287 LOGW(
"channels corrected to %d",
size());
1293 virtual bool begin() {
1296 return AudioStream::begin();
1301 LOGD(
"readBytes: %d",(
int)len);
1302 T *p_data = (T*) data;
1304 int sample_count = result_len /
sizeof(T);
1305 int size_value =
size();
1307 for (
int j=0;j<sample_count; j++){
1308 for (
int i=0; i<size_value; i++){
1309 p_data[result_idx++] = weights[i] * readSample<T>(streams[i]);
1312 return result_idx*
sizeof(T);
1317 streams.push_back(&in);
1318 weights.push_back(weight);
1323 if (channel<
size()){
1324 weights[channel] = weight;
1326 LOGE(
"Invalid channel %d - max is %d", channel,
size()-1);
1338 return streams.size();
1343 int result = streams[0]->available();
1344 for (
int j=1;j<
size();j++){
1345 int tmp = streams[j]->available();
1355 Vector<float> weights{10};
1374 setUpdateCallback(cb_update);
1380 setUpdateCallback(cb_update);
1383 CallbackStream(
size_t (*cb_read)(uint8_t* data,
size_t len),
size_t (*cb_write)(
const uint8_t* data,
size_t len)) {
1384 setWriteCallback(cb_write);
1385 setReadCallback(cb_read);
1388 void setWriteCallback(
size_t (*cb_write)(
const uint8_t* data,
size_t len)){
1389 this->cb_write = cb_write;
1392 void setReadCallback(
size_t (*cb_read)(uint8_t* data,
size_t len)){
1393 this->cb_read = cb_read;
1396 void setUpdateCallback(
size_t (*cb_update)(uint8_t* data,
size_t len)){
1397 this->cb_update = cb_update;
1401 void setAvailableCallback(
int (*cb)()){
1402 this->cb_available = cb;
1405 virtual bool begin(AudioInfo info) {
1409 virtual bool begin()
override {
1414 void end()
override { active =
false;}
1416 int available()
override {
1417 int result = AudioStream::available();
1419 if (available_bytes>=0)
1420 return available_bytes;
1422 if (cb_available==
nullptr)
1425 int tmp_available = cb_available();
1426 if (tmp_available < 0)
1429 return tmp_available;
1432 size_t readBytes(uint8_t* data,
size_t len)
override {
1433 if (!active)
return 0;
1436 return cb_read(data, len);
1441 result = p_stream->readBytes(data , len);
1444 result = cb_update(data, result);
1449 size_t write(
const uint8_t* data,
size_t len)
override {
1450 if (!active)
return 0;
1453 return cb_write(data, len);
1457 size_t result = len;
1459 result = cb_update((uint8_t*)data, len);
1461 return p_out->write(data, result);
1491 available_bytes = val;
1498 size_t (*cb_write)(
const uint8_t* data,
size_t len) =
nullptr;
1499 size_t (*cb_read)(uint8_t* data,
size_t len) =
nullptr;
1500 size_t (*cb_update)(uint8_t* data,
size_t len) =
nullptr;
1501 int (*cb_available)() =
nullptr;
1502 Stream *p_stream =
nullptr;
1503 Print *p_out =
nullptr;
1504 int available_bytes = -1;
1515 template<
typename T,
class TF>
1523 this->channels = channels;
1531 this->channels = channels;
1548 if (p_converter !=
nullptr && info.
channels!=channels){
1549 LOGE(
"Inconsistent number of channels");
1555 bool begin()
override {
1557 LOGE(
"channels must not be 0");
1560 if (p_converter==
nullptr){
1561 p_converter =
new ConverterNChannels<T,TF>(channels);
1563 return AudioStream::begin();
1566 virtual size_t write(
const uint8_t *data,
size_t len)
override {
1567 if (p_converter==
nullptr)
return 0;
1568 size_t result = p_converter->convert((uint8_t *)data, len);
1569 return p_print->write(data, result);
1572 size_t readBytes(uint8_t *data,
size_t len)
override {
1573 if (p_converter==
nullptr)
return 0;
1574 if (p_stream==
nullptr)
return 0;
1575 size_t result = p_stream->readBytes(data, len);
1576 result = p_converter->convert(data, result);
1580 virtual int available()
override {
1581 if (p_stream==
nullptr)
return 0;
1582 return p_stream->available();
1585 virtual int availableForWrite()
override {
1586 return p_print->availableForWrite();
1592 if (p_converter!=
nullptr){
1593 p_converter->
setFilter(channel, filter);
1595 LOGE(
"p_converter is null");
1607 Stream *p_stream =
nullptr;
1608 Print *p_print =
nullptr;
1644 bool begin()
override {
1656 size_t write(
const uint8_t *data,
size_t len) {
1657 updateVolumes(data, len);
1658 size_t result = len;
1659 if (p_out!=
nullptr){
1660 result = p_out->write(data, len);
1665 size_t readBytes(uint8_t *data,
size_t len){
1666 if (p_stream==
nullptr)
return 0;
1667 size_t result = p_stream->readBytes(data, len);
1668 updateVolumes((
const uint8_t*)data, len);
1679 if (volumes.size() == 0) {
1680 LOGE(
"begin not called!");
1683 if (channel >= volumes.size()) {
1684 LOGE(
"invalid channel %d", channel);
1687 return volumes[channel];
1721 for (
int j = 0; j < info.
channels; j++) {
1735 float f_volume_tmp = 0;
1738 Vector<float> volumes_tmp{0};
1739 Print* p_out =
nullptr;
1740 Stream* p_stream =
nullptr;
1742 void updateVolumes(
const uint8_t *data,
size_t len){
1746 updateVolumesT<int16_t>(data, len);
1749 updateVolumesT<int24_t>(data, len);
1752 updateVolumesT<int32_t>(data, len);
1760 template <
typename T>
void updateVolumesT(
const uint8_t *buffer,
size_t size) {
1761 T *bufferT = (T *)buffer;
1762 int samplesCount = size /
sizeof(T);
1763 for (
int j = 0; j < samplesCount; j++) {
1764 float tmp = abs(
static_cast<float>(bufferT[j]));
1765 updateVolume(tmp, j);
1770 void updateVolume(
float tmp,
int j) {
1771 if (tmp > f_volume_tmp) {
1774 if (volumes_tmp.size() > 0 && info.
channels > 0) {
1776 if (tmp > volumes_tmp[ch]) {
1777 volumes_tmp[ch] = tmp;
1783 f_volume = f_volume_tmp;
1784 for (
int j = 0; j < info.
channels; j++) {
1785 volumes[j] = volumes_tmp[j];
1791 using VolumePrint = VolumeMeter;
1792 using VolumeOutput = VolumeMeter;
1802 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
1803 bool use_timer =
true;
1805 TimerFunction timer_function = DirectTimerCallback;
1806 bool adapt_sample_rate =
false;
1807 uint16_t (*callback)(uint8_t *data, uint16_t len) =
nullptr;
1811 static void timerCallback(
void *obj);
1822 friend void timerCallback(
void *obj);
1829 if (timer !=
nullptr)
delete timer;
1830 if (buffer !=
nullptr)
delete buffer;
1831 if (frame !=
nullptr)
delete[] frame;
1845 bool do_restart = active;
1846 if (do_restart)
end();
1850 if (do_restart)
begin(cfg);
1859 LOGD(
"%s: %s", LOG_METHOD,
1860 config.rx_tx_mode == RX_MODE ?
"RX_MODE" :
"TX_MODE");
1862 this->frameCallback = config.callback;
1863 if (cfg.use_timer) {
1864 frameSize = cfg.bits_per_sample * cfg.channels / 8;
1865 frame =
new uint8_t[frameSize];
1868 timer->setTimerFunction(cfg.timer_function);
1869 if (cfg.timer_id>=0){
1870 timer->setTimer(cfg.timer_id);
1873 LOGI(
"sample_rate: %u -> time: %u milliseconds", (
unsigned int)cfg.sample_rate, (
unsigned int)time);
1874 timer->setCallbackParameter(
this);
1875 timer->begin(timerCallback, time, TimeUnit::US);
1878 notifyAudioChange(cfg);
1885 if (this->frameCallback !=
nullptr) {
1886 if (cfg.use_timer) {
1887 timer->begin(timerCallback, time, TimeUnit::US);
1897 if (cfg.use_timer) {
1908 bool active =
false;
1909 uint16_t (*frameCallback)(uint8_t *data, uint16_t len);
1913 uint8_t *frame =
nullptr;
1914 uint16_t frameSize = 0;
1916 unsigned long lastTimestamp = 0u;
1917 uint32_t currentRateValue = 0;
1918 uint32_t printCount = 0;
1921 virtual size_t writeExt(
const uint8_t *data,
size_t len)
override {
1922 if (!active)
return 0;
1925 if (!cfg.use_timer) {
1926 result = frameCallback((uint8_t *)data, len);
1928 result = buffer->
writeArray((uint8_t *)data, len);
1935 virtual size_t readExt(uint8_t *data,
size_t len)
override {
1936 if (!active)
return 0;
1940 if (!cfg.use_timer) {
1941 result = frameCallback(data, len);
1951 unsigned long ms =
millis();
1952 if (lastTimestamp > 0u) {
1953 uint32_t diff = ms - lastTimestamp;
1955 uint16_t rate = 1 * 1000 / diff;
1957 if (currentRateValue == 0) {
1958 currentRateValue = rate;
1960 currentRateValue = (currentRateValue + rate) / 2;
1969 LOGI(
"effective sample rate: %u", (
unsigned int)currentRateValue);
1970 if (cfg.adapt_sample_rate &&
1971 abs((
int)currentRateValue - (
int)cfg.
sample_rate) > 200) {
1973 notifyAudioChange(cfg);
1979 void IRAM_ATTR timerCallback(
void *obj) {
1980 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
1981 if (src !=
nullptr) {
1984 if (src->cfg.rx_tx_mode == RX_MODE) {
1986 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
1987 uint16_t buffer_available = src->buffer->availableForWrite();
1988 if (buffer_available < available_bytes) {
1990 uint16_t to_clear = available_bytes - buffer_available;
1991 uint8_t tmp[to_clear];
1992 src->buffer->readArray(tmp, to_clear);
1994 if (src->buffer->writeArray(src->frame, available_bytes) !=
2000 if (src->buffer !=
nullptr && src->frame !=
nullptr &&
2001 src->frameSize > 0) {
2002 uint16_t available_bytes =
2003 src->buffer->readArray(src->frame, src->frameSize);
2004 if (available_bytes !=
2005 src->frameCallback(src->frame, available_bytes)) {
2006 LOGE(
"data underflow");
2010 src->measureSampleRate();
MemoryType
Memory types.
Definition: AudioTypes.h:35
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition: AudioTypes.h:28