recording a loop while granular freezing

Okay one more thing... I changed the
Code:
#define GRANULAR_MEMORY_SIZE3 20000
to
Code:
#define GRANULAR_MEMORY_SIZE3 6000

and the
Code:
float msec2 = 400;
for the freeze size accordingly to 100.

I assumed that the Serial.println(AudioMemoryUsageMax()); will give me a lower value but it is still the 207.
 
When I copied your code into the audio designer I got this ... are there missing connections ?

Selection_011.jpg
 
Here is the current code:

Code:
#include <Bounce.h>
#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>
#include <Mux.h>

using namespace admux;

Mux mux1(Pin(A14, INPUT, PinType::Analog), Pinset(1, 2, 3));


// 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;
AudioEffectMultiply        multiply2;
AudioEffectDelay           delay1;


AudioSynthWaveform         waveform1;
AudioSynthWaveformDc       dc1;
AudioSynthWaveform         waveform2;
AudioSynthWaveformDc       dc2;

AudioMixer4                mixer1;
AudioMixer4                mixerL;
AudioMixer4                mixerR;
AudioMixer4                revSend1;
AudioMixer4                granularMixL;
AudioMixer4                granularMixR;
AudioMixer4                mixer2grain2;
AudioMixer4                mixer2grain3;
AudioMixer4                mixerDc1;
AudioMixer4                mixerDc2;
AudioMixer4                delaySend1;


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, 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(multiply2, 0, granularMixL, 0);
AudioConnection            patchCord22(multiply2, 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);

// Delay
AudioConnection            patchCordDl1(granularMixL, 0, delaySend1, 0);
AudioConnection            patchCordDl2(granularMixR, 0, delaySend1, 1);
AudioConnection            patchCordDl3(delaySend1, 0, delay1, 0);
AudioConnection            patchCordDl4(delay1, 0, granularMixL, 2);
AudioConnection            patchCordDl5(delay1, 1, granularMixL, 3);
AudioConnection            patchCordDl6(delay1, 2, granularMixR, 2);
AudioConnection            patchCordDl7(delay1, 3, granularMixR, 3);

// VCA

AudioConnection            patchCord27(granular3, 0, multiply1, 0);
AudioConnection            patchCord28(waveform1, 0, mixerDc1, 0);
AudioConnection            patchCord29(dc1, 0, mixerDc1, 1);
AudioConnection            patchCord30(mixerDc1, 0, multiply1, 1);

AudioConnection            patchCord31(granular2, 0, multiply2, 0);
AudioConnection            patchCord32(waveform2, 0, mixerDc2, 0);
AudioConnection            patchCord33(dc2, 0, mixerDc2, 1);
AudioConnection            patchCord34(mixerDc2, 0, multiply2, 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, 3);
Bounce buttonStopRec = Bounce(4, 3);

Bounce buttonGrain2 =   Bounce(28, 3);
Bounce buttonGrain3 =   Bounce(29, 3);
Bounce changeWaveform = Bounce(30, 15);
Bounce changeWaveform2 = Bounce(30, 15);



#define GRANULAR_MEMORY_SIZE 12800  // enough for 290 ms at 44.1 kHz
int16_t granularMemory[GRANULAR_MEMORY_SIZE];

#define GRANULAR_MEMORY_SIZE2 6000  // enough for 290 ms at 44.1 kHz
int16_t granularMemory2[GRANULAR_MEMORY_SIZE2];

#define GRANULAR_MEMORY_SIZE3 6000  // 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
enum Mode {
  stopped,
  recording,
  playing,
};

Mode mode = stopped;
Mode mode1 = stopped;

// The file where data is recorded
File frec;

bool State = false;
bool Stateenv = false;
Mode playmode = playing;
int playmode2 = 0;
unsigned long previousMillis = 0;
unsigned long interval = 500;
unsigned long interval1 = interval - 50;
unsigned long intervalenv = 500;

int current_waveform = 0;
int current_waveform2 = 0;


void setup() {

  granular1.begin(granularMemory, GRANULAR_MEMORY_SIZE);
  granular2.begin(granularMemory2, GRANULAR_MEMORY_SIZE2);
  granular3.begin(granularMemory3, GRANULAR_MEMORY_SIZE3);

  granular1.beginPitchShift(1000);

  mixer1.gain(0, 0.8);
  mixer1.gain(1, 0.8);
  mixer1.gain(2, 0.8);
  mixerL.gain(0, 0.8);
  mixerR.gain(0, 0.8);
  mixerL.gain(1, 0.8);
  mixerR.gain(1, 0.8);
  mixerL.gain(2, 0.8);
  mixerR.gain(2, 0.8);
  mixer2grain2.gain(0, 0);
  mixer2grain3.gain(0, 0);
  granularMixL.gain(0, 0.8);
  granularMixR.gain(0, 0.4);
  granularMixL.gain(1, 0.4);
  granularMixR.gain(1, 0.8);
  granularMixL.gain(2, 0.5);
  granularMixR.gain(2, 0.5);
  granularMixL.gain(3, 0.5);
  granularMixR.gain(3, 0.5);
  mixerDc1.gain(0, 1);
  mixerDc1.gain(1, 1);
  mixerDc2.gain(0, 1);
  mixerDc2.gain(1, 1);


  // Configure the pushbutton pins
  pinMode(0, INPUT_PULLUP);
  pinMode(28, INPUT_PULLUP);
  pinMode(29, INPUT_PULLUP);
  pinMode(30, INPUT_PULLUP);
  pinMode(33, OUTPUT);


  // Audio connections require memory, and the record queue
  // uses this memory to buffer incoming audio.
  AudioMemory(250);

  // Enable the audio shield, select input, and enable output
  sgtl5000_1.enable();
  sgtl5000_1.inputSelect(myInput);
  sgtl5000_1.volume(1);

  // 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);
    }
  }
  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");
  }

  current_waveform = WAVEFORM_SINE;
  waveform1.begin(current_waveform);
  waveform2.begin(current_waveform2);
}



void loop() {

  Serial.println(AudioMemoryUsageMax());

  for (byte i = 0; i < mux1.channelCount(); i++) {
    mux1.channel(i);
    // allow 50 us for signals to stablize
    delayMicroseconds(50);
  }

  env1();
  env2();
  grain();
  grain2();
  grain3();
  DL();
  reverb();
  vca1();
  vca2();
  looplength();

  // First, read the buttons
  buttonRecord.update();
  buttonStopRec.update();


  ///////////////// 1st Sample

  // Respond to button presses
  if (buttonRecord.fallingEdge()) {
   
    stopPlaying1();
    stopPlaying2();
    startRecording();
    playmode = recording;
    

  }

  if (buttonRecord.risingEdge()) {

    stopRecording();
    playmode = playing;
  }


  if (playmode == playing) {

    //play1

    if (State == true) {

      stopPlaying2();

      if (mode == stopped) {
        startPlaying1();

      }
    }

    if (State == false) {

      stopPlaying1();

      if (mode1 == stopped) {
        startPlaying2();
      }

    }
  }


  // If we're playing or recording, carry on...
  if (mode == recording) {

    continueRecording();
  }
  if (mode == playing) {
    
    continuePlaying1();

  }
  if (mode1 == playing) {
 
    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 = recording;
   
  }
}

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");
  
  queue1.end();
  if (mode == 1) {
    while (queue1.available() > 0) {
      frec.write((byte*)queue1.readBuffer(), 256);
      queue1.freeBuffer();
    }
    frec.close();
  }
  mode = stopped;
}

////////// Playing1

void startPlaying1() {

  playRaw1.play("RECORD.RAW");
  mode = playing;
}

void continuePlaying1() {
  if (!playRaw1.isPlaying()) {
    playRaw1.stop();
    mode = stopped;
  }
}

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() {

  float FaderPitch = mux1.read(1) / 1023.0;

  // Continuously adjust the speed, based on the A3 pot
  float ratio;
  //ratio = powf(2.0, knobA11 * 6.0 - 3.0); // 0.5 to 2.0
  ratio = powf(2.0, FaderPitch * 2.0 - 1.0); // 0.125 to 8.0 -- uncomment for far too much range!
  granular1.setSpeed(ratio);
  delayMicroseconds(30);

}

/////////// Grain freeze 1

void grain2() {
  buttonGrain2.update();
      //Serial.println(millis());
  float FaderFreeze1Pitch = mux1.read(2) / 1023.0;
  //float FaderFreeze1Length = mux1.read(3) / 1023.0;

  // Button 0 starts Freeze effect
  if (buttonGrain2.fallingEdge()) {
    mixer2grain2.gain(0, 1);
 //   float msec2 = 50.0 + (FaderFreeze1Length * 150.0);
    float msec2 = 100;    
    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, FaderFreeze1Pitch * 2.0 - 1.0); // 0.125 to 8.0 -- uncomment for far too much range!
  granular2.setSpeed(ratio2);

}

//////////// Grainfreeze2

void grain3() {
  buttonGrain3.update();

  float FaderFreeze2Pitch = mux1.read(3) / 1023.0;
  // float FaderFreeze2Length = mux1.read(3) / 1023.0;

  // Button 0 starts Freeze effect
  if (buttonGrain3.fallingEdge()) {
    mixer2grain3.gain(0, 1);
    //float msec3 = 50.0 + (FaderFreeze2Length * 130.0);
    float msec3 = 100;   
    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, FaderFreeze2Pitch * 2.0 - 1.0); // 0.125 to 8.0 -- uncomment for far too much range!
  granular3.setSpeed(ratio3);

}

///////////// Delay
void DL(){

delaySend1.gain(0, 0.3);
delaySend1.gain(1, 0.3);
 

delay1.delay(0, 300);
delay1.delay(1, 500);
delay1.delay(2, 200);
delay1.delay(3, 400);
}


///////////// Reverb

void reverb() {

  //float KnobA10 = (float)analogRead(A10) / 1023.0;

  freeverbs1.roomsize(0.8);
  freeverbs1.damping(1);

  revSend1.gain(0, 0);
  //revSend1.gain(1, KnobA10);
  //revSend1.gain(2, KnobA10);

}

///////////// VCA

void vca1() {

  float fq1 = mux1.read(4) / 20;
  changeWaveform.update();

  waveform1.amplitude(1);
  waveform1.frequency(fq1 + 0.1);
  dc1.amplitude(0);


  if (changeWaveform.fallingEdge()) {
    switch (current_waveform) {
      case WAVEFORM_SINE:
        current_waveform = WAVEFORM_SAWTOOTH;
        Serial.println("Square");
        break;
      case WAVEFORM_SAWTOOTH:
        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();
  }
}

///////////

void vca2() {

  float fq1 = mux1.read(4) / 20;
  changeWaveform2.update();

  waveform2.amplitude(1);
  waveform2.frequency(fq1 + 0.1);
  dc2.amplitude(0);


  if (changeWaveform2.fallingEdge()) {
    switch (current_waveform2) {
      case WAVEFORM_SINE:
        current_waveform2 = WAVEFORM_SAWTOOTH;
        Serial.println("Square2");
        break;
      case WAVEFORM_SAWTOOTH:
        current_waveform2 = WAVEFORM_SAMPLE_HOLD;
        Serial.println("S&H2");
        break;
      case WAVEFORM_SAMPLE_HOLD:
        current_waveform2 = WAVEFORM_SINE;
        Serial.println("Sine2");
        break;
    }
    AudioNoInterrupts();
    waveform2.begin(current_waveform2);
    AudioInterrupts();
  }
}

void looplength() {
  unsigned long currentMillis = millis();
  interval = map (mux1.read(5), 0, 1023, 50, playRaw1.lengthMillis()); 
  // interval = map (analogRead(A10), 0, 1023, 50, playRaw1.lengthMillis());
  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    State = !State;
  }

  if (currentMillis - previousMillis >= interval1) {
    Stateenv = !Stateenv;
  }

  if (State == HIGH){
    digitalWrite(33, HIGH);
    
  } else {
    digitalWrite(33,LOW);
  }
}
 
Okay some more insights :D I connected a peak object to one of these granular objects and did read the peak. When I am starting to record a new loop the peak does not go to zero but just keeps the last number and stays there. So the freeze is totally frozen :D

Code:
void grain2() {
  buttonGrain2.update();
      //Serial.println(millis());
  float FaderFreeze1Pitch = mux1.read(2) / 1023.0;
  //float FaderFreeze1Length = mux1.read(3) / 1023.0;

  // Button 0 starts Freeze effect
  if (buttonGrain2.fallingEdge()) {
    mixer2grain2.gain(0, 1);
 //   float msec2 = 50.0 + (FaderFreeze1Length * 150.0);
    float msec2 = 100;    
    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, FaderFreeze1Pitch * 2.0 - 1.0); // 0.125 to 8.0 -- uncomment for far too much range!
  granular2.setSpeed(ratio2);

if (peak3.available()){
  Serial.println(peak3.read());
}

}
 
I think SD.remove() is very expensive because you have to overwrite the entire file with 1 bits to be able to record again.
Try to debug this part printing something before and after SD.remove("RECORD.RAW");
 
Back
Top