About the use of resampling


#1

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


#2

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


#3

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


#4

Sure. Sample rate and playback rate is pretty much the same thing. The number of samples per second. Resampling is for changing that number.


#5

OK, thanks guys, I wasn’t 100% sure of that.

all the best

geoffroy


#6

basically, yes that’s how it is supposed to work


#7

thanks kraken
now I’m trying to use Laurent de Soras resampler library…


#8

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…


#9