Hello
I have a dumb question.
I want to play an audio file slower than normal.
So basically, I want to change the playback rate.
If I want to play it an octave lower, I can play it at speed 0.5
For this, should I use resampling ?
I understand that resampling is to play a file at the same playback rate, but to change the output sampling rate.
Can I use the same algorithm to change the sampling rate and to change the playback rate ?
Thanks for the insight
geoffroy
no resampling means playing at a different rate. if you play the file at the same playback rate, you actually are not doing resampling at all…
probably you have confused resampling with time-stretching
No, I didn’t mean timestretching.
Imagine I have an input file at 48khz
My audio driver is 44,1 khz
I want to play the input file twice slower. It will be twice longer also of course (no timestretching).
Does it mean I can use a resampler with the following speed
speed = 0.5 * 48/44.1
?
best
geoffroy
Sure. Sample rate and playback rate is pretty much the same thing. The number of samples per second. Resampling is for changing that number.
OK, thanks guys, I wasn’t 100% sure of that.
all the best
geoffroy
basically, yes that’s how it is supposed to work
thanks kraken
now I’m trying to use Laurent de Soras resampler library…
ehe that’s cool stuff. if you want, here is some interesting code (on how to use that library for oscillator playback):
class MipMapOscillator : public AudioSource
{
public:
//! Constructor
MipMapOscillator() :
data(0),
waveSize(0),
buffer(0),
incrementPhase(0.0f)
{
}
//! Destructor
virtual ~MipMapOscillator()
{
if (buffer)
delete buffer;
}
//==============================================================================
/** Implementation of the SynthVoice method. */
void startPlayback()
{
Int64 pos = static_cast <Int64>(0) << 32 ;
pos += static_cast <Int64> (waveSize * 16) << 32;
resampler.clear_buffers();
resampler.set_playback_pos( pos );
currentPhase = 0.0;
}
/** Implementation of the SynthVoice method. */
void stopPlayback()
{
}
/** Implementation of the SynthVoice method. */
void releasePlayback()
{
}
//==============================================================================
/** Sets the signal's amplitude. */
void setAmplitude (const float newAmplitude)
{
amplitude = newAmplitude;
}
/** Sets the signal's frequency. */
void setFrequency (const double newFrequencyHz)
{
frequency = newFrequencyHz;
long pitch = ((1L << ResamplerFlt::NBR_BITS_PER_OCT) / 1200);
pitch = (long)( pitch * log(frequency / (sampleRate / (double)waveSize)) / log(2.0) * 1200 );
resampler.set_pitch( pitch );
}
/** Set the current playing sample */
void setSampleBuffer( MipMapSampleBuffer* smpl )
{
data = smpl->getMipMap();
waveSize = smpl->getSize();
totalSize = smpl->getTotalSize();
resampler.set_sample( *data );
resampler.set_interp( interpolator );
}
//==============================================================================
/** Implementation of the AudioSource method. */
void prepareToPlay (int samplesPerBlockExpected, double newSampleRate)
{
if( buffer && buffer->getNumSamples() != samplesPerBlockExpected ) {
delete buffer;
buffer = 0;
}
if( !buffer )
buffer = new AudioSampleBuffer(1,samplesPerBlockExpected);
buffer->clear();
sampleRate = newSampleRate;
}
/** Implementation of the AudioSource method. */
void releaseResources()
{
}
//==============================================================================
/** Implementation of the AudioSource method. */
void getNextAudioBlock (const AudioSourceChannelInfo& info)
{
float* out = buffer->getSampleData(0);
Int64 pos = resampler.get_playback_pos();
if ((pos >> 32) > (totalSize >> 1))
{
// Simulate "loop" by going back to the begining
pos &= (static_cast <Int64> (waveSize) << 32) - 1;
// But skip a few periods in order to ensure that we get the
// periodic waveform part on highest MIP-map levels.
// first period
pos += static_cast <Int64> (waveSize * 16) << 32;
resampler.set_playback_pos( pos );
}
resampler.interpolate_block( out, info.numSamples );
for (int j = info.buffer->getNumChannels(); --j >= 0;)
info.buffer->copyFrom( j,
info.startSample,
*buffer,
0,
0,
info.numSamples);
info.buffer->applyGain(info.startSample,info.numSamples,amplitude);
}
public:
InterpPack interpolator;
ResamplerFlt resampler;
MipMapFlt* data; // < the mipmap
unsigned long waveSize; // < size of each wave
unsigned long totalSize; // < size of wave
AudioSampleBuffer* buffer;
float incrementPhase;
double frequency, sampleRate;
double currentPhase, phasePerSample;
float amplitude;
};
that’s a bit old, but you can find some useful function, especially the one that convert frequency from (float) Hz to (long) pitch the library expects…