changing pitch of audio samples - TeensyVariablePlayback library

Thanks for your help, but I think we're currently not on the same page.

I need help to understand the use of the looping functions to play a sound repeatedly without any audible interruptions.
 
Slightly surprised that you're surprised by the "audible interruptions", given that your audio file fades in at the start and out at the end, so there's about 0.5s of near-silence if it's looped without setting start and finish points.

Here's an edit of your code which works, as far as I can tell:
C++:
#include <Arduino.h>
#include <Audio.h>
#include <SD.h>
#include <TeensyVariablePlayback.h>

// GUItool: begin automatically generated code
AudioPlaySdResmp         playSdWav1;     //xy=324,457
AudioOutputI2S           i2s2;           //xy=840.8571472167969,445.5714416503906
AudioConnection          patchCord1(playSdWav1, 0, i2s2, 0);
AudioConnection          patchCord2(playSdWav1, 0, i2s2, 1);
AudioControlSGTL5000     audioShield;
// GUItool: end automatically generated code

double getPlaybackRate(int16_t analog);

char* _filename = "SPACE.WAV";

void setup() {
    Serial.begin(9600);

    if (!(SD.begin(10))) {
        // stop here if no SD card, but print a message
        while (1) {
            Serial.println("Unable to access the SD card");
            delay(500);
        }
    }

    AudioMemory(24);

    audioShield.enable();
    audioShield.volume(0.5);

    playSdWav1.enableInterpolation(true);
    playSdWav1.setPlaybackRate(1.0);

    playSdWav1.playWav(_filename);
    playSdWav1.setLoopType(looptype_repeat);

    // Sound sample isn't seamless, so pick some loop points
    playSdWav1.setLoopStart(19374);
    playSdWav1.setLoopFinish(643346);

    // Extra stuff to mask glitches at loop point
    playSdWav1.setUseDualPlaybackHead(true);
    playSdWav1.setCrossfadeDurationInSamples(1000);
}

float rate=1.0f, factor = 1.001f;
uint32_t next;
bool increasing;
void loop() {
    int newsensorValue = analogRead(A0);

    // I don't have a sensor, so just ramp rate up and down
    if (millis() >= next)
    {
      next = millis() + 3; // every 3ms, i.e. roughly every audio update

      if (increasing)
      {
        rate *= factor;
        increasing = rate < 2.0f;
      }
      else
      {
        rate /= factor;
        increasing = rate < 0.5f;
      }
      playSdWav1.setPlaybackRate(rate);
    }

    if(!playSdWav1.isPlaying()) {
      Serial.println("Restarted playback"); // This Never Happens
      playSdWav1.playWav(_filename);
    }
}

// map analog input 0-1023 to 0.5-3.0 pitch
double getPlaybackRate(int16_t analog) { //analog: 0..1023
    return ((analog / 1023) * 2.5) + 0.5;
}
 
Image of WAV file supplied, showing loop points I selected
1744402502246.png
 
I can't believe that I missed that the sound fades in and out, sorry for that. Will try the code and thank you a lot already
 
Slightly surprised that you're surprised by the "audible interruptions", given that your audio file fades in at the start and out at the end, so there's about 0.5s of near-silence if it's looped without setting start and finish points.

Here's an edit of your code which works, as far as I can tell:
C++:
#include <Arduino.h>
#include <Audio.h>
#include <SD.h>
#include <TeensyVariablePlayback.h>

// GUItool: begin automatically generated code
AudioPlaySdResmp         playSdWav1;     //xy=324,457
AudioOutputI2S           i2s2;           //xy=840.8571472167969,445.5714416503906
AudioConnection          patchCord1(playSdWav1, 0, i2s2, 0);
AudioConnection          patchCord2(playSdWav1, 0, i2s2, 1);
AudioControlSGTL5000     audioShield;
// GUItool: end automatically generated code

double getPlaybackRate(int16_t analog);

char* _filename = "SPACE.WAV";

void setup() {
    Serial.begin(9600);

    if (!(SD.begin(10))) {
        // stop here if no SD card, but print a message
        while (1) {
            Serial.println("Unable to access the SD card");
            delay(500);
        }
    }

    AudioMemory(24);

    audioShield.enable();
    audioShield.volume(0.5);

    playSdWav1.enableInterpolation(true);
    playSdWav1.setPlaybackRate(1.0);

    playSdWav1.playWav(_filename);
    playSdWav1.setLoopType(looptype_repeat);

    // Sound sample isn't seamless, so pick some loop points
    playSdWav1.setLoopStart(19374);
    playSdWav1.setLoopFinish(643346);

    // Extra stuff to mask glitches at loop point
    playSdWav1.setUseDualPlaybackHead(true);
    playSdWav1.setCrossfadeDurationInSamples(1000);
}

float rate=1.0f, factor = 1.001f;
uint32_t next;
bool increasing;
void loop() {
    int newsensorValue = analogRead(A0);

    // I don't have a sensor, so just ramp rate up and down
    if (millis() >= next)
    {
      next = millis() + 3; // every 3ms, i.e. roughly every audio update

      if (increasing)
      {
        rate *= factor;
        increasing = rate < 2.0f;
      }
      else
      {
        rate /= factor;
        increasing = rate < 0.5f;
      }
      playSdWav1.setPlaybackRate(rate);
    }

    if(!playSdWav1.isPlaying()) {
      Serial.println("Restarted playback"); // This Never Happens
      playSdWav1.playWav(_filename);
    }
}

// map analog input 0-1023 to 0.5-3.0 pitch
double getPlaybackRate(int16_t analog) { //analog: 0..1023
    return ((analog / 1023) * 2.5) + 0.5;
}
Just wanted to report back that the code works. Thanks!

I removed the fade in Audacity, so I removed setLoopStart() and setLoopFinish() aswell.
When I extend the crossfade, the loop is almost inaudible.
 
Back
Top