May i contact to "Bleep Labs."???

charnjit

Well-known member
I am continously trying with GranularEffect to get better result. but could not. No example found for slower/faster playback speed of short Drum loop loaded in Psarm , something like this by Nic N but he is not reply for code..
i am seeing in Teensy audio System Design Tool it is contributed by "Bleep Lab" . there is Nobody on forum reply me to use it.
May i contact to Bleep Labs??
if No , is there another platform to ask about Teensy Granular Effect in Details..
Thank you
 
is there Nobody related to Granular???
My suggestion: Granular is not working for playback speed control.it must be Reset/modify to work and update Library. for simple users with examples.
otherwise No need to add it in Audio library
 
Sorry, I am not an Audio person...

But I looked up at the library, and it looked like the comment about "Bleep Labs" was made by Paul like 8 years ago.

You might look around and see what other commits were done about the same time to get clues.

And I assume you did a search on the forum for Bleep labs?
With that I found:
Code:
/*
   Copyright (c) 2018 John-Michael Reed
   bleeplabs.com

   Permission is hereby granted, free of charge, to any person obtaining a copy
   of this software and associated documentation files (the "Software"), to deal
   in the Software without restriction, including without limitation the rights
   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   copies of the Software, and to permit persons to whom the Software is
   furnished to do so, subject to the following conditions:

   The above copyright notice and this permission notice shall be included in all
   copies or substantial portions of the Software.

   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
   SOFTWARE.


   This is a looper based on the Tape Delay effect by Bleep Labs

*/
 
Thanks a lot KurtE .. for reply . i could not understand link you given. I seemed I will have to again fight alone to Granular basic functions.
Thank you
 
Thanks a lot KurtE .. for reply . i could not understand link you given.
The first like was the commit that Paul did to his Audio library to add the text of the bleep labs... I was suggesting you might look back to that and see what other Pull Requests Paul did at about that time.

I was also sort of suggesting you go look at his web site: bleeplabs.com
Which also gets you to his github account: https://github.com/BleepLabs/
Note: I don't see any PRs from user: BleepLabs so not sure if Paul pulled it in himself or ...

Which shows that his name is: John-Michael Reed in Auston Texas.

Then taking a wild guess, maybe the person here is the member john-mike


Who also shows from Auston Texas... But again just a guess
 
Thank you KurtE .... I am sorry . I'm already quite confused for granular. but in experiment , I saw something hopeful. Please Take a look on code:

C++:
                       #define GRANULAR_BUFFER_SIZE  12800
                     int16_t grainBuffer[GRANULAR_BUFFER_SIZE];
 
        
        void setup()       {
                           granular1.begin(grainBuffer, GRANULAR_BUFFER_SIZE);

                             }

         void loop() {

                            if (!playArrayWav1.isPlaying())  { 
                                                                playArrayWav1.play("01.WAV"); 
                                                                  granular1.beginFreeze(250);
                                                              } 
                              granular1.setSpeed(Speed);
                          }
using above part and after calling this
C++:
   Speed=Speed+ 0.5;       
   granular1.beginPitchShift(75);
   granular1.setSpeed(Speed);
i see granular start work with speed without affect pitch . But i am not listening full of my drum loop. i am listening only half or less than half second playback of my drum loop in repeat mode. i can see changes in speed by input . but not playing my full drum loop.
Note: My drum loop is 2.264sec long (195kb)Size.
i have soldered 16mb psram 2 chips to my teensy4.1

if i use granular1.beginFreeze(); parameter more than 250 , No audio from playback. may be , i should use Psram. . but i don't know how to allocate memory for granular to processing my drum loop fully.
could you help me here......
 

Attachments

  • 01.zip
    168.2 KB · Views: 17
In your example snippets of code above...

#define GRANULAR_BUFFER_SIZE 12800 and granular1.begin(grainBuffer, GRANULAR_BUFFER_SIZE); sets up an array of samples. Since we sample at 44100Hz a buffer of 12800 will allow for about 290ms of samples.

When you do granular1.beginFreeze(250); that sets up a grain of length 250ms or 250/1000 *44100 samples 11025 which is just under the size of your array. Anything larger than 290ms will be longer than your buffer.

For the future it is easier to help if we can see a small example of working code (i.e. code that we can run rather than just snippets of code).

cheers Paul
 
if i increase buffer size for use of PSRAM
C++:
     #define GRANULAR_BUFFER_SIZE 2800000   
      EXTMEM int16_t grainBuffer[GRANULAR_BUFFER_SIZE];
and use freeze time granular1.beginFreeze(1132); .Not Work
if freeze time granular1.beginFreeze(566); .Playback start full length(2.264 sec) . No changes on speed increament/Decreament.
if freeze time granular1.beginFreeze(250); .Playback start full length(2.264 sec) . No changes on speed increament/Decreament
as i had used in Post#8 .
i seemed my teensy not using external PSRAM by Calling
C++:
     #define GRANULAR_BUFFER_SIZE 2800000   
      EXTMEM int16_t grainBuffer[GRANULAR_BUFFER_SIZE];
what should i do next ???
is there tested code ??
How to allocate Psram memory for granular For my unknown size .wav files ( less than 10 sec , geart than 2 sec )????
Any hint Please???
 
I had a look at the library object and it uses int16_t to store the buffer size and various pointers. The max number a int16_t can hold is 32,767 for the max time that the current object is just under 0.75s. When you pass it a size of 2800000 it will overflow and have unpredictable results.
You'd need to either:
- Pass a smaller value and keep samples <0.75s
- Modify the library to use int32_t for max_len_def and the other indexes

If I was you, I'd try running it at close to the max time and see if you like how it sounds (it is quite a crude time stretching algorithm and the comments in the object note - It's a bit roboty either way which is obv great and good enough for noise music.). If you like how it sounds then look to patch the object using int32_t for the indexes

Cheers Paul
 
You need to replace that and also the other indexes, I've attached two replacement files that I haven't tested.

Did you test it at maximum length (#define GRANULAR_BUFFER_SIZE 32000) to see if you actually like how it sounds?

Cheers Paul
 

Attachments

  • Archive.zip
    4.2 KB · Views: 19
Thank you Houtson.
using (#define GRANULAR_BUFFER_SIZE 32000) Audio loop playing correct but No Speed Change on Input. seemed too low buffer size.

using granularBuffer[5292000]; feel granular works . I am listening ,Freeze times are slightly better than before. In Audio result Looping is not propper.
please listen result in "A.wav" from attatchment . Speed slower/faster was working good by input.
after sometime (4-5minutes) audio became looping a small begining part of "01.wav" . Please listen result in "B.wav"
to start playback and control Speed below is my code in void loop()
C++:
 EXTMEM int16_t granularBuffer[5292000];
     const uint32_t bufferSize = sizeof(granularBuffer) / sizeof(int16_t);
    
void setup()       {

    AudioMemory(128);
                 audioShield.enable();                                            
                 audioShield.volume(0.5);
              
                 // Ensure the buffer is initialized (EXTMEM is not zeroed by default)
                      memset(granularBuffer, 0, sizeof(granularBuffer));
 
                  // Set up the granular effect to use this buffer
                   granular1.begin(granularBuffer, bufferSize);
                                 }
void loop() {
                      //----------------------SERIAL.AVALABLE-------------------------
  if (Serial.available() > 0) {
    String incomingByte = Serial.readString();                        
                           incomingByte.trim();    
 
                              if (incomingByte=="M") {
                                          Speed=Speed+ 0.5;
                                                  granular1.beginFreeze(0);
                                              granular1.setSpeed(Speed);
                                                    }                
                           if (incomingByte=="9") {
                                           Speed = Speed+0.1;
                                            granular1.beginFreeze(0);
                                         granular1.setSpeed(Speed);
                                                }
                            if (incomingByte=="8") {
                                           Speed = Speed-0.1;
                                        granular1.beginFreeze(0);
                                            granular1.setSpeed(Speed);
                                                  }
                         
                             
                                   
                            }
                           //----------------------SERIAL.AVALABLE-------------------------
                             if (!playArrayWav1.isPlaying())  {
                                                                playArrayWav1.play("01.WAV");
                                                           if  (PLAYING==false)    {
                                                                                 granular1.beginFreeze(2264);
                                                                                 PLAYING=true;
                                                                                 }
                                                              }
                              granular1.setSpeed(Speed);
                    }
i wrote 2264 for freeze duration . because it is total duration of my drum loop. by Test So far i found issue.
my drum loop of 2264 millisec Not is not playing in proper seamless looping.The back part of drum loop "01.wav" is missing!!!!
By the way, i want to have following control on playback.

--play full duration of my Selected Drum loop seamlessly in (repeat mode or Play once According to input)
--PLay it on my desired Speed.
--Stop playback .
--Re-play playback from start position
It would be great if I didn't have to put myself freeze time in code ,The entire duration of the selected .wav file is automatically absorbed into the granular effect for processing.

my .wav files sizes are under Psram capacity. Also would be great if it may play from Psram rather than Sd. how to achieve it in granular???
...................Thank you.................
 

Attachments

  • 01.zip
    168.2 KB · Views: 16
  • A.zip
    1.1 MB · Views: 13
  • B.zip
    1.2 MB · Views: 11
Last edited:
It is difficult to help when I can't see your code or test anything - small extracts of code are not helpful.

How are you selecting .wav files? The granular effects starts sampling when you run .beginFreeze - how are you aligning that with the start of your .wav (is that what you want to do?)

As I note above, the granular effect uses a crude algorithm for time stretching, if you are expecting / needing high quality audio it is probably not suitable.

Cheers, Paul
 
I think OP wants to be able to time stretch in realtime with variable playback speed.
One of the ways of doing this is via granular synthesis but they don’t always sound so great.
I’d be interested to see how this is achieved though.

A better option would be a phase vocoder, but I am not sure the T4.0 if fully capable of doing that in realtime processing. I know @PaulStoffregen was wanting to look into it a few years ago
 
Yes houtson. ...

I wanted to post full code .i posted part of code , because of Someone just told me to post only related part of code.they said ,they have no time to read full code.
you can check my running full code
C++:
#include <Arduino.h>
#include <Audio.h>
#include <SD.h>
#include <TeensyVariablePlayback.h>       
#include <SPI.h>
#include <Wire.h>                                   //  SERIAL+AUDIO+MIDI
#include <Keypad.h>

const uint8_t RowS = 7;  // 7 Rows
const uint8_t COLS = 4;  //4 columns       
char keys[RowS][COLS] = {
  { 1, 2, 3, 4 },
  { 5, 6, 7, 8 },
  { 9, 10, 11, 12 },
  { 13, 14, 15, 16 },
  { 17, 18, 19, 20 },
  { 21, 22, 23, 24 },
  { 25, 26, 27, 28 }
};
uint8_t RowPins[RowS] = { 33, 34, 35, 36, 37, 38, 39 };
uint8_t colPins[COLS] = { 40, 41, 14, 16 };
Keypad kpd = Keypad(makeKeymap(keys), RowPins, colPins, RowS, COLS);
 

       AudioPlaySdResmp        playSdWav1;
       AudioPlaySdResmp        playSdWav2;
      AudioEffectGranular   granular1;
      AudioPlaySdWav    playArrayWav1;       

       AudioMixer4            mixer1;
       AudioMixer4              mixer2;
 
       AudioOutputI2S i2s2;

       AudioConnection          patchCord1(playSdWav1, 0, mixer2, 0);
       AudioConnection          patchCord2(playSdWav1, 0, mixer2, 1);
       AudioConnection          patchCord3(playArrayWav1, 0,granular1,0 );
       AudioConnection          patchCord9(granular1,0,mixer1,0);
       AudioConnection          patchCord7(mixer1, 0, i2s2, 1);
       AudioConnection          patchCord8(mixer1, 0, i2s2, 0);

       AudioControlSGTL5000 audioShield;

#define NUM_WAVS 16 // avoid silly mistakes
 
float Speed = 1.00;
 
bool PLAYING = false;
int Song_length = 0;

 const char *SMP_WAV[NUM_WAVS] = { "01.WAV", "02.WAV", "03.WAV", "04.WAV", "05.WAV", "06.WAV", "07.WAV", "08.WAV", "09.WAV", "10.WAV", "11.WAV", "12.WAV", "13.WAV", "14.WAV", "15.WAV", "16.WAV" };
 
 
     EXTMEM int16_t granularBuffer[5292000];            //  32000 //5292000
     const uint32_t bufferSize = sizeof(granularBuffer) / sizeof(int16_t);     
    
void setup()       {
                  Serial.begin(57600);
                  if (!(SD.begin(BUILTIN_SDCARD))) {
                                                while (1) {
                                                          Serial.println("Unable to access the SD card");
                                                          delay(500);
                                                          }
                                                   }
                 kpd.setHoldTime(1500); 
                 AudioMemory(128);
                 audioShield.enable();                                               
                 audioShield.volume(0.5);
                 // Ensure the buffer is initialized (EXTMEM is not zeroed by default)
                     memset(granularBuffer, 0, sizeof(granularBuffer)); // works ww
 
                  // Set up the granular effect to use this buffer
                   granular1.begin(granularBuffer, bufferSize);    //  works ww
                 }

                    void loop() {
                      //----------------------SERIAL.AVALABLE-------------------------
  if (Serial.available() > 0) {
    String incomingByte = Serial.readString();                           
                           incomingByte.trim();     
                        
                              if (incomingByte=="M") {
                                          Speed=Speed+ 0.5; 
                                             granular1.beginFreeze(0);  //  sizes[0]  // nnnn
                                             granular1.setSpeed(Speed); 
                                           Serial.println(Speed);
                                                    }                   
                           if (incomingByte=="9") {
                                           Speed = Speed+0.1;
                                          
                                           Serial.println(Speed);
                                            granular1.beginFreeze(0); //
                                         granular1.setSpeed(Speed);
                                                }
                            if (incomingByte=="8") {   
                                           Speed = Speed-0.1;
                                           Serial.println(Speed);
                                        granular1.beginFreeze(0); // 
                                            granular1.setSpeed(Speed);
                                                  }
                            
                              
                                      
                            }
                           //----------------------SERIAL.AVALABLE-------------------------
                             if (!playArrayWav1.isPlaying())  { 
                                                                playArrayWav1.play("01.WAV"); 
                                                                
                                                           if  (PLAYING==false)    {
                                                                                 granular1.beginFreeze(2264);  // 2264
                                                                                 PLAYING=true; 
                                                                                 }
                                                              } 
                              granular1.setSpeed(Speed);
                    }
i seemed EXTMEM int16_t granularBuffer[5292000]; is int16_t.
and const uint32_t bufferSize = sizeof(granularBuffer) / sizeof(int16_t); unit32_t
is it affected thing ???it is also in library files you attached in post #13.. looking as granular effect is not allowing too large buffer size upto total capacity of psram (for 16 MB audio file).Plaese reply if any other thing you are seeing.
Thank you......
 
Last edited:
I am 90% sure that granularEffect does not allow buffer size for more than (nearly 1481miilisecons). Because of i tried granular1.beginFreeze(5000); replaced in above post#17's code.while the 2264 millisseconds .wav was playing.. i saw only (nearly 1481miilisecons) part is being repeated and controlled playback speed .Whereas I want the whole duration of selected file to be repeated for playback speed control.

It would be very kind of you. If the effect_granular.h effect_granular.cppfiles are modified accordingly,

Next- i think loading short file to psram & playing using it in granularEffect is better for me. can i do it???
if after loading file to psram , my file address in Psram became SMP_addr[0] and size is sizes[0].
what code makes it useable in granular???? i mean what should be write before void setup() in void setup() in void loop()
............Thank you............
 
Hi the accumulator was overflowing- I've update the files which should fix it. Let me know it it works for longer than 1.4s samples.

The effect_granular effect is not set up for working directly from a SD file or an array.

Confirm that it works with your longer samples and also that it is producing the quality of audio that you are expecting first.

Cheers Paul
 

Attachments

  • Archive.zip
    4.2 KB · Views: 13
Thank you Houtson ...

I am indebted to you for modifying the granular files. I recently test code with your files. I am happy to see playback running in Seamless looping.As my file is 2264 miilisec long . I am writing code to play & freeze below
C++:
 playArrayWav1.play("A01.WAV");
                                                              
                           if  (PLAYING==false)    {
                                                                                 delay(0);
                                                                                 granular1.beginFreeze(2264);   
                                                                                 PLAYING=true;
                                                                                 }
Yes.. now Granular is Freezing Complete given duration. I haven't processed a file longer than this yet. I will try and report you.
Still, how long do you think I can last?
MISSING: Playback going right using using faster/slower speed .But pitch of sample is also being affected with Speed changes. slower make pitch down .faster make pitch up!!!!!
code is used to speed:
C++:
   Speed=Speed+ 0.05;
   granular1.beginFreeze(0); 
   granular1.setSpeed(Speed);
C++:
  Speed=Speed - 0.05;
 granular1.beginFreeze(0); 
   granular1.setSpeed(Speed);
I also try : granular1.beginPitchShift(0);
C++:
  Speed=Speed - 0.05;
 granular1.beginFreeze(0);
   granular1.setSpeed(Speed);
But no changes
How can this be resolved?????????????
Thank you
 
This reply is as reminder for Post#20 . After receiving the modified files from Houston, I was able to freeze my entire sample.but using speed function code posted in post#20 and full code in post#17 , i am getting speed changes with affect pitch of sample. How to get only speed change without affect pitch?? .....
I'm asking about granular only because it can change the speed without changing the pitch. please reply.................

Thank you..
 
By google Search I found something.
1.jpg

is it useable for my requirment???
full details is in PDF pages (attached in reply) .i tried it to understand usage.but could not ...please open and take a look at this . How can I use this in my code to change playback speed without pitch?
 

Attachments

  • what is correct algorithms for teensy granular to keep pitch same while change playback speed ...pdf
    535.1 KB · Views: 17
Last edited:
Apologies for the slow reply – I’ve been away over Easter.

I think there’s a misunderstanding of what the granular object is doing. It’s not a true time-stretch algorithm, it’s replaying short grains at different speeds, so pitch change with setSpeed() is expected. It is also designed to work with streaming audio (rather than a fixed sample).

If you want to keep trying the granular object, after setting the buffer up in setup(), set the grain size small (say 40 mills) with beginPitchFreeze and set the speed with alter setSpeed, then play your sample through it. Play about with the grain size.

As I said above the this is a glitchy effect rather than a proper time stretch - the object notes say "It's a bit roboty either way which is obv great and good enough for noise music."

If you’re not aiming for noise music and want proper time stretch (independent time/pitch), I don't think this is really the right approach, you’d need something like WSOLA or a phase vocoder that Rezo mentions above. I don't think there is anything in the audio library that currently does that.
 
I am so sorry Rezo and Thank You .... I thought , like me, you also wanted to see the audio playback speed gradually increase decrease. But Houston's reply showed me that your recommendation is right for me.I thought the Phase vocoder were just a voice effect not relative to playback speed.
Thanks to Houston ...
Thank you for taking the time to reply..If the audio quality deteriorates when the speed changes in the granular effect,
then that's not what i want. As I have already said before..I want to change the speed of audio samples (short drum loop) while maintaining good quality and without changing the pitch, just like a professional audio music sampler. If I should do something else for this, please let me know.
i have 16mb psram 2 chips soldered on back of teensy 4.1, If it is needed somewhere.if only Phase vocoder is right optionfor me according to my needs, How can I start this(Phase vocoder)?.

If we look at the library there is nothing related to changing the speed of .wav files(from SD card) in the examples.

..i would like it study from begining and go ahead upto Playbackspeed changes effect.

should i start new topic with"Phase vocoder" to know more?

Please answer as much as you can.... Thank you
 
Back
Top