This commit is contained in:
2026-02-12 21:00:02 -08:00
parent 77f8236347
commit 8bdbf227ca
1141 changed files with 1010880 additions and 2 deletions

View File

@@ -0,0 +1,4 @@
These folder contains some work in progress, experiments and tests, so do not expect them to work!
But it might still serve as a source of inspiration...

View File

@@ -0,0 +1,67 @@
/**
* @file basic-a2dp-audiovs1053.ino
* @brief A2DP Sink with output to vs1053. The vs1053 expects encoded data so we encode the stream
* to a WAV file
*
* @author Phil Schatzmann
* @copyright GPLv3
*/
// install https://github.com/pschatzmann/arduino-vs1053.git
#include "AudioTools.h"
#include "AudioTools/AudioLibs/VS1053Stream.h"
#include "BluetoothA2DPSink.h"
BluetoothA2DPSink a2dp_sink;
VS1053Stream out; // output
VS1053Config cfg;
// Write data to VS1053
void read_data_stream(const uint8_t *data, uint32_t bytes) {
int samples = bytes / sizeof(int16_t);
// split up writes to max 512 samples
writeData<int16_t>(&out, (int16_t*) data, samples, 512);
}
// for esp_a2d_audio_state_t see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/bluetooth/esp_a2dp.html#_CPPv421esp_a2d_audio_state_t
void audio_state_changed(esp_a2d_audio_state_t state, void *ptr){
Serial.println(a2dp_sink.to_str(state));
switch(state){
case ESP_A2D_AUDIO_STATE_STOPPED:
case ESP_A2D_AUDIO_STATE_REMOTE_SUSPEND:
// add new wav header
out.end();
out.begin(cfg);
break;
}
}
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// setup VS1053
cfg = out.defaultConfig();
cfg.sample_rate = 44100;
cfg.channels = 2;
cfg.bits_per_sample = 16;
// Use your custom pins or define in AudioCodnfig.h
//cfg.cs_pin = VS1053_CS;
//cfg.dcs_pin = VS1053_DCS;
//cfg.dreq_pin = VS1053_DREQ;
// cfg.reset_pin = //VS1053_RESET;
out.begin(cfg);
// register callbacks
a2dp_sink.set_stream_reader(read_data_stream, false);
a2dp_sink.set_on_audio_state_changed(audio_state_changed);
// Start Bluetooth Audio Receiver
a2dp_sink.set_auto_reconnect(false);
a2dp_sink.start("a2dp-vs1053");
}
void loop() {
}

View File

@@ -0,0 +1,38 @@
/**
* @file communications-ble-client-send.ino
* @author Phil Schatzmann
* @brief Sending audio via BLE: the client acts as audio source
* Please not that the thruput in this scenario is very limited!
* @version 0.1
* @date 2022-11-04
*
* @copyright Copyright (c) 2022
*/
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecADPCM.h" // https://github.com/pschatzmann/adpcm
#include "AudioTools/Sandbox/BLE/AudioBLE.h"
AudioInfo info(16000, 1, 16);
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
Throttle throttle(sound);
AudioBLEClient ble;
ADPCMEncoder adpcm(AV_CODEC_ID_ADPCM_IMA_WAV);
EncodedAudioStream encoder(&ble, &adpcm);
StreamCopy copier(encoder, throttle);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
sineWave.begin(info, N_B4);
throttle.begin(info);
encoder.begin(info);
ble.begin("ble-send", 60 * 10);
Serial.println("started...");
}
void loop() { copier.copy(); }

View File

@@ -0,0 +1,39 @@
/**
* @file communications-ble-server-receive.ino
* @author Phil Schatzmann
* @brief Receiving audio via BLE: the server acts as audio sink
* Please not that the thruput in this scenario is very limited!
* @version 0.1
* @date 2022-11-04
*
* @copyright Copyright (c) 2022
*/
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecADPCM.h" // https://github.com/pschatzmann/adpcm
#include "AudioTools/Sandbox/BLE/AudioBLE.h"
//#include "AudioTools/AudioLibs/AudioBoardStream.h"
AudioInfo info(16000, 1, 16);
ADPCMDecoder adpcm(AV_CODEC_ID_ADPCM_IMA_WAV);
I2SStream i2s; // or AudioBoardStream ...
EncodedAudioStream decoder(&i2s, &adpcm);
AudioBLEServer ble;
StreamCopy copier(decoder, ble);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
decoder.begin(info);
auto cfg = i2s.defaultConfig();
cfg.copyFrom(info);
i2s.begin(cfg);
ble.begin("ble-receive");
}
void loop() {
copier.copy();
}

View File

@@ -0,0 +1,46 @@
/**
* @file communications-ble-client-receive.ino
* @author Phil Schatzmann
* @brief Receiving audio via BLE: The client acts as audio sink and is writing to I2S.
* This scenario works amazingly well!
* @version 0.1
* @date 2022-11-04
*
* @copyright Copyright (c) 2023
*/
#include "AudioTools.h"
//#include "AudioTools/AudioLibs/AudioBoardStream.h"
#include "AudioTools/AudioCodecs/CodecADPCM.h" // https://github.com/pschatzmann/adpcm
#include "AudioTools/Sandbox/BLE/AudioBLE.h"
AudioInfo info(44100, 2, 16);
AudioBLEClient ble;
I2SStream i2s;
ADPCMDecoder adpcm(AV_CODEC_ID_ADPCM_IMA_WAV);
EncodedAudioStream decoder(&i2s, &adpcm);
StreamCopy copier(decoder, ble);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
// start BLE client - wait at most 10 minutes
ble.begin("ble-receive", 60*10);
// start decoder
decoder.begin(info);
// start I2S
auto config = i2s.defaultConfig(TX_MODE);
config.copyFrom(info);
i2s.begin(config);
Serial.println("started...");
}
void loop() {
if (ble)
copier.copy();
}

View File

@@ -0,0 +1,41 @@
/**
* @file communications-ble-server-send.ino
* @author Phil Schatzmann
* @brief Sending audio via BLE: The server acts as audio source.
* This scenario works amazingly well!
* @version 0.1
* @date 2022-11-04
*
* @copyright Copyright (c) 2023
*/
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/CodecADPCM.h" // https://github.com/pschatzmann/adpcm
#include "AudioTools/Sandbox/BLE/AudioBLE.h"
AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t>
sineWave(32000); // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream<int16_t>
sound(sineWave); // Stream generated from sine wave
AudioBLEServer ble;
ADPCMEncoder adpcm(AV_CODEC_ID_ADPCM_IMA_WAV);
EncodedAudioStream encoder(&ble, &adpcm);
StreamCopy copier(encoder, sound);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
sineWave.begin(info, N_B4);
encoder.begin(info);
// ble.setAudioInfoActive(true);
ble.begin("ble-send");
}
void loop() {
if (ble.availableForWrite() > 0)
copier.copy();
}

View File

@@ -0,0 +1,22 @@
# ADS1015
![ADS1015](https://pschatzmann.github.io/arduino-audio-tools/doc/resources/ads1015.jpeg)
The ADS1015 is a 12 bit ADC which is connected via I2C.
### Pins:
| ADS1015 | ESP32
|---------|---------------
| VDD | 3.3
| GND | GND
| SCL | SCL GPIO22
| SDA | SDA GPIO21
| ADDR | GND
| ALRT | -
| A0 | Analog Source (e.g. Electic Guitar)
## Conclusion
The sampling rate is too low to be usefull.

View File

@@ -0,0 +1,68 @@
/**
* @file experiment-ads1015-serial.ino
* @author Phil Schatzmann
* @brief We can use the ADS1015 to provide analog signals. Unfortunatly it is not
* suited for audio because it is too slow.
* @version 0.1
* @date 2022-12-07
*
* @copyright Copyright (c) 2022
*
*/
#include "Wire.h"
#include "Adafruit_ADS1015.h"
#include "AudioTools.h"
const int sample_rate = 3300;
const int buffer_size = 50;
Adafruit_ADS1015 ads1015(0x48);
TimerAlarmRepeating sound_timer;
NBuffer<int16_t> buffer(buffer_size,3);
// callback to record the sound data into a buffer
void write_sample(void *ptr) {
sound_t sample = ads1015.readADC_Differential_0_1();
buffer.write(sample);
}
// Arduino Setup
void setup(void) {
Serial.begin(115200);
// setup microphone
ads1015.begin();
ads1015.setGain(GAIN_SIXTEEN); // GAIN_TWO GAIN_FOUR GAIN_EIGHT GAIN_SIXTEEN
// start the timer to record the data
long waitUs = 1000000 / sample_rate;
sound_timer.start(write_sample, waitUs, US);
}
void printSampleRate() {
static long next_time;
if (millis()>next_time){
next_time = next_time+1000;
Serial.print("sample rate: ");
Serial.println(buffer.sampleRate());
}
}
void printSamples() {
static sound_t array[50][2];
size_t len = buffer.readFrames(array);
for (int j=0;j<len;j++){
Serial.print(array[j][0]);
Serial.print(" ");
Serial.println(array[j][1]);
}
}
// Arduino loop - repeated processing
void loop() {
// copy sound data from samples to I2S
printSamples();
printSampleRate();
}

View File

@@ -0,0 +1,45 @@
/**
* @file receive.ino
* @author Phil Schatzmann
* @brief We receive text over audio with the help of the GWave library
* This is not working!
* @version 0.1
* @date 2022-12-14
*
* @copyright Copyright (c) 2022
*
*/
#include "AudioTools.h"
#include "Experiments/CodecGGWave.h" // https://github.com/ggerganov/ggwave-arduinop
#include "AudioTools/AudioLibs/AudioBoardStream.h" // https://github.com/pschatzmann/arduino-audio-driver.git
int sample_rate = GGWAVE_DEFAULT_SAMPLE_RATE;
int channels = 1;
AudioBoardStream in(AudioKitEs8388V1); // or e.g. I2SStream
GGWaveDecoder dec;
EncodedAudioStream encoder_stream(Serial, dec); // decode and write to I2S - ESP Now is limited to 256 bytes
StreamCopy copier(encoder_stream, in, GGWAVE_DEFAULT_BYTES_PER_FRAME); // copy mic to tfl
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// audio input
auto config = in.defaultConfig(RX_MODE);
config.sample_rate = sample_rate;
config.channels = channels;
config.input_device = ADC_INPUT_LINE2; // microphone
in.begin(config);
// setup codec
auto config_dec = encoder_stream.defaultConfig();
config_dec.sample_rate = sample_rate;
config.channels = channels;
encoder_stream.begin(config);
}
void loop() {
copier.copy();
}

View File

@@ -0,0 +1,44 @@
/**
* @file send.ino
* @author Phil Schatzmann
* @brief We transmit text over audio with the help of the GWave library
* This is not working!
* @version 0.1
* @date 2022-12-14
*
* @copyright Copyright (c) 2022
*
*/
#include "AudioTools.h"
#include "Experiments/CodecGGWave.h" // https://github.com/ggerganov/ggwave-arduinop
#include "AudioTools/AudioLibs/AudioBoardStream.h" // https://github.com/pschatzmann/arduino-audio-driver.git
int sample_rate = GGWAVE_DEFAULT_SAMPLE_RATE;
int channels = 1;
AudioBoardStream out(AudioKitEs8388V1); // or AudioBoardStream
GGWaveEncoder enc;
EncodedAudioStream encoder_stream(&out, &enc); // decode and write to I2S - ESP Now is limited to 256 bytes
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// audio output
auto config = out.defaultConfig(TX_MODE);
config.sample_rate = sample_rate;
config.channels = channels;
out.begin(config);
// setup codec
auto config_dec = encoder_stream.defaultConfig();
config_dec.sample_rate = sample_rate;
config.channels = channels;
encoder_stream.begin(config);
}
void loop() {
encoder_stream.println("this is a test");
delay(5000);
}

View File

@@ -0,0 +1,60 @@
/**
* @file send-hdlc-receive.ino
* @author Phil Schatzmann
* @brief Sending and receiving audio via Serial. You need to connect the RX pin
* with the TX pin!
* The sine wave generator is providing the data as fast as possible, therefore we
* throttle on the sending side to prevent that the receiver is getting the data
* too fast.
*
* To make sure that we transmit only valid data we use HDLC.
*
* @version 0.1
* @date 2022-03-09
*
* @copyright Copyright (c) 2022
*/
#include "AudioTools.h"
#include "AudioTools/Communication/HDLCStream.h"
// #include "AudioTools/AudioLibs/AudioBoardStream.h"
AudioInfo info(8000, 1, 16);
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
Throttle throttle(sound);
I2SStream out;
HDLCStream hdlc_enc(Serial, 256);
HDLCStream hdlc_dec(Serial, 256);
StreamCopy copierOut(hdlc_enc, throttle, 256);
StreamCopy copierIn(out, hdlc_dec, 256);
void setup() {
Serial2.begin(115200);
AudioLogger::instance().begin(Serial2, AudioLogger::Warning);
hdlc_enc.begin();
hdlc_dec.begin();
// Note the format for setting a serial port is as follows:
// Serial.begin(baud-rate, protocol, RX pin, TX pin);
Serial.begin(1000000, SERIAL_8N1);
// Setup sine wave
sineWave.begin(info, N_B4);
throttle.begin(info);
// start I2S
Serial.println("starting I2S...");
auto config = out.defaultConfig(TX_MODE);
config.copyFrom(info);
out.begin(config);
Serial.println("started...");
}
void loop() {
// copy to serial
copierOut.copy();
// copy from serial
copierIn.copy();
}

View File

@@ -0,0 +1,34 @@
/**
* We use the default Arduino SPI API to send/write the data as SPI Master.
* For a sample rate of 44100 with 2 channels and 16 bit data you need to be
* able to transmit faster then 44100 * 2 channels * 2 bytes = 176400 bytes per
* second. Using a SPI communication this gives 176400 * 8 =
* 1'411'200 bps!
*
* Untested DRAFT implementation!
*/
#include <SPI.h>
#include "AudioTools.h"
const size_t BUFFER_SIZE = 1024;
const int SPI_CLOCK = 2000000; // 2 MHz
AudioInfo info(44100, 2, 16); //
Vector<uint8_t> buffer(BUFFER_SIZE);
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
void setup() {
SPI.begin();
sineWave.begin(info, N_B4);
SPI.beginTransaction(SPISettings(SPI_CLOCK, MSBFIRST, SPI_MODE0));
}
void loop() {
// get data
size_t result = sound.readBytes(&buffer[0], buffer.size());
// transmit data
SPI.transfer(&buffer[0], result);
//SPI.endTransaction();
}

View File

@@ -0,0 +1,39 @@
/***
* We use the ESP32DMASPISlave library to implement the SPI slave on the ESP32
* which receives the data
*
* Untested DRAFT implementation!
*/
#include <ESP32DMASPISlave.h>
#include "AudioTools.h"
const size_t BUFFER_SIZE = 1024;
uint8_t *dma_rx_buf;
ESP32DMASPI::Slave spi_slave;
AudioInfo info(44100, 2, 16); //
I2SStream out; // or replace with another output
void setup() {
Serial.begin(115200);
// setup I2S
auto cfg = out.defaultConfig(TX_MODE);
cfg.copyFrom(info);
//cfg.pin_bck = 14;
//cfg.pin_ws = 15;
//cfg.pin_data = 22;
// to use DMA buffer, use these methods to allocate buffer
dma_rx_buf = spi_slave.allocDMABuffer(BUFFER_SIZE);
spi_slave.setDataMode(SPI_MODE0); // default: SPI_MODE0
spi_slave.setMaxTransferSize(BUFFER_SIZE); // default: 4092 bytes
// begin() after setting
spi_slave.begin(); // default: HSPI (please refer README for pin assignments)
}
void loop() {
// start and wait to complete one BIG transaction
size_t received_bytes = spi_slave.transfer(nullptr, dma_rx_buf, BUFFER_SIZE);
out.write(dma_rx_buf, received_bytes);
}

View File

@@ -0,0 +1,48 @@
/***
* We use the RP2040 SPISlave to implement the SPI slave
* which receives the data
*
* Untested DRAFT implementation!
*/
#include <SPISlave.h>
AudioInfo info(44100, 2, 16); //
I2SStream out; // or replace with another output
// Wiring:
// Master RX GP0 <-> GP11 Slave TX
// Master CS GP1 <-> GP9 Slave CS
// Master CK GP2 <-> GP10 Slave CK
// Master TX GP3 <-> GP8 Slave RX
SPISettings spisettings(2000000, MSBFIRST, SPI_MODE0);
// Core 1 will be SPI slave
void recvCallback(uint8_t *data, size_t len) { out.write(data, len); }
void setup() {
Serial.begin(115200);
// setup I2S
auto cfg = out.defaultConfig(TX_MODE);
cfg.copyFrom(info);
// cfg.pin_bck = 14;
// cfg.pin_ws = 15;
// cfg.pin_data = 22;
out.begin(cfg);
// setup SPI
SPISlave.setRX(8);
SPISlave.setCS(9);
SPISlave.setSCK(10);
SPISlave.setTX(11);
// Hook our callbacks into the slave
SPISlave.onDataRecv(recvCallback);
SPISlave.begin(spisettings);
delay(1000);
Serial.println("SPISlave started");
}
void loop() {}

View File

@@ -0,0 +1,48 @@
/**
* @file streams-generator-freq.ino
* @brief Test frequency detection
* @author Phil Schatzmann
* @copyright GPLv3
**/
#include "AudioTools.h"
#include "Experiments/FrequencyDetection.h"
AudioInfo info(16000, 1, 16);
SineWaveGenerator<int16_t> sineWave(32000); // subclass of SoundGenerator with max amplitude of 32000
GeneratedSoundStream<int16_t> sound(sineWave); // Stream generated from sine wave
FrequncyZeroCrossingStream out; // or use FrequncyAutoCorrelationStream
StreamCopy copier(out, sound);
MusicalNotes notes; // copies sound into i2s
int idx = 0;
// Arduino Setup
void setup(void) {
// Open Serial
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
// start the analog output
out.begin(info);
// Setup sine wave
Serial.println("started...");
}
// Arduino loop - copy sound to out
void loop() {
float freq = notes.frequency(idx);
sineWave.begin(info, freq);
copier.copy();
// print result
Serial.print(notes.note(freq));
Serial.print(" ");
Serial.print(notes.frequency(idx));
Serial.print("->");
Serial.print(out.frequency(0));
Serial.print(" ");
Serial.println(notes.note(out.frequency(0)));
if (++idx >= notes.frequencyCount()) stop();
}

View File

@@ -0,0 +1,14 @@
const unsigned char g8_saw_raw[] = {
0x00, 0x00, 0xb5, 0x0b, 0x69, 0x17, 0x22, 0x23, 0xd3, 0x2e, 0x8b, 0x3a,
0x3e, 0x46, 0xf2, 0x51, 0x79, 0xaa, 0x29, 0xb6, 0xe3, 0xc1, 0x93, 0xcd,
0x4a, 0xd9, 0x02, 0xe5, 0xb3, 0xf0, 0x6b, 0xfc, 0x1f, 0x08, 0xd3, 0x13,
0x8c, 0x1f, 0x3b, 0x2b, 0xf8, 0x36, 0xa5, 0x42, 0x61, 0x4e, 0xdd, 0xa6,
0x98, 0xb2, 0x48, 0xbe, 0x00, 0xca, 0xb5, 0xd5, 0x69, 0xe1, 0x1e, 0xed,
0xd8, 0xf8, 0x84, 0x04, 0x42, 0x10, 0xf1, 0x1b, 0xa8, 0x27, 0x62, 0x33,
0x0e, 0x3f, 0xcd, 0x4a, 0x78, 0x56, 0x03, 0xaf, 0xb1, 0xba, 0x6c, 0xc6,
0x1e, 0xd2, 0xd3, 0xdd, 0x89, 0xe9, 0x3e, 0xf5, 0xf4, 0x00, 0xa6, 0x0c,
0x61, 0x18, 0x0e, 0x24, 0xcd, 0x2f, 0x78, 0x3b, 0x37, 0x47, 0xe2, 0x52,
0x6e, 0xab, 0x1a, 0xb7, 0xd6, 0xc2, 0x89, 0xce, 0x3c, 0xda, 0xf4, 0xe5,
0xa7, 0xf1, 0x5d, 0xfd
};
unsigned int g8_saw_raw_len = 124;

View File

@@ -0,0 +1,11 @@
const unsigned char g8_sine_raw[] = {
0x00, 0x00, 0xc1, 0x23, 0x93, 0x41, 0x7e, 0x54, 0x5e, 0x59, 0x6a, 0x4f,
0x3b, 0x38, 0xc0, 0x17, 0x46, 0xf3, 0xf6, 0xd0, 0x69, 0xb6, 0x26, 0xa8,
0x6d, 0xa8, 0x4b, 0xb7, 0x3a, 0xd2, 0xc2, 0xf4, 0x2c, 0x19, 0x67, 0x39,
0x14, 0x50, 0x7a, 0x59, 0xf9, 0x53, 0x8e, 0x40, 0x5f, 0x22, 0x86, 0xfe,
0xde, 0xda, 0x6f, 0xbd, 0x03, 0xab, 0xc1, 0xa6, 0x4b, 0xb1, 0xed, 0xc8,
0xb6, 0xe9, 0x2e, 0x0e, 0x53, 0x30, 0x69, 0x4a, 0x26, 0x58, 0x3d, 0x57,
0xd3, 0x47, 0x7e, 0x2c, 0xc1, 0x09, 0x66, 0xe5, 0x79, 0xc5, 0x3f, 0xaf,
0x7a, 0xa6, 0x89, 0xac, 0x83, 0xc0, 0xfc, 0xde
};
unsigned int g8_sine_raw_len = 92;

View File

@@ -0,0 +1,71 @@
#include "AudioTools.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
#include "g8-sine.h"
#include "g8-sine-long.h"
#include "g8-saw.h"
// sawtooth note g8 recorded at 96000
MemoryStream toneG8(g8_sine_raw, g8_sine_raw_len);
// playback at 24000 (4 times slower)
const AudioInfo info(24000,1,16);
AudioBoardStream i2s(AudioKitEs8388V1);
CsvOutput<int16_t> csv(Serial, 1);
//FilteredStream<int16_t, int16_t> filter(i2s, 1);
ResampleStream resample(csv); // replace with i2s
StreamCopy copier(resample, toneG8, 2048); // copies sound to out
int idx_max = 100;
int idx = idx_max;
MusicalNotes notes;
uint32_t timeout = 0;
void changeNote() {
const float from_tone = N_G8;
// e.g. 6271.93f / 16.35f * 4.0 = 0.01042741229
float step_size = notes.frequency(idx) / from_tone * 4.0f;
Serial.print("playing note: ");
Serial.print(notes.noteAt(idx));
Serial.print(" / step: ");
Serial.println(step_size);
resample.setStepSize(step_size);
idx--;
if (idx < 0) {
idx = idx_max;
Serial.println("-----------------------");
}
timeout = millis() + 1000;
}
// Arduino Setup
void setup(void) {
// Open Serial
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Warning);
// filter.setFilter(0, new MedianFilter<int16_t>(7));
// filter.begin(info);
// open input
toneG8.begin();
toneG8.setLoop(true);
// open resample
auto rcfg = resample.defaultConfig();
rcfg.copyFrom(info);
resample.begin(rcfg);
//resample.setBuffered(false);
// open i2s output
auto cfg = i2s.defaultConfig();
cfg.copyFrom(info);
i2s.begin(cfg);
i2s.setVolume(0.3);
}
// Arduino loop - copy sound to out
void loop() {
if (millis() > timeout) {
changeNote();
}
copier.copy();
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,61 @@
/**
* @file streams-audiokit-tf.ino
* @author Phil Schatzmann
* @brief We use a Nano BLE Sense which has a microphone as input to feed a Tensorflow Light Model which recognises the words yes and no.
* @version 0.1
* @date 2022-03-01
*
* @copyright Copyright (c) 2022
*
*/
#include "AudioTools.h"
#include "AudioTools/AudioLibs/AudioMP34DT05.h"
#include "AudioTools/AudioLibs/TfLiteAudioStream.h"
#include "model.h" // tensorflow model
AudioMP34DT05 mic; // Access I2S as stream
TfLiteAudioFeatureProvider fp;
TfLiteAudioStream tfl; // Audio sink
const char* kCategoryLabels[4] = {
"silence",
"unknown",
"yes",
"no",
};
StreamCopy copier(tfl, mic); // copy mic to tfl
int channels = 1;
int samples_per_second = 16000;
void respondToCommand(const char* found_command, uint8_t score,
bool is_new_command) {
if (is_new_command) {
char buffer[80];
sprintf(buffer, "Result: %s, score: %d, is_new: %s", found_command, score,
is_new_command ? "true" : "false");
Serial.println(buffer);
}
}
void setup() {
Serial.begin(115200);
while(!Serial); // wait for serial to be ready
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
Serial.println("starting...");
// Setup tensorflow
fp.kAudioChannels = channels;
fp.kAudioSampleFrequency = samples_per_second;
fp.respondToCommand = respondToCommand;
tfl.begin(g_model, fp, kCategoryLabels, 10 * 1024);
// setup Audiomic
auto cfg = mic.defaultConfig(RX_MODE);
cfg.channels = channels;
cfg.sample_rate = samples_per_second;
mic.begin(cfg);
Serial.println("started!");
}
void loop() { copier.copy(); }

View File

@@ -0,0 +1,44 @@
/**
* @file test-container-avi.ino
* @author Phil Schatzmann
* @brief Test avi container with pcm 8bit data
* @version 0.1
* @date 2022-04-30
*
* @copyright Copyright (c) 2022
*
*/
#include "AudioTools.h"
#include "AudioTools/AudioCodecs/ContainerAVI.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
#include "AudioTools/Communication/AudioHttp.h"
URLStream url("ssid","password"); // input
AudioBoardStream out(AudioKitEs8388V1);
DecoderL8 l8(false);
AVIDecoder codec(&l8);
EncodedAudioStream avi(&out, &codec);
StreamCopy copier(avi, url);
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// setup output using default settings
out.begin(out.defaultConfig());
// open url
url.begin("https://archive.org/download/Test_Avi/MVI_0043.AVI");
// parse metadata, so that we can validate if the audio/video is supported
while(!codec.isMetadataReady()){
copier.copy();
}
}
void loop() {
// Process data if audio is PCM
if (codec.audioFormat()==AudioFormat::PCM && codec.audioInfo().bits_per_sample==8){
copier.copy();
}
}

View File

@@ -0,0 +1,50 @@
/**
* @brief A simple WebSocket client sketch that sends out some PCM audio
* data using the https://github.com/Links2004/arduinoWebSockets library.AdapterAudioStreamToAudioOutput.AdapterAudioStreamToAudioOutput
* The WebSocket API is asynchronous, so we need to slow down the sending
* to the playback speed, to prevent any buffer overflows at the receiver.
* @author Phil Schatzmann
*/
#include <WebSocketsClient.h> // https://github.com/Links2004/arduinoWebSockets
#include <WiFiMulti.h>
#include "AudioTools.h"
#include "AudioTools/Communication/WebSocketOutput.h"
// websocket
WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
WebSocketOutput out(webSocket);
// audio
AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
Throttle throttle(out)
StreamCopy copier(throttle, sound);
void setup() {
Serial.begin(115200);
// connect to wifi
WiFiMulti.addAP("SSID", "passpasspass");
while (WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
WiFi.setSleep(false);
// start client connecting to server address, port and URL
webSocket.begin("192.168.1.34", 81, "/");
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
sineWave.begin(info, N_B4);
// WebSockets are async, so we need to slow down the sending
throttle.begin(info);
}
void loop() {
webSocket.loop();
// generate audio only when we are connected
if (webSocket.isConnected()) copier.copy();
}

View File

@@ -0,0 +1,49 @@
/**
* @brief A simple WebSocket server sketch that receives PCM audio data using the
* https://github.com/Links2004/arduinoWebSockets library and outputs it via i2s
* to an AudioKit for easy testing. Replace the output with whatever other class
* you like.
* @author Phil Schatzmann
*/
#include <WebSocketsServer.h> //https://github.com/Links2004/arduinoWebSockets
#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <WiFiMulti.h>
#include "AudioTools.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
WiFiMulti WiFiMulti;
WebSocketsServer webSocket(81);
AudioInfo info(44100, 2, 16);
AudioBoardStream i2s(AudioKitEs8388V1); // Access I2S as stream
/// Just output the audio data
void webSocketEvent(uint8_t num, WStype_t type, uint8_t* payload,
size_t length) {
if (type == WStype_BIN) {
i2s.write(payload, length);
}
}
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
WiFiMulti.addAP("SSID", "passpasspass");
while (WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
WiFi.setSleep(false);
Serial.println(WiFi.localIP());
// start server
webSocket.begin();
webSocket.onEvent(webSocketEvent);
// start i2s
auto cfg = i2s.defaultConfig(TX_MODE);
cfg.copyFrom(info);
i2s.begin(cfg);
}
void loop() { webSocket.loop(); }

View File

@@ -0,0 +1,55 @@
/**
* @brief A simple WebSocket client sketch that receives PCM audio data using the
* https://github.com/Links2004/arduinoWebSockets library and outputs it via i2s
* to an AudioKit for easy testing. Replace the output with whatever other class
* you like.
* @author Phil Schatzmann
*/
#include <WebSocketsClient.h> // https://github.com/Links2004/arduinoWebSockets
#include <WiFiMulti.h>
#include "AudioTools.h"
#include "AudioTools/AudioLibs/AudioBoardStream.h"
// websocket
WiFiMulti WiFiMulti;
WebSocketsClient webSocket;
// audio
AudioInfo info(44100, 2, 16);
AudioBoardStream i2s(AudioKitEs8388V1); // Access I2S as stream
// write audio to i2s
void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {
if (type == WStype_BIN) {
i2s.write(payload, length);
}
}
void setup() {
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// connect to wifk
WiFiMulti.addAP("SSID", "passpasspass");
while (WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
WiFi.setSleep(false);
// start client connecting to server address, port and URL
webSocket.begin("192.168.1.34", 81, "/");
// event handler
webSocket.onEvent(webSocketEvent);
// try ever 5000 again if connection has failed
webSocket.setReconnectInterval(5000);
// start i2s
auto cfg = i2s.defaultConfig(TX_MODE);
cfg.copyFrom(info);
i2s.begin(cfg);
}
void loop() {
webSocket.loop();
}

View File

@@ -0,0 +1,53 @@
/**
* @brief A simple WebSocket server sketch using the
* https://github.com/Links2004/arduinoWebSockets library to send out some
* PCM audio data when some clients are connnected.
* The WebSocket API is asynchronous, so we need to slow down the sending
* to the playback speed, to prevent any buffer overflows at the receiver.
* @author Phil Schatzmann
*/
#include <WebSocketsServer.h> // https://github.com/Links2004/arduinoWebSockets
#include <WiFi.h>
#include <WiFiMulti.h>
#include "AudioTools.h"
#include "AudioTools/Communication/WebSocketOutput.h"
WiFiMulti WiFiMulti;
WebSocketsServer webSocket(81);
WebSocketOutput out(webSocket);
// audio
AudioInfo info(44100, 2, 16);
SineWaveGenerator<int16_t> sineWave(32000);
GeneratedSoundStream<int16_t> sound(sineWave);
Throttle throttle(out);
StreamCopy copier(throttle, sound); // copies sound into i2s
void setup() {
// Serial.begin(921600);
Serial.begin(115200);
AudioToolsLogger.begin(Serial, AudioToolsLogLevel::Info);
// connect to wifi
WiFiMulti.addAP("SSID", "passpasspass");
while (WiFiMulti.run() != WL_CONNECTED) {
delay(100);
}
WiFi.setSleep(false);
Serial.println(WiFi.localIP());
// start server
webSocket.begin();
// start sine generation
sineWave.begin(info, N_B4);
throttle.begin(info);
}
void loop() {
webSocket.loop();
// generate audio only when we have any clients
if (webSocket.connectedClients() > 0) copier.copy();
}