dennis dennis - 28 days ago 20
Javascript Question

Cut and Paste audio using web audio api and wavesurfer.js

I am currently trying to make a web editor allowing users to easily adjust basic settings to their audio files, as a plugin I've integrated wavesurfer.js as it has a very neat and cross-browser solution for it's waveform.

After indexing a must-have list for the functionalities I've decided that the cut and paste are essential for making this product work, however after spending hours of trying to figure out how to implement this in the existing library and even starting to rebuild the wavesurfer.js functionalities from scratch to understand the logic I have yet to succeed.

My question would be if anyone can give me some pointers on how to start building a cut and paste functionality or maybe even an example that would be greatly appreciated.

Thanks in advance!

wavesurfer plugin:
http://wavesurfer-js.org

plucked web editor
http://plucked.de

EDIT Solution (instance is the wavesurfer object.):

function cut(instance){
var selection = instance.getSelection();
if(selection){
var original_buffer = instance.backend.buffer;
var new_buffer = instance.backend.ac.createBuffer(original_buffer.numberOfChannels, original_buffer.length, original_buffer.sampleRate);

var first_list_index = (selection.startPosition * original_buffer.sampleRate);
var second_list_index = (selection.endPosition * original_buffer.sampleRate);
var second_list_mem_alloc = (original_buffer.length - (selection.endPosition * original_buffer.sampleRate));

var new_list = new Float32Array( parseInt( first_list_index ));
var second_list = new Float32Array( parseInt( second_list_mem_alloc ));
var combined = new Float32Array( original_buffer.length );

original_buffer.copyFromChannel(new_list, 0);
original_buffer.copyFromChannel(second_list, 0, second_list_index)

combined.set(new_list)
combined.set(second_list, first_list_index)

new_buffer.copyToChannel(combined, 0);

instance.loadDecodedBuffer(new_buffer);
}else{
console.log('did not find selection')
}
}

Answer

Reading this answer suggests you can create an empty AudioBuffer of the size of the audio segment you want to copy (size = length in seconds ⨉ sample rate), then fill its channel data with the data from the segment.

So the code might be like this:

var originalBuffer = wavesurfer.backend.buffer;
var emptySegment = wavesurfer.backend.ac.createBuffer(
    originalBuffer.numberOfChannels,
    segmentDuration * originalBuffer.sampleRate,
    originalBuffer.sampleRate
);
for (var i = 0; i < originalBuffer.numberOfChannels; i++) {
    var chanData = originalBuffer.getChannelData(i);
    var segmentChanData = emptySegment.getChannelData(i);
    for (var j = 0, len = chanData.length; j < len; j++) {
        segmentChanData[j] = chanData[j];
    }
}

emptySegment; // Here you go!
              // Not empty anymore, contains a copy of the segment!
Comments