Krischomat
Well-known member
I started a sampler/looper project and right now I can record an audio loop and I setted up two grain object to freeze parts of the loop. The thing is now, when I have the freezing going on and I want to record a new loop, the whole audio stops for the recording. When I stop the recording the freeze is there as before the recording. I tried my luck with adding AudioNoInterrupts() at different points in the void recording() and void continuerecording() part but this did not help and dissabled the recording option.
Here is the Code:
Here is the Code:
Code:
#include <Bounce.h>
#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
// GUItool: begin automatically generated code
AudioInputI2S in; //xy=105,63
AudioEffectFade fade1;
AudioEffectFade fade2;
AudioEffectGranular granular1;
AudioEffectGranular granular2;
AudioEffectGranular granular3;
AudioEffectFreeverbStereo freeverbs1;
AudioEffectEnvelope envelope1;
AudioEffectMultiply multiply1;
AudioSynthWaveform waveform1;
AudioSynthWaveformDc dc1;
AudioMixer4 mixer1;
AudioMixer4 mixerL;
AudioMixer4 mixerR;
AudioMixer4 revSend1;
AudioMixer4 granularMixL;
AudioMixer4 granularMixR;
AudioMixer4 mixer2grain2;
AudioMixer4 mixer2grain3;
AudioMixer4 mixerDc;
AudioAnalyzePeak peak1; //xy=278,108
AudioRecordQueue queue1; //xy=281,63
AudioPlaySdRaw playRaw1; //xy=302,157
AudioOutputI2S out; //xy=470,120
AudioConnection patchCord1(in, 0, queue1, 0);
AudioConnection patchCord2(in, 0, peak1, 0);
AudioConnection patchCord3(playRaw1, 0, fade1, 0);
AudioConnection patchCord4(playRaw1, 0, fade2, 0);
AudioConnection patchCord5(fade1, 0, mixer1, 0);
AudioConnection patchCord6(fade2, 0, mixer1, 1);
AudioConnection patchCord7(mixer1, 0, granular1, 0);
AudioConnection patchCord8(granular1, 0, envelope1, 0);
AudioConnection patchCord9(envelope1, 0, revSend1, 0);
AudioConnection patchCord10(revSend1, 0, freeverbs1, 0);
AudioConnection patchCord11(granular1, 0, mixerL, 0);
AudioConnection patchCord12(granular1, 0, mixerR, 0);
AudioConnection patchCord13(freeverbs1, 0, mixerL, 1);
AudioConnection patchCord14(freeverbs1, 1, mixerR, 1);
AudioConnection patchCord15(mixerL, 0, out, 0);
AudioConnection patchCord16(mixerR, 0, out, 1);
// Granular Mix
AudioConnection patchCord17(granular1, 0, mixer2grain2, 0);
AudioConnection patchCord18(granular1, 0, mixer2grain3, 0);
AudioConnection patchCord19(mixer2grain2, 0, granular2, 0);
AudioConnection patchCord20(mixer2grain3, 0, granular3, 0);
AudioConnection patchCord21(granular2, 0, granularMixL, 0);
AudioConnection patchCord22(granular2, 0, granularMixR, 0);
AudioConnection patchCord23(multiply1, 0, granularMixL, 1);
AudioConnection patchCord24(multiply1, 0, granularMixR, 1);
AudioConnection patchCord25(granularMixL, 0, mixerL, 2);
AudioConnection patchCord26(granularMixR, 0, mixerR, 2);
// VCA
AudioConnection patchCord27(granular3, 0, multiply1, 0);
AudioConnection patchCord28(waveform1, 0, mixerDc, 0);
AudioConnection patchCord29(dc1, 0, mixerDc, 1);
AudioConnection patchCord30(mixerDc, 0, multiply1, 1);
AudioControlSGTL5000 sgtl5000_1; //xy=265,212
// GUItool: end automatically generated code
// For a stereo recording version, see this forum thread:
// https://forum.pjrc.com/threads/46150?p=158388&viewfull=1#post158388
// A much more advanced sound recording and data logging project:
// https://github.com/WMXZ-EU/microSoundRecorder
// https://github.com/WMXZ-EU/microSoundRecorder/wiki/Hardware-setup
// https://forum.pjrc.com/threads/52175?p=185386&viewfull=1#post185386
// Bounce objects to easily and reliably read the buttons
Bounce buttonRecord = Bounce(0, 8);
Bounce buttonGrain = Bounce(1, 8); // 8 = 8 ms debounce time
Bounce buttonPlay = Bounce(2, 8);
Bounce buttonGrain2 = Bounce(3, 8);
Bounce buttonGrain3 = Bounce(28, 8);
Bounce changeWaveform = Bounce(29, 15);
#define GRANULAR_MEMORY_SIZE 10000 // enough for 290 ms at 44.1 kHz
int16_t granularMemory[GRANULAR_MEMORY_SIZE];
#define GRANULAR_MEMORY_SIZE2 10000 // enough for 290 ms at 44.1 kHz
int16_t granularMemory2[GRANULAR_MEMORY_SIZE2];
#define GRANULAR_MEMORY_SIZE3 10000 // enough for 290 ms at 44.1 kHz
int16_t granularMemory3[GRANULAR_MEMORY_SIZE3];
// which input on the audio shield will be used?
const int myInput = AUDIO_INPUT_LINEIN;
//const int myInput = AUDIO_INPUT_MIC;
// Use these with the Teensy Audio Shield
#define SDCARD_CS_PIN 10
#define SDCARD_MOSI_PIN 7
#define SDCARD_SCK_PIN 14
// Remember which mode we're doing
int mode = 0; // 0=stopped, 1=recording, 2=playing
int mode1 = 0;
int mode2 = 0; // 0=stopped, 1=recording, 2=playing
int mode12 = 0;
// The file where data is recorded
File frec;
bool State = false;
bool Stateenv = false;
int playmode = 0;
int playmode2 = 0;
unsigned long previousMillis = 0;
long interval = 500;
long interval1 = interval - 50;
long intervalenv = 500;
int current_waveform = 0;
void setup() {
granular1.begin(granularMemory, GRANULAR_MEMORY_SIZE);
granular2.begin(granularMemory2, GRANULAR_MEMORY_SIZE2);
granular3.begin(granularMemory3, GRANULAR_MEMORY_SIZE3);
mixer1.gain(0, 0.8);
mixer1.gain(1, 0.8);
mixer1.gain(2, 0.8);
mixerL.gain(0, 0.6);
mixerR.gain(0, 0.6);
mixerL.gain(1, 0.6);
mixerR.gain(1, 0.6);
mixerL.gain(2, 0.6);
mixerR.gain(2, 0.6);
mixer2grain2.gain(0, 0);
mixer2grain3.gain(0, 0);
granularMixL.gain(0, 0.7);
granularMixR.gain(0, 0.3);
granularMixL.gain(1, 0.3);
granularMixR.gain(1, 0.7);
mixerDc.gain(0, 1);
mixerDc.gain(1, 1);
// Configure the pushbutton pins
pinMode(0, INPUT_PULLUP);
pinMode(1, INPUT_PULLUP);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(28, INPUT_PULLUP);
pinMode(29, INPUT_PULLUP);
// Audio connections require memory, and the record queue
// uses this memory to buffer incoming audio.
AudioMemory(240);
// Enable the audio shield, select input, and enable output
sgtl5000_1.enable();
sgtl5000_1.inputSelect(myInput);
sgtl5000_1.volume(0.5);
// Initialize the SD card
SPI.setMOSI(SDCARD_MOSI_PIN);
SPI.setSCK(SDCARD_SCK_PIN);
if (!(SD.begin(SDCARD_CS_PIN))) {
// stop here if no SD card, but print a message
while (1) {
Serial.println("Unable to access the SD card");
delay(500);
}
}
current_waveform = WAVEFORM_SINE;
waveform1.begin(current_waveform);
}
void loop() {
/// Looplength
unsigned long currentMillis = millis();
interval = map (analogRead(A13), 0, 1023, 50, playRaw1.lengthMillis());
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
if (State == false) {
State = true;
} else {
State = false;
}
}
if (currentMillis - previousMillis >= interval1) {
if (Stateenv == false) {
Stateenv = true;
} else {
Stateenv = false;
}
}
env1();
env2();
grain();
grain2();
grain3();
reverb();
envelope();
vca1();
// First, read the buttons
buttonRecord.update();
buttonPlay.update();
///////////////// 1st Sample
// Respond to button presses
if (buttonRecord.fallingEdge()) {
stopPlaying1();
stopPlaying2();
startRecording();
playmode = 0;
}
if (buttonRecord.risingEdge()) {
stopRecording();
playmode = 1;
}
if (playmode == 1) {
//play1
if (State == true) {
if (mode == 0) {
startPlaying1();
}
}
if (State == false) {
stopPlaying1();
}
//play2
if (State == false) {
if (mode1 == 0) {
startPlaying2();
}
}
if (State == true) {
stopPlaying2();
}
}
// If we're playing or recording, carry on...
if (mode == 1) {
continueRecording();
}
if (mode == 2) {
continuePlaying1();
}
if (mode1 == 2) {
continuePlaying2();
}
}
////////////////// 1st Sample
void startRecording() {
Serial.println("startRecording");
if (SD.exists("RECORD.RAW")) {
// The SD library writes new data to the end of the
// file, so to start a new recording, the old file
// must be deleted before new data is written.
SD.remove("RECORD.RAW");
}
frec = SD.open("RECORD.RAW", FILE_WRITE);
if (frec) {
queue1.begin();
mode = 1;
}
}
void continueRecording() {
if (queue1.available() >= 2) {
byte buffer[512];
// Fetch 2 blocks from the audio library and copy
// into a 512 byte buffer. The Arduino SD library
// is most efficient when full 512 byte sector size
// writes are used.
memcpy(buffer, queue1.readBuffer(), 256);
queue1.freeBuffer();
memcpy(buffer + 256, queue1.readBuffer(), 256);
queue1.freeBuffer();
// write all 512 bytes to the SD card
//elapsedMicros usec = 0;
frec.write(buffer, 512);
// Uncomment these lines to see how long SD writes
// are taking. A pair of audio blocks arrives every
// 5802 microseconds, so hopefully most of the writes
// take well under 5802 us. Some will take more, as
// the SD library also must write to the FAT tables
// and the SD card controller manages media erase and
// wear leveling. The queue1 object can buffer
// approximately 301700 us of audio, to allow time
// for occasional high SD card latency, as long as
// the average write time is under 5802 us.
//Serial.print("SD write, us=");
//Serial.println(usec);
}
}
void stopRecording() {
Serial.println("stopRecording");
AudioInterrupts();
queue1.end();
if (mode == 1) {
while (queue1.available() > 0) {
frec.write((byte*)queue1.readBuffer(), 256);
queue1.freeBuffer();
}
frec.close();
}
mode = 0;
}
//playing1
void startPlaying1() {
playRaw1.play("RECORD.RAW");
mode = 2;
}
void continuePlaying1() {
if (!playRaw1.isPlaying()) {
playRaw1.stop();
mode = 0;
}
}
void stopPlaying1() {
if (mode == 2) playRaw1.stop();
mode = 0;
}
//playing2
void startPlaying2() {
playRaw1.play("RECORD.RAW");
mode1 = 2;
}
void continuePlaying2() {
if (!playRaw1.isPlaying()) {
playRaw1.stop();
mode1 = 0;
}
}
void stopPlaying2() {
if (mode1 == 2) playRaw1.stop();
mode1 = 0;
}
////////////// Fades
void env1() {
if (Stateenv == false) {
fade1.fadeOut(50);
} else {
fade1.fadeIn(50);
}
}
void env2() {
if (Stateenv == true) {
fade2.fadeOut(50);
} else {
fade2.fadeIn(50);
}
}
/////////// grain for main loop
void grain() {
buttonGrain.update();
// float knobA12 = (float)analogRead(A12) / 1023.0;
float knobA11 = (float)analogRead(A11) / 1023.0;
// Button 1 starts Pitch Shift effect
if (buttonGrain.risingEdge()) {
// float msec = 10.0 + (knobA12 * 100.0);
granular1.beginPitchShift(1000);
}
// Continuously adjust the speed, based on the A3 pot
float ratio;
//ratio = powf(2.0, knobA11 * 2.0 - 1.0); // 0.5 to 2.0
ratio = powf(2.0, knobA11 * 6.0 - 3.0); // 0.125 to 8.0 -- uncomment for far too much range!
granular1.setSpeed(ratio);
}
/////grain freeze 1
void grain2() {
buttonGrain2.update();
float knobA14 = (float)analogRead(A14) / 1023.0;
float knobA10 = (float)analogRead(A10) / 1023.0;
// Button 0 starts Freeze effect
if (buttonGrain2.fallingEdge()) {
mixer2grain2.gain(0, 1);
float msec2 = 50.0 + (knobA14 * 150.0);
granular2.beginFreeze(msec2);
Serial.print("Begin granular freeze using ");
Serial.print(msec2);
Serial.println(" grains");
}
if (buttonGrain2.risingEdge()) {
mixer2grain2.gain(0, 0);
granular2.stop();
}
float ratio2;
//ratio2 = powf(2.0, knobA10 * 2.0 - 1.0); // 0.5 to 2.0
ratio2 = powf(2.0, knobA10 * 6.0 - 3.0); // 0.125 to 8.0 -- uncomment for far too much range!
granular2.setSpeed(ratio2);
}
/////grainfreeze2
void grain3() {
buttonGrain3.update();
float knobA14 = (float)analogRead(A14) / 1023.0;
float knobA10 = (float)analogRead(A10) / 1023.0;
// Button 0 starts Freeze effect
if (buttonGrain3.fallingEdge()) {
mixer2grain3.gain(0, 1);
float msec3 = 50.0 + (knobA14 * 130.0);
granular3.beginFreeze(msec3);
Serial.print("Begin granular freeze using ");
Serial.print(msec3);
Serial.println(" grains");
}
if (buttonGrain3.risingEdge()) {
mixer2grain3.gain(0, 0);
granular3.stop();
}
float ratio3;
//ratio2 = powf(2.0, knobA10 * 2.0 - 1.0); // 0.5 to 2.0
ratio3 = powf(2.0, knobA10 * 6.0 - 3.0); // 0.125 to 8.0 -- uncomment for far too much range!
granular3.setSpeed(ratio3);
}
void reverb() {
//float KnobA10 = (float)analogRead(A10) / 1023.0;
freeverbs1.roomsize(0.8);
freeverbs1.damping(1);
//revSend1.gain(0, KnobA10);
//revSend1.gain(1, KnobA10);
//revSend1.gain(2, KnobA10);
}
void envelope() {
if (buttonPlay.fallingEdge()) {
envelope1.noteOn();
}
if (buttonPlay.risingEdge()) {
envelope1.noteOff();
}
envelope1.attack(50);
envelope1.hold(10000);
envelope1.release(11000);
envelope1.sustain(1);
}
void vca1(){
float fq1 = analogRead(A14) / 20;
changeWaveform.update();
waveform1.amplitude(1);
waveform1.frequency(fq1 + 0.1);
dc1.amplitude(1);
if (changeWaveform.fallingEdge()){
switch (current_waveform) {
case WAVEFORM_SINE:
current_waveform = WAVEFORM_SQUARE;
Serial.println("Square");
break;
case WAVEFORM_SQUARE:
current_waveform = WAVEFORM_SAMPLE_HOLD;
Serial.println("S&H");
break;
case WAVEFORM_SAMPLE_HOLD:
current_waveform = WAVEFORM_SINE;
Serial.println("Sine");
break;
}
AudioNoInterrupts();
waveform1.begin(current_waveform);
AudioInterrupts();
}
}