Skip to content

Audio #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 66 commits into
base: audio
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
dc9e6b2
DRAFT audio support for rp2040
pschatzmann Sep 25, 2024
0b003e8
Audio examples
pschatzmann Sep 27, 2024
0147cdc
Audio compile errors
pschatzmann Sep 27, 2024
a52c990
getInterfaceDescriptor
pschatzmann Sep 28, 2024
e6f99ad
Cleanup audio_config.h
pschatzmann Sep 28, 2024
1aad41b
Cleanup audio_config
pschatzmann Sep 28, 2024
8874a3b
Audio Stream example
pschatzmann Sep 28, 2024
e27ebe1
Additional checks
pschatzmann Sep 30, 2024
27d26ed
Correct Device Descriptor Logic
pschatzmann Sep 30, 2024
7ea9d0b
DRAFT microphone
pschatzmann Oct 9, 2024
347acf0
Final microphone corrections
pschatzmann Oct 9, 2024
6dafc4d
set CDC active by default
pschatzmann Oct 9, 2024
29d1160
Restrict Audio to RP2040
pschatzmann Oct 9, 2024
bd679aa
Non working DRAFT speaker
pschatzmann Oct 9, 2024
5478497
Non working DRAFT speaker
pschatzmann Oct 9, 2024
a1becac
Blinking support
pschatzmann Oct 10, 2024
8ee769d
Non working DRAFT speaker
pschatzmann Oct 10, 2024
a8e65e1
Extend configuration to other platforms
pschatzmann Oct 11, 2024
98faa62
Allign descriptor
pschatzmann Oct 11, 2024
a030442
Prevent NPE
pschatzmann Oct 11, 2024
a63f1b1
Status timing
pschatzmann Oct 11, 2024
a0ff232
Additional checks on begin
pschatzmann Oct 11, 2024
87bd132
doc for Descriptors
pschatzmann Oct 11, 2024
ecd394f
Update descriptor
pschatzmann Oct 11, 2024
6820010
Remove getDeviceDescriptor()
pschatzmann Oct 11, 2024
ac6bb49
Update examples
pschatzmann Oct 11, 2024
4193857
Fix broken CDC in Speaker
pschatzmann Oct 11, 2024
1ed7586
Correct log level
pschatzmann Oct 11, 2024
ac2482b
Activate TU_VERIFY
pschatzmann Oct 13, 2024
e0ced34
RP2040 dcd_rp2040 patch
pschatzmann Oct 13, 2024
6b45ee0
Added support for logging
pschatzmann Oct 13, 2024
2ab548d
config allow defined in platformio
pschatzmann Oct 13, 2024
99ae776
Cleanup redundant helper methods
pschatzmann Oct 13, 2024
63fdd5d
Delete commented out methods
pschatzmann Oct 13, 2024
0d128f4
Provide api to check for status
pschatzmann Oct 13, 2024
482f941
Move global methods to end of cpp file
pschatzmann Oct 13, 2024
d96b0c1
Logging: added flush
pschatzmann Oct 13, 2024
71a88a3
Roll back unnecesary changes
pschatzmann Oct 13, 2024
f21d8ba
cdc_rp2040.c patch
pschatzmann Oct 13, 2024
9da74ef
remove .vscode
pschatzmann Oct 13, 2024
81e87bd
add vscode to gitignore
pschatzmann Oct 13, 2024
ef9a12c
RP3040 support for dcd_edpt_iso_alloc() and dcd_edpt_iso_activate()
pschatzmann Oct 14, 2024
4c5d086
cdc_rp2030.c misspelled function
pschatzmann Oct 14, 2024
8b6c3da
rp2040 driver cleanup naming
pschatzmann Oct 14, 2024
df38021
dec_rp2040: casts to prevent warnings
pschatzmann Oct 15, 2024
85b571b
Draft Headset
pschatzmann Oct 15, 2024
20abe65
Support for all platforms
pschatzmann Oct 16, 2024
ea636b3
Adapt Platform Config
pschatzmann Oct 16, 2024
ad597a3
ESP32 option CFG_FORCE_DEFAULT_AUDIO_CONFIG
pschatzmann Oct 16, 2024
40944cb
Headset working w/o CDC
pschatzmann Oct 16, 2024
b92866c
Update examples
pschatzmann Oct 16, 2024
89dda26
Interface Descriptor additional checks
pschatzmann Oct 17, 2024
e9f853d
Support for setConfigurationBufferSize
pschatzmann Oct 17, 2024
d8696a5
fix broken total_len
pschatzmann Oct 17, 2024
e730f7f
Microphone Stream example
pschatzmann Oct 18, 2024
498dbde
Support for CFG_TUD_AUDIO_FUNC_1_DESC_LEN_API
pschatzmann Oct 25, 2024
b4846ca
tinyusb_audio_descriptor_length
pschatzmann Oct 25, 2024
07164dc
tinyusb_audio_descriptor_length
pschatzmann Oct 25, 2024
2b97d53
tinyusb_audio_descriptor_length
pschatzmann Oct 25, 2024
ff6ba8b
move to 3.4.0
pschatzmann Nov 4, 2024
78791f6
Merge branch 'Audio1' into Audio
pschatzmann Jan 4, 2025
688f391
microphone example
pschatzmann Jan 5, 2025
51ff7b8
audio_microphone.ino
pschatzmann Jan 5, 2025
c5266ee
Support manuel feedback
pschatzmann Jan 9, 2025
1f77496
rp2040 i2s example
pschatzmann Jan 9, 2025
74a903a
BITS_PER_SAMPLE
pschatzmann Mar 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
.idea
platformio.ini
.pio/
.vscode/
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Supported device class drivers are:
- Mass Storage Class (MSC): with multiple LUNs
- Musical Instrument Digital Interface (MIDI)
- Video (UVC): work in progress
- Audio (UAC): work in progress
- WebUSB with vendor specific class

### Host Stack
Expand Down
78 changes: 78 additions & 0 deletions examples/Audio/audio_headset/audio_headset.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
Copyright (c) 2024 Phl Schatzmann

A combination of a microphone and headset at the same time.
Unfortunately it will only work when Serial output is not active

*********************************************************************/

#include "Adafruit_TinyUSB.h"

Adafruit_USBD_Audio usb;
size_t sample_count_mic = 0;
size_t sample_count_spk = 0;

// Microphone: generate data for USB
size_t readCB(uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
int16_t* data16 = (int16_t*)data;
size_t samples = len / sizeof(int16_t);
size_t result = 0;
// generate random stereo data
for (int j = 0; j < samples; j+=2) {
data16[j] = random(-32000, 32000);
data16[j+1] = random(-32000, 32000);;
result += sizeof(int16_t)*2;
sample_count_mic += 2;
}
return result;
}

// Speaker: receive data from USB and write them to the final destination
size_t writeCB(const uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
int16_t* data16 = (int16_t*)data;
size_t samples = len / sizeof(int16_t);
sample_count_spk += samples;
return len;
}

void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}

Serial.begin(115200);

// Start USB device as both Audio Source and Sink
usb.setReadCallback(readCB);
usb.setWriteCallback(writeCB);
usb.begin(44100, 2, 16);

// If already enumerated, additional class driver begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}

void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// use LED do display status
if (usb.updateLED()){
Serial.print("Total Microphone samples: ");
Serial.print(sample_count_mic);
Serial.print(" / Speaker samples: ");
Serial.print(sample_count_spk);
Serial.print(" / Sample rate: ");
Serial.println(usb.rate());
}
}
64 changes: 64 additions & 0 deletions examples/Audio/audio_microphone/audio_microphone.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
Copyright (c) 2024 Phl Schatzmann

This example generates white noise that you can output on your PC

*********************************************************************/

#include "Adafruit_TinyUSB.h"

Adafruit_USBD_Audio usb;
size_t sample_count = 0;

size_t readCB(uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
int16_t* data16 = (int16_t*)data;
size_t samples = len / sizeof(int16_t);
size_t result = 0;
// generate random data
for (int j = 0; j < samples; j++) {
data16[j] = random(-32000, 32000);
result += sizeof(int16_t);
}
return result;
}

void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}

Serial.begin(115200);
//while(!Serial); // wait for serial

// Start USB device as Audio Source
usb.setReadCallback(readCB);
usb.begin(44100, 2, 16);

// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}

}

void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// use LED do display status
if (usb.updateLED()){
Serial.print("Total samples: ");
Serial.print(sample_count);
Serial.print(" / Sample rate: ");
Serial.println(usb.rate());
}
}
56 changes: 56 additions & 0 deletions examples/Audio/audio_microphone_stream/audio_microphone_stream.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
Copyright (c) 2024 Phl Schatzmann

This example generates a sawtooth that you can output on your PC
We use the AudioTools to generate the data input.

We could use the callback function here as well, but we demo how
to integrate with a (fast) Arduino Stream.

*********************************************************************/

#include "Adafruit_TinyUSB.h"
#include "AudioTools.h" // https://github.com/pschatzmann/arduino-audio-tools

Adafruit_USBD_Audio usb;
AudioInfo info(44100, 2, 16);
SawToothGenerator<int16_t> sawtooth;
GeneratedSoundStream<int16_t> sawthooth_stream(sawtooth);

void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}

Serial.begin(115200);
//while(!Serial); // wait for serial

// generate 493 hz (note B4)
sawtooth.begin(info, 493.0f);

// Start USB device as Audio Source
usb.setInput(sawthooth_stream);
usb.begin(info.sample_rate, info.channels, info.bits_per_sample);

// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}

void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif
// optional: use LED do display status
usb.updateLED();
}
61 changes: 61 additions & 0 deletions examples/Audio/audio_speaker/audio_speaker.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
Copyright (c) 2024 Phl Schatzmann

This example counts the 'received' samples and prints them on
Serial (via CDC)

*********************************************************************/

#include "Adafruit_TinyUSB.h"

Adafruit_USBD_Audio usb;
size_t sample_count = 0;

size_t writeCB(const uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
int16_t* data16 = (int16_t*)data;
size_t samples = len / sizeof(int16_t);
sample_count += samples;
return len;
}

void setup() {
// Manual begin() is required on core without built-in support e.g. mbed rp2040
if (!TinyUSBDevice.isInitialized()) {
TinyUSBDevice.begin(0);
}

Serial.begin(115200);
//while(!Serial); // wait for serial

// Start USB device as Audio Sink
usb.setWriteCallback(writeCB);
usb.begin(44100, 2, 16);

// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}

}

void loop() {
#ifdef TINYUSB_NEED_POLLING_TASK
// Manual call tud_task since it isn't called by Core's background
TinyUSBDevice.task();
#endif

// use LED do display status
if (usb.updateLED()){
Serial.print("Total samples: ");
Serial.print(sample_count);
Serial.print(" / Sample rate: ");
Serial.println(usb.rate());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/*********************************************************************
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!

MIT license, check LICENSE for more information
Copyright (c) 2024 Phl Schatzmann

This example uses a Rasperry Pico to send the output to i2s. To prevent
any underruns or overruns we take care of the feedback ourself.

*********************************************************************/
#include "Adafruit_TinyUSB.h"
#include "AudioTools.h"
#include "AudioTools/Concurrency/RP2040.h"

AudioInfo info(44100, 2, 16);
Adafruit_USBD_Audio usb;
BufferRP2040 buffer(256, 20);
QueueStream queue(buffer);
I2SStream i2s;
StreamCopy copier(i2s, queue);

size_t writeCB(const uint8_t* data, size_t len, Adafruit_USBD_Audio& ref) {
usb.setFeedbackPercent(buffer.size()*100 / buffer.available());
return queue.write(data, len);
}

void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
//while(!Serial); // wait for serial
delay(1000);
Serial.println("starting...");
// start queue
queue.begin(80);

// Start USB device as Audio Sink w/o automatic feedback
usb.setFeedbackMethod(AUDIO_FEEDBACK_METHOD_DISABLED);
usb.setWriteCallback(writeCB);
if (!usb.begin(info.sample_rate, info.channels, info.bits_per_sample)){
Serial.println("USB error");
}

// If already enumerated, additional class driverr begin() e.g msc, hid, midi won't take effect until re-enumeration
if (TinyUSBDevice.mounted()) {
TinyUSBDevice.detach();
delay(10);
TinyUSBDevice.attach();
}
}

void loop() {
usb.updateLED();
}

void setup1(){
//start i2s
auto cfg = i2s.defaultConfig(TX_MODE);
cfg.copyFrom(info);
cfg.buffer_size = 256;
cfg.buffer_count = 3;
if (!i2s.begin(cfg)){
Serial.print("i2s error");
}
}

void loop1() {
copier.copy();
}
4 changes: 4 additions & 0 deletions src/Adafruit_TinyUSB.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
#include "arduino/video/Adafruit_USBD_Video.h"
#endif

#if CFG_TUD_AUDIO
#include "arduino/audio/Adafruit_USBD_Audio.h"
#endif

// Initialize device hardware, stack, also Serial as CDC
// Wrapper for TinyUSBDevice.begin(rhport)
void TinyUSB_Device_Init(uint8_t rhport);
Expand Down
2 changes: 1 addition & 1 deletion src/arduino/Adafruit_TinyUSB_API.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,4 +98,4 @@ __attribute__((used)) int CFG_TUSB_DEBUG_PRINTF(const char *__restrict format,

} // extern C

#endif // CFG_TUD_ENABLED || CFG_TUH_ENABLED
#endif // CFG_TUD_ENABLED || CFG_TUH_ENABLED
Loading