Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Realtime example of using SuperpoweredTimeStretching #256

Closed
garynewby opened this issue Mar 11, 2017 · 6 comments
Closed

Realtime example of using SuperpoweredTimeStretching #256

garynewby opened this issue Mar 11, 2017 · 6 comments

Comments

@garynewby
Copy link

garynewby commented Mar 11, 2017

Any chance of posting a snippet outlining usage of SuperpoweredTimeStretching in the realtime audio callback?

I've tried utilizing the relevant parts of the SuperpoweredOfflineProcessingExample, but it looks like I need to incorporate a ring buffer as SuperpoweredTimeStretching produces a variable amount of samples and the audio buffer is fixed size. Using SuperpoweredAudiopointerList maybe the key but I don't understand it's usage from just the docs.

@superpoweredSDK
Copy link
Collaborator

Untested example code:

typedef struct liveTimeStretchingHandler {
    SuperpoweredTimeStretching *timeStretcher;
    SuperpoweredAudiopointerList *outputBuffers;
} liveTimeStretchingHandler;
static void setupLiveTimeStretching(liveTimeStretchingHandler *handler, int currentSamplerate) {
    handler->timeStretcher = new SuperpoweredTimeStretching(currentSamplerate);
    handler->outputBuffers = new SuperpoweredAudiopointerList(8, 16);
}
static void liveTimeStretchingProcess(float *outputBuffer, int numberOfSamples, int64_t *samplePositionOfTheFirstSampleInOutputBuffer, liveTimeStretchingHandler *handler) {
    while (numberOfSamples > 0) {
        // Try to fulfill the request from the output buffers first.
        int numberOfSamplesFromOutputBuffers = (numberOfSamples < handler->outputBuffers->sampleLength) ? numberOfSamples : handler->outputBuffers->sampleLength;

        if (handler->outputBuffers->makeSlice(0, numberOfSamplesFromOutputBuffers)) {
            *samplePositionOfTheFirstSampleInOutputBuffer = handler->outputBuffers->nextSamplePosition();
            numberOfSamplesFromOutputBuffers = 0;

            while (true) {
                int numSamples = 0;
                float *timeStretchedAudio = (float *)handler->outputBuffers->nextSliceItem(&numSamples);
                if (!timeStretchedAudio) break;

                // Incorporating this whole liveTimeStretchingProcess() method into your processing loop would be better,
                // as this memcpy could be done something useful instead of just copying.
                memcpy(outputBuffer, timeStretchedAudio, numSamples * 8);

                outputBuffer += numSamples * 2;
                numberOfSamplesFromOutputBuffers += numSamples;
            };

            handler->outputBuffers->truncate(numberOfSamplesFromOutputBuffers, true);
            numberOfSamples -= numberOfSamplesFromOutputBuffers;
            if (numberOfSamples < 1) break;
        }

        // There were not enough samples in the output buffers at this point. Let's feed the time stretcher.
        SuperpoweredAudiobufferlistElement inputBuffer;

        // This helps you tracking the current position in your music.
        // You can leave it at zero too, but samplePositionOfTheFirstSampleInOutputBuffer will not reflect the current position in this case.
        inputBuffer.samplePosition = 0;

        inputBuffer.startSample = 0;
        inputBuffer.samplesUsed = 0;
        inputBuffer.endSample = handler->timeStretcher->numberOfInputSamplesNeeded;
        inputBuffer.buffers[0] = SuperpoweredAudiobufferPool::getBuffer(handler->timeStretcher->numberOfInputSamplesNeeded * 8 + 64);
        inputBuffer.buffers[1] = inputBuffer.buffers[2] = inputBuffer.buffers[3] = NULL;

        // YOUR TODO HERE: Produce handler->timeStretcher->numberOfInputSamplesNeeded samples into inputBuffer.buffers[0], interleaved floating point audio.
        
        handler->timeStretcher->process(&inputBuffer, handler->outputBuffers);
    }
}

@garynewby
Copy link
Author

That's awesome, thank you.

@AndrewsAlves
Copy link

What to do at
// YOUR TODO HERE: Produce handler->timeStretcher->numberOfInputSamplesNeeded samples into inputBuffer.buffers[0], interleaved floating point audio.

???

@LucasVanDongen
Copy link

LucasVanDongen commented Oct 23, 2017

I tried to adapt the example to make it work for me, but the only thing I hear is a static buzz like the 512 sample buffer loops over and over.

static bool audioProcessing(void *clientdata,
                            float **buffers,
                            unsigned int inputChannels,
                            unsigned int outputChannels,
                            unsigned int numberOfSamples,
                            unsigned int samplerate,
                            uint64_t hostTime) {
    __unsafe_unretained Superpowered *self = (__bridge Superpowered *)clientdata;
    //int64_t *samplePositionOfTheFirstSampleInOutputBuffer = 0; // Seems to be passed in
    //float outputBuffer[numberOfSamples * 2 + 16];
    float lalaBuffer[numberOfSamples * 2 + 16]; // Why do I need to do this intermediary step?
    SuperpoweredInterleave(buffers[0], buffers[1], lalaBuffer, numberOfSamples);
    float *outputBuffer = lalaBuffer;

    while (numberOfSamples > 0) {
        // Try to fulfill the request from the output buffers first.
        int numberOfSamplesFromOutputBuffers = (numberOfSamples < self->outputBuffers->sampleLength) ? numberOfSamples : self->outputBuffers->sampleLength;
        
        if (self->outputBuffers->makeSlice(0, numberOfSamplesFromOutputBuffers)) {
            //*samplePositionOfTheFirstSampleInOutputBuffer = self->outputBuffers->nextSamplePosition();
            numberOfSamplesFromOutputBuffers = 0;
            
            while (true) {
                int numSamples = 0;
                float *timeStretchedAudio = (float *)self->outputBuffers->nextSliceItem(&numSamples);
                if (!timeStretchedAudio) {
                    break;
                }
                
                // Incorporating this whole liveTimeStretchingProcess() method into your processing loop would be better,
                // as this memcpy could be done something useful instead of just copying.
                memcpy(outputBuffer, timeStretchedAudio, numSamples * 8);
                
                outputBuffer += numSamples * 2;
                numberOfSamplesFromOutputBuffers += numSamples;
            };
            
            self->outputBuffers->truncate(numberOfSamplesFromOutputBuffers, true);
            numberOfSamples -= numberOfSamplesFromOutputBuffers;
            if (numberOfSamples < 1) {
                break;
            }
        }
        
        // There were not enough samples in the output buffers at this point. Let's feed the time stretcher.
        SuperpoweredAudiobufferlistElement inputBuffer;
        
        // This helps you tracking the current position in your music.
        // You can leave it at zero too, but samplePositionOfTheFirstSampleInOutputBuffer will not reflect the current position in this case.
        inputBuffer.samplePosition = 0;
        
        inputBuffer.startSample = 0;
        inputBuffer.samplesUsed = 0;
        inputBuffer.endSample = self->timeStretcher->numberOfInputSamplesNeeded;
        inputBuffer.buffers[0] = SuperpoweredAudiobufferPool::getBuffer(self->timeStretcher->numberOfInputSamplesNeeded * 8 + 64);
        inputBuffer.buffers[1] = inputBuffer.buffers[2] = inputBuffer.buffers[3] = NULL;
        
        self->timeStretcher->process(&inputBuffer, self->outputBuffers);
        //self->timeStretcher->
        // YOUR TODO HERE: Produce handler->timeStretcher->numberOfInputSamplesNeeded samples into inputBuffer.buffers[0], interleaved floating point audio.
        //self->timeStretcher->numberOfInputSamplesNeeded
    }

    return true;
}

@temkich
Copy link

temkich commented Nov 6, 2017

What to do at
// YOUR TODO HERE ?

if i do like this:

int samples = self->timeStretcher->numberOfInputSamplesNeeded;
        float *timeStretchedAudio = (float *)self->outputBuffers->nextSliceItem(&samples);
        if (timeStretchedAudio != 0) {
            SuperpoweredDeInterleave(timeStretchedAudio, buffers[0], buffers[1], numberOfSamples);
        }

in output no effect. what i do wrong?

@skopintsevDima
Copy link

Where I need to use methods setupLiveTimeStretching and liveTimeStretchingProcess?
Can you share example of implementaions of TODO mark?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants