About the use of resampling

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…