Go Down

Topic: Success getting TMRpcm to change the pitch and speed of sounds (Read 1 time) previous topic - next topic

Ozerik

Thanks to an old post here I inserted some code into the TMRpcm library, and getting it to play clips with a variable speed and pitch by changing the sample rate for each time the sound file is played.

In file TRMpcm.cpp I changed these two lines:

Code: [Select]

    SAMPLE_RATE = sFile.read();
    SAMPLE_RATE = sFile.read() << 8 | SAMPLE_RATE;


to these four lines of code:

Code: [Select]


    SAMPLE_RATE = sFile.read();  // you need these two reads just to make sure that
    SAMPLE_RATE = sFile.read();  //  the file pointer is in the right place for later code
    int pot = analogRead(A0);      // or what ever the pot is on
    SAMPLE_RATE = map(pot, 0, 1023, 8000, 44000);



It works PERFECTLY!!! Problem: the sample rate and therefore pitch/speed are only changed at the beginning of each playback event, which is no biggie for my project. But if I wanted to change the sample rate mid-playback, how..... how would I do that???

Grumpy_Mike

Quote
But if I wanted to change the sample rate mid-playback,
Can you explain what you mean by that, that has me confused.

Ozerik

Can you explain what you mean by that, that has me confused.
Sure, I want pitch/speed (basically, the sample playback rate) to change in the middle of playing a sound. At the moment, it only detects the sample rate when the clip starts to be played.

Grumpy_Mike

Not sure you can do that. As it would mean receiving MIDI messages while you are outputting the samples. When you do that what you are producing will glitch as you will interfere with the sample rate.

Lucario448

I think this is how (assuming you're using a 16-bit timer):

Code: [Select]
unsigned long newSR = map(analogRead(A0), 0, 1023, 8000, 44100);

if (bitRead(optionByte,6)) *ICRn[tt] = 10 * (800000 /  newSR);
else *ICRn[tt] = 10 * (1600000 / newSR);

optionByte and ICRn are actually global variables, so there should be no problem in using them anywhere (at compiling time though); furthermore no library modification required.
Although not sure if there would be a side effect since this also changes PWM's (carrier) frequency, and if the duty cycle (outputted sample's value) will be scaled accordingly.

spdif

I think this is how (assuming you're using a 16-bit timer):

Code: [Select]
unsigned long newSR = map(analogRead(A0), 0, 1023, 8000, 44100);

if (bitRead(optionByte,6)) *ICRn[tt] = 10 * (800000 /  newSR);
else *ICRn[tt] = 10 * (1600000 / newSR);

optionByte and ICRn are actually global variables, so there should be no problem in using them anywhere (at compiling time though); furthermore no library modification required.
Although not sure if there would be a side effect since this also changes PWM's (carrier) frequency, and if the duty cycle (outputted sample's value) will be scaled accordingly.
Hello there.

How to exactly implement this code? I am unable to do it... Please help!

Thanx.

Lucario448

Put it anywhere in your code (as long as TMRpcm.h is included), you can even wrap this snippet into a function if you wish...

spdif

Put it anywhere in your code (as long as TMRpcm.h is included), you can even wrap this snippet into a function if you wish...
Thanx! I tried it earlier also but i get the "optionByte was not declared in this scope" error.

optionByte is a Global variable and could be accessed from anywhere as you said but...

TMRpcm.h is included in the sketch and the code is in the loop section.

Grumpy_Mike

That means you are doing something wrong that you don't know. Please post the code ( using code tags ) of your sketch.
Quote
TMRpcm.h is included in the sketch
Where have you put this file, not in the sketch itself.

spdif

Maybe I am doing something wrong. Here is the code

Code: [Select]

#include <SD.h>                      // need to include the SD library
//#define SD_ChipSelectPin 53  //example uses hardware SS pin 53 on Mega2560
#define SD_ChipSelectPin 4  //using digital pin 4 on arduino nano 328, can use other pins
#include <TMRpcm.h>           //  also need to include this library...
#include <SPI.h>

TMRpcm tmrpcm;   // create an object for use in this sketch

unsigned long time = 0;

unsigned long newSR ;

  tmrpcm.speakerPin = 9; //5,6,11 or 46 on Mega, 9 on Uno, Nano, etc
  //Complimentary Output or Dual Speakers:
  //pinMode(10,OUTPUT); Pin pairs: 9,10 Mega: 5-2,6-7,11-12,46-45
  
  Serial.begin(115200);
  pinMode(13,OUTPUT); //LED Connected to analog pin 0
  if (!SD.begin(SD_ChipSelectPin)) {  // see if the card is present and can be initialized:
    Serial.println("SD fail");  
    return;   // don't do anything more if not

  }
  else{  
    Serial.println("SD ok");  
  }
  //tmrpcm.play("idleNew.wav"); //the sound file "music" will play each time the arduino powers up, or is reset
}



void loop(){  

newSR = map(analogRead(A0), 0, 1023, 8000, 44100);

if (bitRead(optionByte,6)) *ICRn[tt] = 10 * (800000 /  newSR);
else *ICRn[tt] = 10 * (1600000 / newSR);

if (!tmrpcm.isPlaying()) {
    tmrpcm.play("idleNew.wav");
    
  }

 
}




[code]
[/code]


Grumpy_Mike

Well it was the idea of Lucario448 who seems to have gone away. I would try a PM to see if he is still around.

Go Up