11#pragma push_macro("abs")
22#pragma pop_macro("abs")
28#ifndef ARDUINO_USB_MODE
29#error This Microcontroller has no Native USB interface
31#if ARDUINO_USB_MODE == 1
32#error This sketch should be used when USB is in OTG mode
36#if !defined(USE_TINYUSB) && !defined(ARDUINO_ARCH_STM32) && \
37 !defined(ARDUINO_ARCH_RENESAS) && !defined(IS_ZEPHYR)
38#error This Microcontroller has no Native USB interface
42#include "AudioLogger.h"
47#define USB_DESCR_MAX_LEN 512
92static inline uint8_t
u16Low(uint16_t v) {
return (uint8_t)(v & 0xFF); }
93static inline uint8_t
u16High(uint16_t v) {
return (uint8_t)(v >> 8); }
115 enum audio_format_type_t {
117 AUDIO_FORMAT_TYPE_II,
118 AUDIO_FORMAT_TYPE_III,
127 enum audio_feedback_method_t {
128 AUDIO_FEEDBACK_METHOD_DISABLED,
129 AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED,
130 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT,
131 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2,
132 AUDIO_FEEDBACK_METHOD_FIFO_COUNT
141 struct audiod_function_t {
143 uint8_t
const* p_desc;
155 volatile uint8_t ep_in;
159 volatile uint8_t ep_out;
166 uint16_t desc_length;
172 uint8_t compute_method;
173 bool format_correction;
178 uint32_t sample_freq;
183 uint32_t fifo_lvl_avg;
184 uint16_t fifo_lvl_thr;
185 uint16_t rate_const[2];
189 uint32_t sample_rate_tx;
190 uint16_t packet_sz_tx[3];
191 uint8_t bclock_id_tx;
193 audio_format_type_t format_type_tx;
194 uint8_t n_channels_tx;
195 uint8_t n_bytes_per_sample_tx;
199 uint32_t tx_sample_acc;
207 std::vector<uint8_t> ctrl_buf;
208 std::vector<uint8_t> alt_setting;
209 std::vector<uint8_t> lin_buf_out;
210 std::vector<uint8_t> lin_buf_in;
211 std::vector<uint32_t> fb_buf;
220 struct audio_feedback_params_t {
222 uint32_t sample_freq;
270 LOGE(
"Unsupported bits_per_sample: %d (must be 16, 24, or 32)",
286 "Could not change channel count from %d to %d: channel count is "
292 "Could not change bits per sample from %d to %d: bits per sample is "
330 LOGE(
"Unsupported bits_per_sample: %d (must be 16, 24, or 32)",
341 uint16_t cb_sz = 64u;
345 if (needed > cb_sz) cb_sz = needed;
356 mute_.assign(vol_sz,
false);
362 LOGE(
"beginUSB failed");
371 for (uint8_t ch = 0; ch < (uint8_t)
volume_.size(); ch++) {
424 LOGW(
"setVolume %f channel: %d", vol, channel);
425 if (channel >=
volume_.size())
return false;
436 return (channel <
mute_.size()) ?
mute_[channel] :
false;
444 LOGW(
"setMute %s channel: %d", m ?
"true" :
"false", channel);
445 if (channel >=
mute_.size())
return false;
490 if (fct.ep_in != 0)
return true;
498 if (fct.ep_out != 0)
return true;
563 audiod_function_t*, uint16_t)>
637 audio_feedback_params_t*)>
654 size_t write(
const uint8_t* data,
size_t len) {
669 while (written < len) {
711 std::fill(audio.lin_buf_in.begin(), audio.lin_buf_in.end(), 0);
712 std::fill(audio.lin_buf_out.begin(), audio.lin_buf_out.end(), 0);
811 uint16_t xferred_bytes)>
845 audio_feedback_params_t* feedback_param)>
897 processVolume<int8_t>((int8_t*)data, len);
900 processVolume<int16_t>((int16_t*)data, len / 2);
906 processVolume<int32_t>((int32_t*)data, len / 4);
917 if (
volume_.empty())
return 1.0f;
918 if (
mute_[0])
return 0.0f;
920 if (channel >=
volume_.size())
return master;
921 if (
mute_[channel])
return 0.0f;
922 return master *
volume_[channel];
925 template <
typename T>
928 for (
size_t i = 0; i < sample_count; i++) {
929 uint8_t ch = (uint8_t)(i % ch_count) + 1;
931 data[i] = (T)(data[i] * vol);
946 LOGW(
"Sample rate changed to %u Hz", rate);
951 for (
auto& fct :
audiod_fct_) fct.sample_rate_tx = rate;
977 if (vol <= 0.0f)
return (int16_t)0x8000;
978 if (vol >= 1.0f)
return 0;
985 if (v == (int16_t)0x8000)
return 0.0f;
986 if (v >= 0)
return 1.0f;
1008 for (uint8_t i = 0; i < (uint8_t)
audiod_fct_.size(); i++) {
1034 return bps == 16 || bps == 24 || bps == 32;
1048 return offsetof(audiod_function_t, ctrl_buf_sz) +
1049 sizeof(((audiod_function_t*)0)->ctrl_buf_sz);
1056 uint8_t frame_shift) {
1059 switch (audio->feedback.compute_method) {
1060 case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: {
1068 audio->feedback.compute.fifo_count.fifo_lvl_avg =
1069 audio->feedback.compute.fifo_count.fifo_lvl_avg -
1070 (audio->feedback.compute.fifo_count.fifo_lvl_avg >> 8) +
1071 ((uint32_t)ff_count << 8);
1072 uint32_t avg = audio->feedback.compute.fifo_count.fifo_lvl_avg >> 8;
1073 uint32_t thr = audio->feedback.compute.fifo_count.fifo_lvl_thr;
1074 uint32_t nom = audio->feedback.compute.fifo_count.nom_value;
1076 audio->feedback.value =
1077 nom + (uint32_t)audio->feedback.compute.fifo_count.rate_const[0] *
1081 (uint32_t)audio->feedback.compute.fifo_count.rate_const[1] *
1083 audio->feedback.value =
1084 (nom > drop) ? nom - drop : audio->feedback.min_value;
1086 uint32_t clamped = audio->feedback.value < audio->feedback.min_value
1087 ? audio->feedback.min_value
1088 : audio->feedback.value;
1089 audio->feedback.value = clamped > audio->feedback.max_value
1090 ? audio->feedback.max_value
1094 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
1095 audio->feedback.value = 1UL << audio->feedback.compute.power_of_2;
1098 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
1099 audio->feedback.value =
1100 (uint32_t)(audio->feedback.compute.float_const *
1101 (
float)(1UL << (16u - (frame_shift - 1u))));
1104 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED: {
1106 audio->feedback.value =
1107 (audio->feedback.compute.fixed.sample_freq << 16) / frame_div;
1133 audio->ctrl_buf.resize(size);
1134 audio->ctrl_buf_sz = size;
1143 audio->lin_buf_in.resize(max_pkt);
1149 audio->lin_buf_out.resize(max_pkt);
1152 audio->fb_buf.resize(1);
1176 uint8_t
const* raw_desc, uint16_t max_len) {
1195 uint8_t ep_in = 0, ep_out = 0, ep_fb = 0;
1196 uint16_t ep_in_size = 0, ep_out_size = 0;
1198 bool has_ep_out_view =
false;
1200 uint8_t
const* p_desc_end =
1202 while (p_desc_end - p_desc > 0) {
1209 if (desc_ep.
usage == 0) {
1213 ep_in_size = sz > ep_in_size ? sz : ep_in_size;
1218 ep_out_size = sz > ep_out_size ? sz : ep_out_size;
1219 desc_ep_out = desc_ep;
1220 has_ep_out_view =
true;
1229 LOGD(
"iso_alloc IN ep=0x%02x sz=%u: %s", ep_in, ep_in_size,
1230 alloc_ok ?
"OK" :
"FAIL");
1234 LOGD(
"iso_alloc OUT ep=0x%02x sz=%u: %s", ep_out, ep_out_size,
1235 alloc_ok ?
"OK" :
"FAIL");
1236 if (has_ep_out_view)
audiod_fct_[i].ep_out_view = desc_ep_out;
1246 LOGD(
"iso_activate OUT: done");
1261 uint8_t
const* p_desc_end =
1263 while (p_desc_end - p_desc > 0) {
1289 uint8_t
const* p_desc_end =
1291 while (p_desc_end - p_desc > 0) {
1300 LOGE(
" UAC2: interrupt EP 0x%02x open failed", ep_addr);
1340 if (entityID != 0) {
1343 uint8_t* cb =
audiod_fct_[func_id].ctrl_buf.data();
1377 this, rhport, p_request,
1392 this, rhport, p_request,
audiod_fct_[func_id].ctrl_buf.data());
1405 uint32_t xferred_bytes) {
1407 (void)xferred_bytes;
1408 for (uint8_t func_id = 0; func_id <
getAudioCount(); func_id++) {
1415 audio->alt_setting.size() != 0) {
1422 if (frame_bytes > audio->ep_in_sz) frame_bytes = audio->ep_in_sz;
1428 uint8_t* dst = audio->lin_buf_in.data();
1431 if (n < frame_bytes) memset(dst + n, 0, frame_bytes - n);
1440 if (xferred_bytes > 0)
1442 (
int)xferred_bytes);
1444 rx_done_cb_(
this, rhport, audio, (uint16_t)xferred_bytes);
1446 audio->lin_buf_out.data(), audio->ep_out_sz);
1464 if (audio->ep_fb != 0) {
1466 uint32_t
const interval =
1467 1UL << (audio->feedback.frame_shift - hs_adjust);
1468 if (0 == (frame_count & (interval - 1))) {
1470 audio->feedback.frame_shift);
1491 memcpy(cb, &rate, 4);
1498 uint16_t cnt = (uint16_t)rates.size();
1499 memcpy(cb, &cnt, 2);
1500 for (
size_t i = 0; i < rates.size(); i++) {
1501 uint32_t r = rates[i];
1503 memcpy(cb + 2 + i * 12, &r, 4);
1504 memcpy(cb + 2 + i * 12 + 4, &r, 4);
1505 memcpy(cb + 2 + i * 12 + 8, &z, 4);
1508 rhport, p_request, cb,
1509 (uint16_t)(2 + rates.size() * 12));
1514 memcpy(cb, &cnt, 2);
1515 memcpy(cb + 2, &rate, 4);
1516 memcpy(cb + 6, &rate, 4);
1517 memcpy(cb + 10, &z, 4);
1533 cb[0] =
isMute(channel) ? 1 : 0;
1544 int16_t vmin = -25600, vmax = 0, vres = 256;
1545 memcpy(cb + 0, &cnt, 2);
1546 memcpy(cb + 2, &vmin, 2);
1547 memcpy(cb + 4, &vmax, 2);
1548 memcpy(cb + 6, &vres, 2);
1559 uint8_t func_id = 0;
1560 uint8_t* cb =
audiod_fct_[func_id].ctrl_buf.data();
1639 return (entityID != 0)
1665 uint8_t
const* p_desc =
1670 uint8_t
const* p_desc_end =
descU16(p_desc + 6) + p_desc;
1675 while (p_desc_end - p_desc > 0) {
1676 if (p_desc[3] == entityID)
1693 uint8_t
const* p_desc_end =
1698 p_desc +=
descU16(p_desc + 6);
1702 while (p_desc_end - p_desc > 0) {
1721 uint8_t
const* p_desc_end =
audiod_fct_[i].p_desc +
1726 while (p_desc_end - p_desc > 0) {
1740 uint8_t
const* p_desc) {
1745 if (audio->sample_rate_tx == 0)
1757 audio->n_channels_tx = p_desc[10];
1758 audio->format_type_tx = (audio_format_type_t)p_desc[5];
1765 p_desc[3] == AUDIO_FORMAT_TYPE_I) {
1766 audio->n_bytes_per_sample_tx = p_desc[4];
1772 if (audio->n_channels_tx == 0) audio->n_channels_tx =
config_.
channels;
1773 if (audio->n_bytes_per_sample_tx == 0)
1775 if (audio->format_type_tx == 0) audio->format_type_tx = AUDIO_FORMAT_TYPE_I;
1787 uint8_t
const** pp_desc_int) {
1788 if (audio->p_desc) {
1790 uint8_t
const* p_desc_end =
1794 uint8_t
const* p_desc =
descNext(audio->p_desc);
1795 p_desc +=
descU16(p_desc + 6);
1800 while (p_desc_end - p_desc > 0) {
1807 *pp_desc_int = p_desc;
1827 uint8_t
const** pp_desc_int) {
1846 uint8_t func_id, idxItf;
1847 uint8_t
const* dummy;
1851 if (!
backend().controlTransfer(
1852 rhport, p_request, &
audiod_fct_[func_id].alt_setting[idxItf], 1))
1855 LOGI(
" Get itf: %u - current alt: %u", itf,
1862 bool apply_correction =
1865 if (apply_correction) {
1866 uint8_t* fb = (uint8_t*)audio->fb_buf.data();
1869 *(fb++) = (audio->feedback.value >> 2) & 0xFF;
1870 *(fb++) = (audio->feedback.value >> 10) & 0xFF;
1871 *(fb++) = (audio->feedback.value >> 18) & 0xFF;
1874 audio->fb_buf[0] = audio->feedback.value;
1892 (uint8_t*)audio->fb_buf.data(),
1893 apply_correction ? 3 : 4);
1897 void closeEpIn(uint8_t rhport, audiod_function_t* audio, uint8_t itf,
1899 if (!
isEpInEnabled() || audio->ep_in_as_intf_num != itf)
return;
1900 audio->ep_in_as_intf_num = 0;
1907 audio->packet_sz_tx[0] = 0;
1908 audio->packet_sz_tx[1] = 0;
1909 audio->packet_sz_tx[2] = 0;
1914 void closeEpOut(uint8_t rhport, audiod_function_t* audio, uint8_t itf,
1916 if (!
isEpOutEnabled() || audio->ep_out_as_intf_num != itf)
return;
1917 audio->ep_out_as_intf_num = 0;
1918 if (!
backend().usesIsoAlloc()) {
1940 memset(&audio->feedback, 0,
sizeof(audio->feedback));
1948 if (
backend().usesIsoAlloc()) {
1962 void openEpIn(uint8_t rhport, audiod_function_t* audio, uint8_t itf,
1964 uint8_t
const* p_desc_for_params) {
1966 audio->ep_in_as_intf_num = itf;
1968 if (audio->ep_in_sz == 0)
return;
1975 if (first_pkt > audio->ep_in_sz) first_pkt = audio->ep_in_sz;
1976 audio->lin_buf_in.assign(audio->ep_in_sz, 0);
1978 audio->lin_buf_in.data(), first_pkt);
1983 void openEpOut(uint8_t rhport, audiod_function_t* audio, uint8_t itf,
1986 audio->ep_out_as_intf_num = itf;
1988 if (audio->ep_out_sz == 0)
return;
1992 if (audio->lin_buf_out.size() < audio->ep_out_sz)
1993 audio->lin_buf_out.assign(audio->ep_out_sz, 0);
2003 audio->feedback.frame_shift = desc_ep.
bInterval - 1;
2010 audio_feedback_params_t fb_param = {};
2011 fb_param.method = AUDIO_FEEDBACK_METHOD_FIFO_COUNT;
2015 audio->feedback.compute_method = fb_param.method;
2018 audio->feedback.format_correction =
2022 audio->feedback.min_value = ((fb_param.sample_freq - 1) / frame_div) << 16;
2023 audio->feedback.max_value = (fb_param.sample_freq / frame_div + 1) << 16;
2025 switch (fb_param.method) {
2026 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FIXED:
2027 case AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT:
2028 case AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2:
2030 fb_param.frequency.mclk_freq);
2032 case AUDIO_FEEDBACK_METHOD_FIFO_COUNT: {
2035 if (fifo_depth == 0) fifo_depth = 1;
2036 uint16_t fifo_lvl_thr = fifo_depth / 2;
2037 audio->feedback.compute.fifo_count.fifo_lvl_thr = fifo_lvl_thr;
2045 audio->feedback.compute.fifo_count.fifo_lvl_avg =
2046 ((uint32_t)fifo_lvl_thr) << 8;
2048 ((fb_param.sample_freq / 100) << 16) / (frame_div / 100);
2049 audio->feedback.compute.fifo_count.nom_value = nominal;
2050 audio->feedback.compute.fifo_count.rate_const[0] =
2051 (uint16_t)((audio->feedback.max_value - nominal) / fifo_lvl_thr);
2052 audio->feedback.compute.fifo_count.rate_const[1] =
2053 (uint16_t)((nominal - audio->feedback.min_value) / fifo_lvl_thr);
2055 audio->feedback.compute.fifo_count.rate_const[0] /= 8;
2056 audio->feedback.compute.fifo_count.rate_const[1] /= 8;
2066 uint8_t func_id, uint8_t itf, uint8_t alt) {
2067 uint8_t
const* p_desc = audio->p_desc;
2068 uint8_t
const* p_desc_end =
2070 LOGD(
" openEPs: p_desc=%p end=%p len=%u itf=%u alt=%u",
2071 p_desc, p_desc_end, audio->desc_length, itf, alt);
2073 while (p_desc_end - p_desc > 0) {
2077 uint8_t
const* p_desc_for_params =
2079 uint8_t foundEPs = 0;
2081 LOGD(
" matched itf=%u alt=%u nEps=%u", itf, alt, nEps);
2083 while (foundEPs < nEps && (p_desc_end - p_desc > 0)) {
2084 LOGD(
" scan: type=0x%02x len=%u offset=%d",
2085 p_desc[1], p_desc[0], (
int)(p_desc - audio->p_desc));
2089 LOGD(
" activating ep=0x%02x type=%u...",
2092 LOGD(
" activateEndpoint FAILED");
2096 LOGD(
" activated OK");
2105 desc_ep.
usage == 0x00)
2106 openEpIn(rhport, audio, itf, desc_ep, p_desc_for_params);
2120 if (foundEPs != nEps)
return true;
2138 LOGD(
"SET_ITF itf=%u alt=%u [start]", itf, alt);
2140 uint8_t func_id, idxItf;
2141 uint8_t
const* p_desc;
2144 LOGD(
" AS interface %u not found", itf);
2148 LOGD(
" found func=%u idx=%u", func_id, idxItf);
2154 closeEpIn(rhport, audio, itf, p_request);
2158 audio->alt_setting[idxItf] = alt;
2165 bool enable_sof =
false;
2181 return value != 0 && (value & (value - 1)) == 0;
2186 while ((value >>= 1u) != 0u) result++;
2191 uint32_t mclk_freq) {
2199 uint32_t
const n_frame = (1UL << audio->feedback.frame_shift);
2201 if ((((1UL << k) * sample_freq / mclk_freq) + 1) > n_frame) {
2202 LOGE(
" UAC2 feedback interval too small");
2207 if ((mclk_freq % sample_freq) == 0 &&
2209 audio->feedback.compute_method =
2210 AUDIO_FEEDBACK_METHOD_FREQUENCY_POWER_OF_2;
2211 audio->feedback.compute.power_of_2 =
2212 (uint8_t)(16 - (audio->feedback.frame_shift - 1) -
2214 }
else if (audio->feedback.compute_method ==
2215 AUDIO_FEEDBACK_METHOD_FREQUENCY_FLOAT) {
2216 audio->feedback.compute.float_const =
2217 (float)sample_freq / (
float)mclk_freq *
2218 (1UL << (16 - (audio->feedback.frame_shift - 1)));
2220 audio->feedback.compute.fixed.sample_freq = sample_freq;
2221 audio->feedback.compute.fixed.mclk_freq = mclk_freq;
2228 if (audio->format_type_tx != AUDIO_FORMAT_TYPE_I)
return false;
2229 if (!audio->n_channels_tx)
return false;
2230 if (!audio->n_bytes_per_sample_tx)
return false;
2231 if (!audio->interval_tx)
return false;
2232 if (!audio->sample_rate_tx)
return false;
2235 audio->tx_sample_acc = 0;
2238 const uint8_t interval =
2239 full_speed ? audio->interval_tx : 1 << (audio->interval_tx - 1);
2241 const uint16_t sample_normimal = (uint16_t)(audio->sample_rate_tx *
2242 interval / (full_speed ? 1000 : 8000));
2243 const uint16_t sample_reminder = (uint16_t)(audio->sample_rate_tx *
2244 interval % (full_speed ? 1000 : 8000));
2246 const uint16_t packet_sz_tx_min =
2247 (uint16_t)((sample_normimal - 1) * audio->n_channels_tx *
2248 audio->n_bytes_per_sample_tx);
2249 const uint16_t packet_sz_tx_norm =
2250 (uint16_t)(sample_normimal * audio->n_channels_tx *
2251 audio->n_bytes_per_sample_tx);
2252 const uint16_t packet_sz_tx_max =
2253 (uint16_t)((sample_normimal + 1) * audio->n_channels_tx *
2254 audio->n_bytes_per_sample_tx);
2257 if (packet_sz_tx_max > audio->ep_in_sz)
return false;
2260 if (sample_reminder) {
2263 audio->packet_sz_tx[0] = packet_sz_tx_norm;
2264 audio->packet_sz_tx[1] = packet_sz_tx_norm;
2265 audio->packet_sz_tx[2] = packet_sz_tx_max;
2269 audio->packet_sz_tx[0] = packet_sz_tx_min;
2270 audio->packet_sz_tx[1] = packet_sz_tx_norm;
2271 audio->packet_sz_tx[2] = packet_sz_tx_max;
2283 if (audio->sample_rate_tx == 0 || audio->n_channels_tx == 0 ||
2284 audio->n_bytes_per_sample_tx == 0) {
2286 return audio->ep_in_sz;
2289 const uint32_t denom = full_speed ? 1000u : 8000u;
2290 const uint8_t iv = audio->interval_tx ? audio->interval_tx : 1;
2291 const uint32_t interval = full_speed ? iv : (1u << (iv - 1));
2293 audio->tx_sample_acc += audio->sample_rate_tx * interval;
2294 const uint32_t samples = audio->tx_sample_acc / denom;
2295 audio->tx_sample_acc -= samples * denom;
2298 samples * audio->n_channels_tx * audio->n_bytes_per_sample_tx;
2299 if (bytes > audio->ep_in_sz) bytes = audio->ep_in_sz;
2300 return (uint16_t)bytes;
#define LOGW(...)
Definition AudioLoggerIDF.h:29
#define LOGI(...)
Definition AudioLoggerIDF.h:28
#define LOGD(...)
Definition AudioLoggerIDF.h:27
#define LOGE(...)
Definition AudioLoggerIDF.h:30
#define USB_DESCR_MAX_LEN
Definition USBAudioDeviceBase.h:47
RxTxMode
The Microcontroller is the Audio Source (TX_MODE) or Audio Sink (RX_MODE). RXTX_MODE is Source and Si...
Definition AudioTypes.h:26
@ RXTX_MODE
Definition AudioTypes.h:26
@ TX_MODE
Definition AudioTypes.h:26
@ RX_MODE
Definition AudioTypes.h:26