~AudioPlaySdWav(){SAFE_RELEASE_INPUTS(); SAFE_RELEASE_MANY(2,block_left,block_right);}
~AudioPlayWAVbuffered() { stop(); }
/*
* Thrash the preload SD card playback using dynamic objects.
* ONLY for use with the Dynamic Audio library!
*/
#include <Audio.h>
#define COUNT_OF(x) (sizeof x / sizeof x[0])
// GUItool: begin automatically generated code
AudioMixer4 mixerL; //xy=527,390
AudioMixer4 mixerR; //xy=531,473
AudioOutputI2S i2sOut; //xy=683,434
AudioRecordQueue sync; //xy=699,546
AudioConnection patchCord1(mixerL, 0, i2sOut, 0);
AudioConnection patchCord2(mixerR, 0, i2sOut, 1);
AudioConnection patchCord3(mixerR, sync);
AudioControlSGTL5000 sgtl5000; //xy=688,477
// GUItool: end automatically generated code
/**********************************************************************/
// These files are what they say: all 3s long, mono, 44.1kHz
const char* files[] = {
"sine110.wav",
"sine220.wav",
"sine330.wav",
"sine440.wav",
"sine550.wav",
"sine660.wav"
};
AudioPreload* preloads[COUNT_OF(files)];
// Pre-load all the above into fairly short buffers, a different size for each
void doPreload(void)
{
for (int i=0;i<COUNT_OF(files);i++)
{
#define PRELOAD_SIZE(x) (1024 + x * 512) // 11.6, 17.4 ... 40.6ms
preloads[i] = new AudioPreload(files[i],AudioBuffer::inHeap,PRELOAD_SIZE(i));
Serial.printf("Preload %d (%s -> %s); %d valid; buffer at 0x%08X\n",i,files[i],preloads[i]->filepath,preloads[i]->valid,preloads[i]->buffer);
}
}
/**********************************************************************/
struct bip {
AudioPlayWAVstereo* player;
AudioConnection* l,*r;
uint32_t stopAt;
};
bip bippers[4];
/*
* "bip" a file by creating a playback object, connecting it, and starting it playing
* from the designated preload object. Note we DO permit multiple playback objects
* to use the SAME preload object, and hence the SAME file on SD. And it works.
*/
void bipStart(int idx,AudioPreload* prld,uint32_t stopAt)
{
bip* bp = bippers+idx;
Serial.printf("Start %d at %d with %s for %dms\n",idx,millis(),prld->filepath,stopAt - millis());
Serial.flush();
if (nullptr == bp->player)
{
bp->player = new AudioPlayWAVstereo;
bp->l = new AudioConnection;
bp->r = new AudioConnection;
bp->l->connect(*bp->player,0,mixerL,idx);
bp->r->connect(*bp->player,1,mixerR,idx);
bp->player->createBuffer(4096,AudioBuffer::inHeap);
}
bp->stopAt = stopAt;
bp->player->play(*prld);
}
/*
* Stop the "bip" by brutally deleting the playback object
* and its connections. You could change the if (1) and
* just stop the playback, but where's the fun in that?
*/
void bipStop(int idx)
{
bip* bp = bippers+idx;
Serial.printf("Stop %d at %d\n",idx, millis());
Serial.flush();
if (1)
{
delete bp->player;
delete bp->l;
delete bp->r;
*bp = {0,0,0,0};
}
else
{
bp->player->stop();;
bp->stopAt = 0;
}
}
/*
* Every so often, try to start another random "bip".
* Also check for any whose time has come, and stop them.
*/
void bipUpdate(void)
{
int rnum = random(100);
bool tryStart = rnum < 2; // 2% chance of trying to start something
for (int i=0;i<COUNT_OF(bippers);i++)
{
if (bippers[i].stopAt != 0 && millis() > bippers[i].stopAt)
bipStop(i);
if (tryStart && 0 == bippers[i].stopAt)
{
AudioPreload* prld = preloads[random(COUNT_OF(preloads))]; // random file
uint32_t stopAt = random(1,15); // 1 to 14
stopAt *= stopAt; // 1, 4, 9, ... 196
stopAt *= 2; // 2, 8, 18, ... 392
stopAt += millis(); // random play duration
bipStart(i, prld, stopAt);
tryStart = false;
}
}
}
/**********************************************************************/
void setup()
{
AudioMemory(20);
while (!Serial)
;
if (CrashReport)
Serial.println(CrashReport);
while (!SD.begin(BUILTIN_SDCARD))
{
Serial.println("SD fail");
delay(250);
}
doPreload();
Serial.println("Running");
mixerL.gain(0,0.9f);
mixerL.gain(1,0.7f);
mixerL.gain(2,0.5f);
mixerL.gain(3,0.3f);
mixerR.gain(0,0.3f);
mixerR.gain(1,0.5f);
mixerR.gain(2,0.7f);
mixerR.gain(3,0.9f);
sgtl5000.setAddress(HIGH);
sgtl5000.enable();
sgtl5000.volume(0.2f);
sync.begin();
}
bool syncSet;
void loop()
{
// sync to audio engine
while (sync.available() > 0)
{
sync.readBuffer();
sync.freeBuffer();
syncSet = true;
}
if (syncSet) // stuff to do just after audio update
{
static int syncCount = 0;
syncSet = false;
syncCount++;
if (0 == syncCount % 100)
{
Serial.printf("Used blocks = %d\n",AudioMemoryUsage());
}
}
bipUpdate();
delay(1);
}
#include <Audio.h>
#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
AudioInputI2S is2stereoIn; //xy=381.4285888671875,1194.2857666015625
AudioAmplifier amp1R; //xy=592.2857398986816,1331.1428871154785
AudioAmplifier amp1L; //xy=595.2857398986816,1046.1428546905518
AudioRecordWAVstereo record; //xy=962,1193
AudioMixer4 mixer1; //xy=808.5714912414551,1085.7143383026123
AudioMixer4 mixer2; //xy=810.2857971191406,1318.285831451416
AudioFilterBiquad biquad1L; //xy=960.1428604125977,907.4286336898804
AudioFilterBiquad biquad1R; //xy=993.8571090698242,1543.4284753799438
AudioOutputI2S i2sOut; //xy=1010,1169.9999446868896
AudioAnalyzePeak peakL; //xy=1221.4285888671875,868.2857666015625
AudioOutputUSB usb2; //xy=1266.4285888671875,1148.2857666015625
AudioAnalyzePeak peakR; //xy=1283.8571891784668,1455.57124710083
AudioPlayWAVstereo play ; //xy=630.0000610351562,1197.1428031921387
AudioConnection patchCord1(is2stereoIn, 0, amp1L, 0);
AudioConnection patchCord2(is2stereoIn, 1, amp1R, 0);
AudioConnection patchCord15(amp1L, 0, record, 0);
AudioConnection patchCord13(amp1L, 0, i2sOut, 0);
AudioConnection patchCord14(mixer1, 0, usb2, 0);
AudioConnection patchCord17(amp1R, 0,record,1);
AudioConnection patchCord16(mixer2, 0, usb2, 1);
AudioConnection patchCord18(amp1R, 0, i2sOut, 1);
AudioConnection patchCord19(biquad1L, peakL);
AudioConnection patchCord20(biquad1R, peakR);
void SDsetup() {
// Initialize the SD card
SPI.setMOSI(7);
SPI.setSCK(14);
if (!(SD.begin(254))) {
delay(600);
}
}
void setup() {
SDsetup();
AudioMemory(20);
Serial.begin(9600);
amp1L.gain(1.5); //
amp1R.gain(1.5); //
}
int testStarted = 0;
int testCompleted = 0;
void loop() {
digitalWrite(36, HIGH); //needed for activating my i2S device
digitalWrite(31, HIGH); //needed for activating my i2S device
if (!testStarted)
{
startRecording();
testStarted = 1;
}
if (testStarted && !testCompleted && millis() > 5000)
{
stopRecording();
testCompleted = 1;
}
return;
}
void stopRecording() {
record.stop();
}
const char* startRecording() {
short nameIncrement = 0;
String fileName = "X" + String(nameIncrement) + ".wav";
if(SD.exists(fileName.c_str())) {
SD.remove(fileName.c_str());
}
record.recordSD(fileName.c_str());
return fileName.c_str();
}
record.createBuffer(8192,AudioBuffer::inHeap);
AudioRecordWAVstereo is a new addition to the audio library?
any chance it will go back to the main repo?
Is there an upper limit to the Buffer size? I would like to use a large Buffer, because of the high latency of SD cards for recording.It's really important to configure a suitably sized buffer for each and every buffered playback or record object. In this instance, in setup() you need something like:
Code:record.createBuffer(8192,AudioBuffer::inHeap);
The only limit is the amount of spare memory you have. If your heap is mostly unused on a Teensy 4.x, then you have about 5s of buffer for a mono signal, or 2.5s for stereo. With 8MB of PSRAM that grows to 90s or 45s. Each object has its own buffer which can be in either region, so you could go with a smaller buffer in heap for playback, and a big one in PSRAM for recording.Is there an upper limit to the Buffer size? I would like to use a large Buffer, because of the high latency of SD cards for recording.
Good news! Do come back if you have further questions, I’d like to be as sure as possible that it’s in good shape before it gets into a PR or beta.The forked Audio library + the record.createBuffer(8192,AudioBuffer::inHeap);
worked
I been battling this for months lol. Thanks h4yn0nnym0u5e.
//Play 14 files simultanously
//
//Download the file "Mellotron Violin samples (zip)" from here: https://robertsonics.com/tsunami-downloads/
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#define COUNT_OF(x) (sizeof x / sizeof x[0])
// GUItool: begin automatically generated code
AudioPlayWAVstereo playWav1;
AudioPlayWAVstereo playWav2;
AudioPlayWAVstereo playWav3;
AudioPlayWAVstereo playWav4;
AudioPlayWAVstereo playWav5;
AudioPlayWAVstereo playWav6;
AudioPlayWAVstereo playWav7;
AudioMixer4 mixer1; //xy=512,151
AudioMixer4 mixer2; //xy=515,226
AudioMixer4 mixer3; //xy=516,304
AudioMixer4 mixer4; //xy=516,377
AudioMixer4 mixer5; //xy=517,448
AudioMixer4 mixer6; //xy=518,521
AudioMixer4 mixer7; //xy=519,601
AudioMixer4 mixer8; //xy=521,682
AudioMixer4 mixer9; //xy=745,277
AudioMixer4 mixer10; //xy=756,528
AudioOutputMQS audioOutput; //
AudioConnection patchCord5(playWav6, 0, mixer2, 1);
AudioConnection patchCord6(playWav6, 1, mixer6, 1);
AudioConnection patchCord9(playWav5, 0, mixer2, 0);
AudioConnection patchCord10(playWav5, 1, mixer6, 0);
AudioConnection patchCord13(playWav7, 0, mixer2, 2);
AudioConnection patchCord14(playWav7, 1, mixer6, 2);
AudioConnection patchCord17(playWav3, 0, mixer1, 2);
AudioConnection patchCord18(playWav3, 1, mixer5, 2);
AudioConnection patchCord19(playWav4, 0, mixer1, 3);
AudioConnection patchCord20(playWav4, 1, mixer5, 3);
AudioConnection patchCord23(playWav1, 0, mixer1, 0);
AudioConnection patchCord24(playWav1, 1, mixer5, 0);
AudioConnection patchCord27(playWav2, 0, mixer1, 1);
AudioConnection patchCord28(playWav2, 1, mixer5, 1);
AudioConnection patchCord29(mixer1, 0, mixer9, 0);
AudioConnection patchCord30(mixer2, 0, mixer9, 1);
AudioConnection patchCord31(mixer3, 0, mixer9, 2);
AudioConnection patchCord32(mixer4, 0, mixer9, 3);
AudioConnection patchCord33(mixer5, 0, mixer10, 0);
AudioConnection patchCord34(mixer6, 0, mixer10, 1);
AudioConnection patchCord35(mixer7, 0, mixer10, 2);
AudioConnection patchCord36(mixer8, 0, mixer10, 3);
AudioConnection patchCord37(mixer9, 0, audioOutput, 0);
AudioConnection patchCord38(mixer10, 0, audioOutput, 1);
// GUItool: end automatically generated code
const int numFiles = 6;
AudioPlayWAVstereo *player[numFiles] = {
&playWav1, &playWav2, &playWav3, &playWav4,
&playWav5, &playWav6, //&playWav7
};
const char* filename[numFiles] = {
"AMBPIANO.WAV",
"BASSSYNTH.WAV",
"CELLO.WAV",
"MAINSYNTH.WAV",
//"ORCHESTRA.WAV",
"PIANO.WAV",
"SECRET.WAV",
};
int cnt = 0;
AudioPreload* preloads[COUNT_OF(filename)];
void doPreload(void)
{
for (int i=0;i<numFiles;i++)
{
#define PRELOAD_SIZE(x) (1024 + x * 512) // 11.6, 17.4 ... 40.6ms
preloads[i] = new AudioPreload(filename[i],AudioBuffer::inHeap,PRELOAD_SIZE(i));
}
}
void setup() {
Serial.begin(9600);
AudioMemory(16);
delay(500);
if (CrashReport) {
pinMode(13, OUTPUT);
digitalWriteFast(13, 1);
Serial.println(CrashReport);
CrashReport.clear();
delay(30000);
}
if (!(SD.begin(BUILTIN_SDCARD))) {
// stop here, but print a message repetitively
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
// set up mixers
float gain = 1.0 / numFiles;
for (int i = 0; i < 4; i++) {
mixer1.gain(i, gain);
mixer2.gain(i, gain);
mixer3.gain(i, gain);
mixer4.gain(i, gain);
mixer5.gain(i, gain);
mixer6.gain(i, gain);
mixer7.gain(i, gain);
mixer8.gain(i, gain);
}
gain = 1.0 / 4;
for (int i = 0; i < 4; i++) {
mixer9.gain(i, gain);
mixer10.gain(i, gain);
}
for (int i = 0; i < numFiles; i++)
{
Serial.printf("Start %02d : %s\n", i + 1, filename[i]);
player[i]->createBuffer(32768,AudioBuffer::inHeap);
}
doPreload();
}
void loop() {
for (int i = 0; i < numFiles; i++)
{
player[i]->cueSD(filename[i]);
}
for (int i = 0; i < numFiles; i++)
{
Serial.printf("Start %02d : %s\n", i + 1, filename[i]);
player[i]->playSD(filename[i]);
}
AudioNoInterrupts();
for (int i = 0; i < numFiles; i++) {
player[i]->togglePlayPause();
}
AudioInterrupts();
for (int i = 0; i < numFiles; i++) {
player[i]->togglePlayPause();
}
int playing;
do {
playing = 0;
for (int i = 0; i < numFiles; i++)
{
if (player[i]->isPlaying())
playing++;
}
} while (playing > 0);
Serial.println("All stopped.");
}
int playing;
do {
playing = 0;
for (int i = 0; i < numFiles; i++)
{
if (player[i]->isPlaying())
playing++;
}
[COLOR="#FF0000"]yield();[/COLOR]
} while (playing > 0);
Yes, that's the correct repository, but I've made many branches fixing various bugs and developing features. Assuming you want the simple guide:Thanks for the replies!
OK. I've found the repository, https://github.com/h4yn0nnym0u5e/Audio.
I assume this is an updated version of the teensy audio library that comes pre-installed in the TeensyDuino IDE? Updated with the features of WavPlayerEx?
I'm going to try to figure out how to install it...
Thanks!