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

It is necessary in my code to load the samples into RAM.I removed the vocoder code and tried loading the RAM & play sample, the same files loaded very quickly in just 1 second and start play. Simple code without vocoder is as follow:

C++:
#include <Audio.h>               // WAV playing will
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include "effect_phaseVocoder.h"

AudioEffectPhaseVocoder vocoder;

 AudioOutputI2S       audioOut;
 AudioControlSGTL5000 codec;

AudioConnection patchLeft (vocoder, 0, audioOut, 0);
AudioConnection patchRight(vocoder, 0, audioOut, 1);


// RAM CODE
#define NUM_WAVS 16 // avoid silly mistakes
 const char *SMP_WAV[NUM_WAVS] = { "A01.WAV", "A02.WAV", "A03.WAV", "A04.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" };
File x_File;
int16_t *SMP_addr[NUM_WAVS];
uint32_t sizes[NUM_WAVS];

 
void setup() {
    AudioMemory(40);
    Serial.begin(57600);
     codec.enable();
     codec.volume(0.5f);

    if (!SD.begin(BUILTIN_SDCARD)) {
        Serial.println("SD init failed");
        return;
    }
     Serial.println("Card ok");
     RAM_LOAD ();        Serial.println("RAM loaded........................");
     vocoder.stop();
      vocoder.setSample(SMP_addr[0], sizes[0]/2);
        vocoder.setLoop(true);
     //   applyStretch(stretch);
        vocoder.play();
}

 
void loop() {
              }

///=========================================
            void RAM_LOAD ()  {         
              
  int SMP_FILE_NUM=0;
  for (int i = 0; i < NUM_WAVS; i++) {
                              x_File = SD.open(SMP_WAV[i], FILE_READ);
                             if (x_File)
                                         {
      sizes[i] = x_File.size();
      SMP_addr[i] = (int16_t*) extmem_malloc(sizes[i]);
      if (nullptr == SMP_addr[i])
        Serial.printf("Failed to allocate %d in EXTMEM for %s\n", sizes[i], SMP_WAV[i]);
      else     {
        if (sizes[i] != x_File.read(SMP_addr[i], sizes[i]))     
        {
          Serial.printf("Failed to read in %s - wrong length\n", SMP_WAV[i]);
          extmem_free(SMP_addr[i]); // free memory
          SMP_addr[i] = nullptr;    // mark as "not loaded"
        }
        else
          Serial.printf("Read %s into memory at %08X; %d bytes\n", SMP_WAV[i], SMP_addr[i], sizes[i]);
      }
      x_File.close();
    }
    else
      Serial.printf("Failed to open %s\n", SMP_WAV[i]);
  }
}
I'll try to slowly mix the more vocoder code into this sketch.
in vocoder.setSample(SMP_addr[3], sizes[3] / 2); i used sizes[3] / 2) only for complete duration of my drum loop.If I don't do this, then in loop mode, half the sequence plays with the SMP_addr[3] and the other half plays with some other sample. when i use vocoder.setSample(SMP_addr[3], sizes[3] / 2); Selected samples play well with complete duration.

After mixing more control code I will report what I got......
Thank you.............
 
Last edited:
If we want to load a new sample with New size into the same stretcher, do we need to clear the stretcher memory first? If yes.... What function should be called????

If no more than 4 stretches are run at a time .Considering the psram capacity, how many stretcher objects can we create using the mixer?
 
If we want to load a new sample with New size into the same stretcher, do we need to clear the stretcher memory first? If yes.... What function should be called????
If you want to load a new sample just use vocoder.setSample(newBuffer, newNumSamples);

If no more than 4 stretches are run at a time .Considering the psram capacity, how many stretcher objects can we create using the mixer?
Sorry I don't know what you mean
 
I mean, no more than four stretchers will be call to vocoder.play(); through the mixer simultaneously. I can only work with four or so at the same time.The remaining stretchers will remain stopped until further inputs are issued. something like this
str.jpg
 
Thank you Paul.. You made phase vocoder library. Using it I found some imperfections.
Should I start new thread with name "Phase vocoder" Or ask here in this thread??? I will continue after your reply..
 
Thank you Paul, I appreciate your work in Teensy Development.
Here I want to tell you the flaws I am seeing in its performance.Like this is your own example code:
C++:
// timestretch_example.ino
//
// Phase vocoder time-stretching — Teensy 4.x + Audio Shield (SGTL5000)
//
// Controls (Serial):
//   SPACE  start / restart playback
//   s      stop playback
//   p      faster  (decrease stretch)
//   q      slower  (increase stretch)
//   1-3    load and play 01.WAV / 02.WAV / 03.WAV
//   t      transient threshold: 4  (sensitive — more phase resets)
//   y      transient threshold: 8  (default)
//   u      transient threshold: 16 (subtle — fewer phase resets)
//   d      toggle profiling report
//   h      print help
//
// Optional: pot wiper → A0 (outer legs to 3.3 V and GND)
//   Pot maps to stretch STRETCH_MIN … STRETCH_MAX

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include "effect_phaseVocoder.h"

// ---------------------------------------------------------------------------
// Audio graph
// ---------------------------------------------------------------------------
AudioEffectPhaseVocoder vocoder;
// AudioOutputUSB          audioOut;
   AudioOutputI2S       audioOut;
  AudioControlSGTL5000 codec;

AudioConnection patchLeft (vocoder, 0, audioOut, 0);
AudioConnection patchRight(vocoder, 0, audioOut, 1);

// ---------------------------------------------------------------------------
// Config
// ---------------------------------------------------------------------------
static const int   POT_PIN      = A0;
static const float STRETCH_MIN  = 0.5f;   // 0.5 = half duration (2× faster)
static const float STRETCH_MAX  = 1.5f;   // 1.5 = 1.5× duration (slower)
static const int   POT_READ_MS  = 50;
static const float CONTROL_STEP = 0.01f;
static const bool  USE_POT      = false;

float stretch   = 1.0f;
float pitchSt   = 0.0f;   // pitch shift in semitones
bool  profiling = false;

// ---------------------------------------------------------------------------
// Sample buffer
// DMAMEM places in OCRAM (512 KB) instead of DTCM.
// On Teensy 4.1 with PSRAM: replace DMAMEM with EXTMEM for much larger buffers.
// ---------------------------------------------------------------------------
EXTMEM int16_t sampleBuffer[44100 * 5];  //  DMAMEM
static uint32_t sampleCount = 0;

static const char *sampleFiles[] = { "A01.WAV", "A02.WAV", "A03.WAV" };
static int currentSample = 0;

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
static float clampf(float v, float lo, float hi) {
    return v < lo ? lo : v > hi ? hi : v;
}

static void applyStretch(float newStretch) {
    stretch = clampf(newStretch, STRETCH_MIN, STRETCH_MAX);
    vocoder.setStretch(stretch);
    float durationS = stretch * (sampleCount / (float)AUDIO_SAMPLE_RATE_EXACT);
    Serial.print("x  Speed: "); Serial.print(1.0f / stretch, 2);
    Serial.print("x  Duration: "); Serial.print(durationS, 1); Serial.println("s");
}

static void printHelp() {
    Serial.println("--- Controls ---");
    Serial.println("  SPACE  start / restart");
    Serial.println("  s      stop");
    Serial.println("  p      faster");
    Serial.println("  q      slower");
    Serial.println("  1-3    load 01.WAV / 02.WAV / 03.WAV");
    Serial.println("  w      pitch up 1 semitone");
    Serial.println("  x      pitch down 1 semitone");
    Serial.println("  z      reset pitch to 0");
    Serial.println("  t      transient threshold: 4  (sensitive)");
    Serial.println("  y      transient threshold: 8  (default)");
    Serial.println("  u      transient threshold: 16 (subtle)");
    Serial.println("  d      toggle profiling");
    Serial.println("  e      print per-section costs");
    Serial.println("  h      this help");
}

// ---------------------------------------------------------------------------
// WAV loader — handles mono and stereo (stereo: left channel only).
// Reads channel count from WAV header offset 22.
// ---------------------------------------------------------------------------
static bool loadSampleFromSD(const char *filename) {
    File f = SD.open(filename);
    if (!f) {
        Serial.print("Could not open: "); Serial.println(filename);
        return false;
    }

    f.seek(22);
    int chanLo = f.read();
    int chanHi = f.read();
    if (chanLo < 0 || chanHi < 0) { f.close(); return false; }
    const uint16_t numChannels = (uint16_t)((chanHi << 8) | chanLo);

    f.seek(44);  // skip 44-byte WAV header to raw PCM data
    sampleCount = 0;
    const uint32_t maxSamples = sizeof(sampleBuffer) / sizeof(sampleBuffer[0]);

    while (f.available() && sampleCount < maxSamples) {
        int lo = f.read();
        int hi = f.read();
        if (lo < 0 || hi < 0) break;
        sampleBuffer[sampleCount++] = (int16_t)((hi << 8) | lo);
        if (numChannels == 2) {
            // skip right channel sample
            if (f.read() < 0 || f.read() < 0) break;
        }
    }
    f.close();

    Serial.print("Loaded: "); Serial.print(filename);
    Serial.print("  samples: "); Serial.print(sampleCount);
    Serial.print("  ch: "); Serial.print(numChannels);
    Serial.print("  dur: "); Serial.print(sampleCount / (float)AUDIO_SAMPLE_RATE_EXACT, 1);
    Serial.println("s");
    return sampleCount > 0;
}

static void loadAndPlay(int index) {
    currentSample = index;
    vocoder.stop();
    if (loadSampleFromSD(sampleFiles[index])) {
        vocoder.setSample(sampleBuffer, sampleCount);
        vocoder.setLoop(true);
        applyStretch(stretch);
        vocoder.play();
    }
}

// ---------------------------------------------------------------------------
// setup
// ---------------------------------------------------------------------------
void setup() {
    AudioMemory(40);
    Serial.begin(57600);
    while (!Serial && millis() < 2000) {}

      codec.enable();
      codec.volume(0.5f);

    if (!SD.begin(BUILTIN_SDCARD)) {
        Serial.println("SD init failed");
        return;
    }

    vocoder.setTransientThreshold(16.0f);
    loadAndPlay(0);
    printHelp();
}

// ---------------------------------------------------------------------------
// loop
// ---------------------------------------------------------------------------
void loop() {
    static uint32_t lastPotRead = 0;
    static uint32_t lastProf    = 0;

    if (Serial.available() > 0) {
        char key = Serial.read();
        if      (key == ' ')                { vocoder.stop(); vocoder.play(); Serial.println("Playing"); }
        else if (key == 's')                { vocoder.stop(); Serial.println("Stopped"); }
        else if (key == 'p')                applyStretch(stretch - CONTROL_STEP);  // faster
        else if (key == 'q')                applyStretch(stretch + CONTROL_STEP);  // slower
        else if (key >= '1' && key <= '3')  loadAndPlay(key - '1');
        else if (key == 'w')                { pitchSt += 1.0f; vocoder.setPitchShift(pitchSt); Serial.print("Pitch: "); Serial.print(pitchSt, 0); Serial.println(" st"); }
        else if (key == 'x')                { pitchSt -= 1.0f; vocoder.setPitchShift(pitchSt); Serial.print("Pitch: "); Serial.print(pitchSt, 0); Serial.println(" st"); }
        else if (key == 'z')                { pitchSt = 0.0f;  vocoder.setPitchShift(pitchSt); Serial.println("Pitch: 0 st"); }
        else if (key == 't')                { vocoder.setTransientThreshold(4.0f);  Serial.println("Transient threshold: 4"); }
        else if (key == 'y')                { vocoder.setTransientThreshold(8.0f);  Serial.println("Transient threshold: 8"); }
        else if (key == 'u')                { vocoder.setTransientThreshold(16.0f); Serial.println("Transient threshold: 16"); }
        else if (key == 'd')                { profiling = !profiling; Serial.println(profiling ? "Profiling: on" : "Profiling: off"); }
        else if (key == 'e')                {
            float tW, tF, tA, tS, tI, tO;
            if (vocoder.getProfilingDetailed(tW, tF, tA, tS, tI, tO)) {
                Serial.println("--- Section costs (mean µs) ---");
                Serial.print("  window fill:     "); Serial.println(tW, 1);
                Serial.print("  forward FFT:     "); Serial.println(tF, 1);
                Serial.print("  phase analysis:  "); Serial.println(tA, 1);
                Serial.print("  phase synthesis: "); Serial.println(tS, 1);
                Serial.print("  inverse FFT:     "); Serial.println(tI, 1);
                Serial.print("  OLA + output:    "); Serial.println(tO, 1);
            }
        }
        else if (key == 'h')                printHelp();
    }

    // Profiling report every 2 seconds
    if (profiling && millis() - lastProf >= 2000) {
        lastProf = millis();
        float    meanUs;
        uint32_t peakUs;
        if (vocoder.getProfiling(meanUs, peakUs)) {
            const float budgetUs = 1e6f / (AUDIO_SAMPLE_RATE_EXACT / (float)AUDIO_BLOCK_SAMPLES);
            Serial.print("update()  mean: "); Serial.print(meanUs, 1);
            Serial.print(" us  peak: ");      Serial.print(peakUs);
            Serial.print(" us  load: ");      Serial.print(meanUs / budgetUs * 100.0f, 1);
            Serial.println("%");
        }
    }

    if (USE_POT && millis() - lastPotRead >= POT_READ_MS) {
        lastPotRead = millis();
        int raw = analogRead(POT_PIN);
        applyStretch(STRETCH_MIN + (raw / 1023.0f) * (STRETCH_MAX - STRETCH_MIN));
    }
}

While listening to the time stretching of A01.wav using this code, I noticed that increasing or decreasing the stretch ratio from 1.0 has a slightly negative impact on the audio quality.Sometimes, fluctuations in the audio volume of the sample are also heard during time stretching.i have also test vocoder.setTransientThreshold with 4.0 ,8.0, 16.0 but no satisfy. I urge you to try using the attached drum loops"A01.wav" with above code. Be sure to check what you're feeling by listening to the stretch ratio from 0.5 to 1.5 through a good quality audio amp/monitor/headphones by Audio out jack of board.I believe that if you stretch it up/down yourself and listen to it carefully, you will be able to improve better..Your ability is telling, I hope you will update the library's algoritham upto professional quality audio Time Stretching.
good luck.......
 

Attachments

  • A01.zip
    309.4 KB · Views: 1
Thank you Paul, I appreciate your work in Teensy Development.
Here I want to tell you the flaws I am seeing in its performance.Like this is your own example code:
C++:
// timestretch_example.ino
//
// Phase vocoder time-stretching — Teensy 4.x + Audio Shield (SGTL5000)
//
// Controls (Serial):
//   SPACE  start / restart playback
//   s      stop playback
//   p      faster  (decrease stretch)
//   q      slower  (increase stretch)
//   1-3    load and play 01.WAV / 02.WAV / 03.WAV
//   t      transient threshold: 4  (sensitive — more phase resets)
//   y      transient threshold: 8  (default)
//   u      transient threshold: 16 (subtle — fewer phase resets)
//   d      toggle profiling report
//   h      print help
//
// Optional: pot wiper → A0 (outer legs to 3.3 V and GND)
//   Pot maps to stretch STRETCH_MIN … STRETCH_MAX

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include "effect_phaseVocoder.h"

// ---------------------------------------------------------------------------
// Audio graph
// ---------------------------------------------------------------------------
AudioEffectPhaseVocoder vocoder;
// AudioOutputUSB          audioOut;
   AudioOutputI2S       audioOut;
  AudioControlSGTL5000 codec;

AudioConnection patchLeft (vocoder, 0, audioOut, 0);
AudioConnection patchRight(vocoder, 0, audioOut, 1);

// ---------------------------------------------------------------------------
// Config
// ---------------------------------------------------------------------------
static const int   POT_PIN      = A0;
static const float STRETCH_MIN  = 0.5f;   // 0.5 = half duration (2× faster)
static const float STRETCH_MAX  = 1.5f;   // 1.5 = 1.5× duration (slower)
static const int   POT_READ_MS  = 50;
static const float CONTROL_STEP = 0.01f;
static const bool  USE_POT      = false;

float stretch   = 1.0f;
float pitchSt   = 0.0f;   // pitch shift in semitones
bool  profiling = false;

// ---------------------------------------------------------------------------
// Sample buffer
// DMAMEM places in OCRAM (512 KB) instead of DTCM.
// On Teensy 4.1 with PSRAM: replace DMAMEM with EXTMEM for much larger buffers.
// ---------------------------------------------------------------------------
EXTMEM int16_t sampleBuffer[44100 * 5];  //  DMAMEM
static uint32_t sampleCount = 0;

static const char *sampleFiles[] = { "A01.WAV", "A02.WAV", "A03.WAV" };
static int currentSample = 0;

// ---------------------------------------------------------------------------
// Helpers
// ---------------------------------------------------------------------------
static float clampf(float v, float lo, float hi) {
    return v < lo ? lo : v > hi ? hi : v;
}

static void applyStretch(float newStretch) {
    stretch = clampf(newStretch, STRETCH_MIN, STRETCH_MAX);
    vocoder.setStretch(stretch);
    float durationS = stretch * (sampleCount / (float)AUDIO_SAMPLE_RATE_EXACT);
    Serial.print("x  Speed: "); Serial.print(1.0f / stretch, 2);
    Serial.print("x  Duration: "); Serial.print(durationS, 1); Serial.println("s");
}

static void printHelp() {
    Serial.println("--- Controls ---");
    Serial.println("  SPACE  start / restart");
    Serial.println("  s      stop");
    Serial.println("  p      faster");
    Serial.println("  q      slower");
    Serial.println("  1-3    load 01.WAV / 02.WAV / 03.WAV");
    Serial.println("  w      pitch up 1 semitone");
    Serial.println("  x      pitch down 1 semitone");
    Serial.println("  z      reset pitch to 0");
    Serial.println("  t      transient threshold: 4  (sensitive)");
    Serial.println("  y      transient threshold: 8  (default)");
    Serial.println("  u      transient threshold: 16 (subtle)");
    Serial.println("  d      toggle profiling");
    Serial.println("  e      print per-section costs");
    Serial.println("  h      this help");
}

// ---------------------------------------------------------------------------
// WAV loader — handles mono and stereo (stereo: left channel only).
// Reads channel count from WAV header offset 22.
// ---------------------------------------------------------------------------
static bool loadSampleFromSD(const char *filename) {
    File f = SD.open(filename);
    if (!f) {
        Serial.print("Could not open: "); Serial.println(filename);
        return false;
    }

    f.seek(22);
    int chanLo = f.read();
    int chanHi = f.read();
    if (chanLo < 0 || chanHi < 0) { f.close(); return false; }
    const uint16_t numChannels = (uint16_t)((chanHi << 8) | chanLo);

    f.seek(44);  // skip 44-byte WAV header to raw PCM data
    sampleCount = 0;
    const uint32_t maxSamples = sizeof(sampleBuffer) / sizeof(sampleBuffer[0]);

    while (f.available() && sampleCount < maxSamples) {
        int lo = f.read();
        int hi = f.read();
        if (lo < 0 || hi < 0) break;
        sampleBuffer[sampleCount++] = (int16_t)((hi << 8) | lo);
        if (numChannels == 2) {
            // skip right channel sample
            if (f.read() < 0 || f.read() < 0) break;
        }
    }
    f.close();

    Serial.print("Loaded: "); Serial.print(filename);
    Serial.print("  samples: "); Serial.print(sampleCount);
    Serial.print("  ch: "); Serial.print(numChannels);
    Serial.print("  dur: "); Serial.print(sampleCount / (float)AUDIO_SAMPLE_RATE_EXACT, 1);
    Serial.println("s");
    return sampleCount > 0;
}

static void loadAndPlay(int index) {
    currentSample = index;
    vocoder.stop();
    if (loadSampleFromSD(sampleFiles[index])) {
        vocoder.setSample(sampleBuffer, sampleCount);
        vocoder.setLoop(true);
        applyStretch(stretch);
        vocoder.play();
    }
}

// ---------------------------------------------------------------------------
// setup
// ---------------------------------------------------------------------------
void setup() {
    AudioMemory(40);
    Serial.begin(57600);
    while (!Serial && millis() < 2000) {}

      codec.enable();
      codec.volume(0.5f);

    if (!SD.begin(BUILTIN_SDCARD)) {
        Serial.println("SD init failed");
        return;
    }

    vocoder.setTransientThreshold(16.0f);
    loadAndPlay(0);
    printHelp();
}

// ---------------------------------------------------------------------------
// loop
// ---------------------------------------------------------------------------
void loop() {
    static uint32_t lastPotRead = 0;
    static uint32_t lastProf    = 0;

    if (Serial.available() > 0) {
        char key = Serial.read();
        if      (key == ' ')                { vocoder.stop(); vocoder.play(); Serial.println("Playing"); }
        else if (key == 's')                { vocoder.stop(); Serial.println("Stopped"); }
        else if (key == 'p')                applyStretch(stretch - CONTROL_STEP);  // faster
        else if (key == 'q')                applyStretch(stretch + CONTROL_STEP);  // slower
        else if (key >= '1' && key <= '3')  loadAndPlay(key - '1');
        else if (key == 'w')                { pitchSt += 1.0f; vocoder.setPitchShift(pitchSt); Serial.print("Pitch: "); Serial.print(pitchSt, 0); Serial.println(" st"); }
        else if (key == 'x')                { pitchSt -= 1.0f; vocoder.setPitchShift(pitchSt); Serial.print("Pitch: "); Serial.print(pitchSt, 0); Serial.println(" st"); }
        else if (key == 'z')                { pitchSt = 0.0f;  vocoder.setPitchShift(pitchSt); Serial.println("Pitch: 0 st"); }
        else if (key == 't')                { vocoder.setTransientThreshold(4.0f);  Serial.println("Transient threshold: 4"); }
        else if (key == 'y')                { vocoder.setTransientThreshold(8.0f);  Serial.println("Transient threshold: 8"); }
        else if (key == 'u')                { vocoder.setTransientThreshold(16.0f); Serial.println("Transient threshold: 16"); }
        else if (key == 'd')                { profiling = !profiling; Serial.println(profiling ? "Profiling: on" : "Profiling: off"); }
        else if (key == 'e')                {
            float tW, tF, tA, tS, tI, tO;
            if (vocoder.getProfilingDetailed(tW, tF, tA, tS, tI, tO)) {
                Serial.println("--- Section costs (mean µs) ---");
                Serial.print("  window fill:     "); Serial.println(tW, 1);
                Serial.print("  forward FFT:     "); Serial.println(tF, 1);
                Serial.print("  phase analysis:  "); Serial.println(tA, 1);
                Serial.print("  phase synthesis: "); Serial.println(tS, 1);
                Serial.print("  inverse FFT:     "); Serial.println(tI, 1);
                Serial.print("  OLA + output:    "); Serial.println(tO, 1);
            }
        }
        else if (key == 'h')                printHelp();
    }

    // Profiling report every 2 seconds
    if (profiling && millis() - lastProf >= 2000) {
        lastProf = millis();
        float    meanUs;
        uint32_t peakUs;
        if (vocoder.getProfiling(meanUs, peakUs)) {
            const float budgetUs = 1e6f / (AUDIO_SAMPLE_RATE_EXACT / (float)AUDIO_BLOCK_SAMPLES);
            Serial.print("update()  mean: "); Serial.print(meanUs, 1);
            Serial.print(" us  peak: ");      Serial.print(peakUs);
            Serial.print(" us  load: ");      Serial.print(meanUs / budgetUs * 100.0f, 1);
            Serial.println("%");
        }
    }

    if (USE_POT && millis() - lastPotRead >= POT_READ_MS) {
        lastPotRead = millis();
        int raw = analogRead(POT_PIN);
        applyStretch(STRETCH_MIN + (raw / 1023.0f) * (STRETCH_MAX - STRETCH_MIN));
    }
}

While listening to the time stretching of A01.wav using this code, I noticed that increasing or decreasing the stretch ratio from 1.0 has a slightly negative impact on the audio quality.Sometimes, fluctuations in the audio volume of the sample are also heard during time stretching.i have also test vocoder.setTransientThreshold with 4.0 ,8.0, 16.0 but no satisfy. I urge you to try using the attached drum loops"A01.wav" with above code. Be sure to check what you're feeling by listening to the stretch ratio from 0.5 to 1.5 through a good quality audio amp/monitor/headphones by Audio out jack of board.I believe that if you stretch it up/down yourself and listen to it carefully, you will be able to improve better..Your ability is telling, I hope you will update the library's algoritham upto professional quality audio Time Stretching.
good luck.......

Having examined the audio library supplied with Teensyduino I cannot find the example you mention above. I do not believe that it is Paul's code.
 
Back
Top