snapshot
This commit is contained in:
4
libraries/audio-tools/examples/sandbox/README.md
Normal file
4
libraries/audio-tools/examples/sandbox/README.md
Normal 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...
|
||||
@@ -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() {
|
||||
}
|
||||
@@ -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(); }
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
# ADS1015
|
||||
|
||||

|
||||
|
||||
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.
|
||||
@@ -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();
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
44
libraries/audio-tools/examples/sandbox/ggwave/send/send.ino
Normal file
44
libraries/audio-tools/examples/sandbox/ggwave/send/send.ino
Normal 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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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() {}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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;
|
||||
@@ -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();
|
||||
}
|
||||
1564
libraries/audio-tools/examples/sandbox/streams-mp34dt05-tf/model.h
Normal file
1564
libraries/audio-tools/examples/sandbox/streams-mp34dt05-tf/model.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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(); }
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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(); }
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user