Forum Rule: Always post complete source code & details to reproduce any issue!
Page 2 of 2 FirstFirst 1 2
Results 26 to 32 of 32

Thread: recording a loop while granular freezing

  1. #26
    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.

  2. #27
    Senior Member CorBee's Avatar
    Join Date
    Jun 2018
    Location
    Netherlands
    Posts
    527
    When I copied your code into the audio designer I got this ... are there missing connections ?

    Click image for larger version. 

Name:	Selection_011.jpg 
Views:	35 
Size:	55.0 KB 
ID:	25572

  3. #28
    Hmm that weird. Mine looks like this (with a delay added).
    Click image for larger version. 

Name:	Bildschirmfoto 2021-08-14 um 18.06.22.png 
Views:	37 
Size:	92.3 KB 
ID:	25573

  4. #29
    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);
      }
    }

  5. #30
    Senior Member CorBee's Avatar
    Join Date
    Jun 2018
    Location
    Netherlands
    Posts
    527
    Seems that the audio designer doesnt copy the patchcords properly.

  6. #31
    Okay some more insights 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

    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());
    }
    
    }

  7. #32
    Member dimitre's Avatar
    Join Date
    Aug 2016
    Location
    São Paulo
    Posts
    95
    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");

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •