Вопрос

To my knowledge, the Web Audio API in google Chrome (v21) does not support the following:

    source.playbackRate.value = -1; 

I very much wish! I will be patient, but in the meantime, this post has a nice alternative solution. I have adopted it to try and reverse my own audio samples loaded from a loaded bufferlist, hoping that I can have both a forward and reversed version of each loaded buffer, like so:

    function finishedLoading(bufferList)  {
        for (var it = 0; it < this.urlList.length; ++it) {  
            storedBuffer[it] = bufferList[it]; // assign bufferList to globals
            storedBufferR[it] = bufferList[it];

            // attempt to reverse storedBufferR only ...
            Array.prototype.reverse.call( storedBufferR[it].getChannelData(0) );
            Array.prototype.reverse.call( storedBufferR[it].getChannelData(1) ); 
        }
    }

The above function indeed reverses playback, however it reverses both 'storedbufferR' and 'storedbuffer' such that all buffers are reversed!

So here is where I get lost... I understand that Array.protoype affects all arrays, so I suppose I can see how 'storedBuffer' is affected by a reverse method on 'storedBufferR'. EDIT: the reverse method only affects the array in question

But is it possible to rewrite the above function to ensure array.protoype affects only the stored buffer I want reversed? If not, is there another way to go about storing both a forward and reversed version?

Это было полезно?

Решение

The comment about the two AudioBuffers sharing the same reference was on the right track, but the solution isn't to create a new AudioContext; rather, you just need to create a new AudioBuffer and clone the underlying Float32Arrays that hold the actual audio samples.

For example, this function would clone an AudioBuffer:

function cloneAudioBuffer(audioBuffer){
    var channels = [],
        numChannels = audioBuffer.numberOfChannels;

    //clone the underlying Float32Arrays
    for (var i = 0; i < numChannels; i++){
        channels[i] = new Float32Array(audioBuffer.getChannelData(i));
    }

    //create the new AudioBuffer (assuming AudioContext variable is in scope)
    var newBuffer = context.createBuffer(
                        audioBuffer.numberOfChannels,
                        audioBuffer.length,
                        audioBuffer.sampleRate
                    );

    //copy the cloned arrays to the new AudioBuffer
    for (var i = 0; i < numChannels; i++){
        newBuffer.getChannelData(i).set(channels[i]);
    }

    return newBuffer;
}

Then, to modify the above...

function finishedLoading(bufferList)  {
    for (var it = 0; it < this.urlList.length; ++it) {  
        storedBuffer[it] = bufferList[it]; // assign bufferList to globals
        storedBufferR[it] = cloneAudioBuffer(bufferList[it]);

        // attempt to reverse storedBufferR only ...
        Array.prototype.reverse.call( storedBufferR[it].getChannelData(0) );
        Array.prototype.reverse.call( storedBufferR[it].getChannelData(1) ); 
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top