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;
99 LOGD(
"MemoryStream: %d", buffer_size);
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){
268 if (!memoryCanChange())
return false;
272#if defined(ESP32) && defined(ARDUINO)
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;
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(); }
406 if (
newInfo.bits_per_sample !=
sizeof(
T)*8){
407 LOGE(
"Wrong bits_per_sample: %d",
newInfo.bits_per_sample);
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);
520 LOGD(
"%s: %zu", LOG_METHOD, len);
522 for (
int j=0;
j<len;
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());
582 buffer.setAvailable(result);
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;
719 total_bytes_since_begin += len;
720 return measure(p_stream->readBytes(data, len));
723 int available()
override {
724 return p_stream->available();
729 total_bytes_since_begin += len;
730 return measure(p_print->write(data, len));
735 return p_print->availableForWrite();
740 return bytes_per_second;
745 if (frame_size==0)
return 0;
746 return bytes_per_second/frame_size;
755 AudioStream::info = info;
760 total_bytes_since_begin = 0;
762 return AudioStream::begin();
765 bool begin(AudioInfo info){
780 void setName(
const char* name){
786 return millis() - ms_at_begin;
791 return total_bytes_since_begin;
809 if (pos < total_bytes_since_begin) {
813 total_bytes_since_begin = pos;
821 Print *p_print=
nullptr;
824 int bytes_per_second = 0;
827 Print *p_logout=
nullptr;
828 bool report_bytes =
false;
829 const char* name =
"";
831 uint32_t total_bytes_since_begin = 0;
833 size_t measure(
size_t len) {
841 bytes_per_second = total_bytes /
time_diff * 1000;
853 if (report_bytes || frame_size==0){
854 snprintf(msg, 70,
"%s ==> Bytes per second: %d", name, bytes_per_second);
856 snprintf(msg, 70,
"%s ==> Samples per second: %d", name, bytes_per_second/frame_size);
858 if (p_logout!=
nullptr){
859 p_logout->println(msg);
874 size_t total_size = 0;
897 p_info_from = &stream;
901 return progress_info;
918 void setPrint(Print &print){
922 bool begin()
override {
923 if (p_info_from!=
nullptr){
926 return AudioStream::begin();
936 progress_info = info;
944 progress_info.total_size = len;
949 return progress_info.total_size;
954 return total_processed;
959 return total_processed / byteRate();
964 return progress_info.total_size;
974 if (progress_info.total_size==0)
return 0;
975 return 100.0 * total_processed / progress_info.total_size;
980 if (p_stream==
nullptr)
return 0;
981 return measure(p_stream->readBytes(data, len));
984 int available()
override {
985 if (p_stream==
nullptr)
return 0;
986 return p_stream->available();
991 if (p_print==
nullptr)
return 0;
992 return measure(p_print->write(data, len));
997 if (p_print==
nullptr)
return 0;
998 return p_print->availableForWrite();
1003 Stream *p_stream=
nullptr;
1004 Print *p_print=
nullptr;
1006 size_t total_processed = 0;
1008 size_t measure(
size_t len) {
1009 total_processed += len;
1015 int byte_rate = info.sample_rate * info.bits_per_sample * info.channels / 8;
1017 LOGE(
"Audio Info not defined");
1036 int correction_us = 0;
1067 bool begin(ThrottleConfig cfg) {
1074 bool begin(AudioInfo info) {
1075 LOGI(
"begin sample_rate: %d, channels: %d, bits: %d", (
int)info.sample_rate, (
int) info.channels, (
int)info.bits_per_sample);
1077 this->cfg.copyFrom(info);
1082 frame_size = cfg.bits_per_sample / 8 * cfg.channels;
1089 start_time = micros();
1093 int availableForWrite() {
1095 return p_out->availableForWrite();
1097 return DEFAULT_BUFFER_SIZE;
1100 size_t write(
const uint8_t* data,
size_t len){
1101 size_t result = p_out->write(data, len);
1107 if (p_in==
nullptr)
return 0;
1108 return p_in->available();
1111 size_t readBytes(uint8_t* data,
size_t len)
override{
1112 if (p_in==
nullptr) {
1116 size_t result = p_in->readBytes(data, len);
1122 void delayBytes(
size_t bytes) { delayFrames(bytes / frame_size); }
1125 void delayFrames(
size_t frames) {
1126 sum_frames += frames;
1127 uint64_t durationUsEff = micros() - start_time;
1128 uint64_t durationUsToBe = getDelayUs(sum_frames);
1129 int64_t waitUs = durationUsToBe - durationUsEff + cfg.correction_us;
1130 LOGD(
"wait us: %ld",
static_cast<long>(waitUs));
1132 int64_t waitMs = waitUs / 1000;
1133 if (waitMs > 0) delay(waitMs);
1134 delayMicroseconds(waitUs - (waitMs * 1000));
1136 LOGD(
"negative delay!")
1140 inline int64_t getDelayUs(uint64_t frames){
1141 return (frames * 1000000) / cfg.sample_rate;
1144 inline int64_t getDelayMs(uint64_t frames){
1145 return getDelayUs(frames) / 1000;
1148 inline int64_t getDelaySec(uint64_t frames){
1149 return getDelayUs(frames) / 1000000l;
1153 uint32_t start_time = 0;
1154 uint32_t sum_frames = 0;
1157 Print *p_out =
nullptr;
1158 Stream *p_in =
nullptr;
1177 streams.push_back(&in);
1178 weights.push_back(
weight);
1184 if (channel<
size()){
1185 streams[channel] = ∈
1187 LOGE(
"Invalid channel %d - max is %d", channel,
size()-1);
1194 LOGI(
"frame_size: %d",frame_size);
1195 return frame_size>0;
1200 if (channel<
size()){
1201 weights[channel] =
weight;
1203 for (
int j=0;
j<weights.size();
j++){
1204 total += weights[
j];
1206 total_weights = total;
1208 LOGE(
"Invalid channel %d - max is %d", channel,
size()-1);
1216 result_vect.clear();
1217 current_vect.clear();
1218 total_weights = 0.0;
1223 return streams.size();
1228 if (total_weights==0 || frame_size==0 || len==0) {
1229 LOGW(
"readBytes: %d",(
int)len);
1233 if (limit_available_data){
1251 limit_available_data =
flag;
1256 retry_count =
retry;
1261 Vector<int> weights{0};
1262 int total_weights = 0;
1264 bool limit_available_data =
false;
1265 int retry_count = 5;
1266 Vector<int> result_vect;
1267 Vector<T> current_vect;
1272 result_vect.resize(samples);
1273 current_vect.resize(samples);
1283 float factor = total_weights == 0.0f ? 0.0f :
static_cast<float>(weights[
j]) / total_weights;
1288 for (
int j=0;
j<samples;
j++){
1289 p_data[
j] = result_vect[
j];
1296 int result = DEFAULT_BUFFER_SIZE;
1298 result = min(result, streams[
j]->available());
1303 void resultAdd(
float fact){
1304 for (
int j=0;
j<current_vect.size();
j++){
1305 current_vect[
j]*=
fact;
1306 result_vect[
j] += current_vect[
j];
1311 memset(result_vect.data(), 0,
sizeof(
int)*result_vect.size());
1342 LOGW(
"channels corrected to %d",
size());
1348 virtual bool begin() {
1351 return AudioStream::begin();
1356 LOGD(
"readBytes: %d",(
int)len);
1357 T *p_data = (
T*) data;
1362 for (
int j=0;
j<sample_count;
j++){
1372 streams.push_back(&in);
1373 weights.push_back(
weight);
1378 if (channel<
size()){
1379 weights[channel] =
weight;
1381 LOGE(
"Invalid channel %d - max is %d", channel,
size()-1);
1393 return streams.size();
1398 int result = streams[0]->available();
1400 int tmp = streams[
j]->available();
1410 Vector<float> weights{10};
1429 setUpdateCallback(cb_update);
1435 setUpdateCallback(cb_update);
1439 setWriteCallback(cb_write);
1440 setReadCallback(cb_read);
1443 void setWriteCallback(
size_t (*cb_write)(
const uint8_t* data,
size_t len)){
1444 this->cb_write = cb_write;
1447 void setReadCallback(
size_t (*cb_read)(uint8_t* data,
size_t len)){
1448 this->cb_read = cb_read;
1451 void setUpdateCallback(
size_t (*cb_update)(uint8_t* data,
size_t len)){
1452 this->cb_update = cb_update;
1456 void setAvailableCallback(
int (*cb)()){
1457 this->cb_available = cb;
1460 virtual bool begin(AudioInfo info) {
1464 virtual bool begin()
override {
1469 void end()
override { active =
false;}
1471 int available()
override {
1472 int result = AudioStream::available();
1474 if (available_bytes>=0)
1475 return available_bytes;
1477 if (cb_available==
nullptr)
1480 int tmp_available = cb_available();
1481 if (tmp_available < 0)
1484 return tmp_available;
1487 size_t readBytes(uint8_t* data,
size_t len)
override {
1488 if (!active)
return 0;
1491 return cb_read(data, len);
1496 result = p_stream->readBytes(data , len);
1499 result = cb_update(data, result);
1504 size_t write(
const uint8_t* data,
size_t len)
override {
1505 if (!active)
return 0;
1508 return cb_write(data, len);
1512 size_t result = len;
1514 result = cb_update((uint8_t*)data, len);
1516 return p_out->write(data, result);
1546 available_bytes =
val;
1553 size_t (*cb_write)(
const uint8_t* data,
size_t len) =
nullptr;
1556 int (*cb_available)() =
nullptr;
1557 Stream *p_stream =
nullptr;
1558 Print *p_out =
nullptr;
1559 int available_bytes = -1;
1570template<
typename T,
class TF>
1578 this->channels = channels;
1586 this->channels = channels;
1603 if (p_converter !=
nullptr && p_converter->getChannels()!=channels){
1604 LOGE(
"Inconsistent number of channels");
1610 bool begin()
override {
1612 LOGE(
"channels must not be 0");
1615 if (p_converter==
nullptr){
1616 p_converter =
new ConverterNChannels<T,TF>(channels);
1618 return AudioStream::begin();
1621 virtual size_t write(
const uint8_t *data,
size_t len)
override {
1622 if (p_converter==
nullptr)
return 0;
1623 size_t result = p_converter->convert((uint8_t *)data, len);
1624 return p_print->write(data, result);
1627 size_t readBytes(uint8_t *data,
size_t len)
override {
1628 if (p_converter==
nullptr)
return 0;
1629 if (p_stream==
nullptr)
return 0;
1630 size_t result = p_stream->readBytes(data, len);
1631 result = p_converter->convert(data, result);
1635 virtual int available()
override {
1636 if (p_stream==
nullptr)
return 0;
1637 return p_stream->available();
1640 virtual int availableForWrite()
override {
1641 return p_print->availableForWrite();
1647 if (p_converter!=
nullptr){
1648 p_converter->
setFilter(channel, filter);
1650 LOGE(
"p_converter is null");
1662 Stream *p_stream =
nullptr;
1663 Print *p_print =
nullptr;
1699 bool begin()
override {
1711 size_t write(
const uint8_t *data,
size_t len) {
1712 updateVolumes(data, len);
1713 size_t result = len;
1714 if (p_out!=
nullptr){
1715 result = p_out->write(data, len);
1720 size_t readBytes(uint8_t *data,
size_t len){
1721 if (p_stream==
nullptr)
return 0;
1722 size_t result = p_stream->readBytes(data, len);
1723 updateVolumes((
const uint8_t*)data, len);
1734 if (volumes.size() == 0) {
1735 LOGE(
"begin not called!");
1738 if (channel >= volumes.size()) {
1739 LOGE(
"invalid channel %d", channel);
1742 return volumes[channel];
1778 count += sample_count_per_channel;
1780 return total / count;
1785 return sum[channel] / sample_count_per_channel;
1807 float f_volume_tmp = 0;
1810 Vector<float> volumes_tmp{0};
1811 Vector<float> sum{0};
1812 Vector<float> sum_tmp{0};
1813 Print* p_out =
nullptr;
1814 Stream* p_stream =
nullptr;
1815 size_t sample_count_per_channel = 0;
1817 void updateVolumes(
const uint8_t *data,
size_t len){
1821 updateVolumesT<int8_t>(data, len);
1824 updateVolumesT<int16_t>(data, len);
1827 updateVolumesT<int24_t>(data, len);
1830 updateVolumesT<int32_t>(data, len);
1838 template <
typename T>
void updateVolumesT(
const uint8_t *buffer,
size_t size) {
1839 T *bufferT = (T *)buffer;
1840 int samplesCount = size /
sizeof(T);
1841 sample_count_per_channel = samplesCount / info.
channels;
1842 for (
int j = 0; j < samplesCount; j++) {
1843 float tmp = abs(
static_cast<float>(bufferT[j]));
1844 updateVolume(tmp, j);
1849 void updateVolume(
float tmp,
int j) {
1850 if (tmp > f_volume_tmp) {
1853 if (volumes_tmp.size() > 0 && info.
channels > 0) {
1855 if (tmp > volumes_tmp[ch]) {
1856 volumes_tmp[ch] = tmp;
1863 f_volume = f_volume_tmp;
1864 for (
int j = 0; j < info.
channels; j++) {
1865 volumes[j] = volumes_tmp[j];
1866 sum[j] = sum_tmp[j];
1872using VolumePrint = VolumeMeter;
1873using VolumeOutput = VolumeMeter;
1883 uint16_t buffer_size = DEFAULT_BUFFER_SIZE;
1884 bool use_timer =
true;
1886 TimerFunction timer_function = DirectTimerCallback;
1887 bool adapt_sample_rate =
false;
1892static void timerCallback(
void *
obj);
1903 friend void timerCallback(
void *
obj);
1910 if (timer !=
nullptr)
delete timer;
1911 if (buffer !=
nullptr)
delete buffer;
1912 if (frame !=
nullptr)
delete[] frame;
1940 LOGD(
"%s: %s", LOG_METHOD,
1941 config.rx_tx_mode == RX_MODE ?
"RX_MODE" :
"TX_MODE");
1943 this->frameCallback = config.callback;
1944 if (cfg.use_timer) {
1945 frameSize = cfg.bits_per_sample * cfg.channels / 8;
1946 frame =
new uint8_t[frameSize];
1949 timer->setTimerFunction(cfg.timer_function);
1950 if (cfg.timer_id>=0){
1951 timer->setTimer(cfg.timer_id);
1954 LOGI(
"sample_rate: %u -> time: %u milliseconds", (
unsigned int)cfg.sample_rate, (
unsigned int)time);
1955 timer->setCallbackParameter(
this);
1956 timer->begin(timerCallback, time, TimeUnit::US);
1959 notifyAudioChange(cfg);
1966 if (this->frameCallback !=
nullptr) {
1967 if (cfg.use_timer) {
1968 timer->begin(timerCallback, time, TimeUnit::US);
1978 if (cfg.use_timer) {
1989 bool active =
false;
1997 unsigned long lastTimestamp = 0
u;
2002 virtual size_t writeExt(
const uint8_t *data,
size_t len)
override {
2003 if (!active)
return 0;
2006 if (!cfg.use_timer) {
2007 result = frameCallback((
uint8_t *)data, len);
2009 result = buffer->writeArray((uint8_t *)data, len);
2016 virtual size_t readExt(uint8_t *data,
size_t len)
override {
2017 if (!active)
return 0;
2021 if (!cfg.use_timer) {
2022 result = frameCallback(data, len);
2024 result = buffer->readArray(data, len);
2032 unsigned long ms =
millis();
2033 if (lastTimestamp > 0
u) {
2038 if (currentRateValue == 0) {
2039 currentRateValue = rate;
2041 currentRateValue = (currentRateValue + rate) / 2;
2050 LOGI(
"effective sample rate: %u", (
unsigned int)currentRateValue);
2051 if (cfg.adapt_sample_rate &&
2054 notifyAudioChange(cfg);
2060void IRAM_ATTR timerCallback(
void *obj) {
2061 TimerCallbackAudioStream *src = (TimerCallbackAudioStream *)obj;
2062 if (src !=
nullptr) {
2065 if (src->cfg.rx_tx_mode == RX_MODE) {
2067 uint16_t available_bytes = src->frameCallback(src->frame, src->frameSize);
2068 uint16_t buffer_available = src->buffer->availableForWrite();
2069 if (buffer_available < available_bytes) {
2071 uint16_t to_clear = available_bytes - buffer_available;
2072 uint8_t tmp[to_clear];
2073 src->buffer->readArray(tmp, to_clear);
2075 if (src->buffer->writeArray(src->frame, available_bytes) !=
2081 if (src->buffer !=
nullptr && src->frame !=
nullptr &&
2082 src->frameSize > 0) {
2083 uint16_t available_bytes =
2084 src->buffer->readArray(src->frame, src->frameSize);
2085 if (available_bytes !=
2086 src->frameCallback(src->frame, available_bytes)) {
2087 LOGE(
"data underflow");
2091 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