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

Cut & Paste Audio #419

Closed
cskonopka opened this issue Mar 26, 2015 · 15 comments
Closed

Cut & Paste Audio #419

cskonopka opened this issue Mar 26, 2015 · 15 comments
Labels

Comments

@cskonopka
Copy link

I saw this post by katspaugh on stack and was curious if there are any examples of this floating around. There is a piece of potential example code I've tried to abstract but haven't had any luck.

http://stackoverflow.com/questions/24551854/cut-and-paste-audio-using-web-audio-api-and-wavesurfer-js

@thijstriemstra
Copy link
Contributor

Without reading the whole stackoverflow post, can you state in one sentence what you'd like to see supported in wavesurfer.js?

@cskonopka
Copy link
Author

Sure.

"A function that creates/fills an empty buffer source by creating a copy of the current buffer source that has a specific start and end point."

Some of the code is in the stack post.

@allannaranjo
Copy link

This will take a wavesurfer buffer and will create a smaller version with
the selected area, the function will return a new blob, from which you can
redraw the wavesurfer.

Allan

EXTRACTED FROM A PRIVATE PROJECT IF YOU NEED MORE INFO LET ME KNOW:

var app = {
 trimBlob : function(params){

/*
 EXTRACTED FROM A PRIVATE PROJECT
IF YOU NEED MORE INFO LET ME KNOW:

allan.naranjo@gmail.com
---------------------------------------------
This method works with wavesurfer.
Make a selection, using wavesurfer api take the start and end.
---------------------------------------------
The function will take the buffer used to create the waveform and will
create
a new blob with the selected area from the original blob using the
offlineAudioContext

*/

var self = this;
var start = params.start;
var end = params.end;

var originalAudioBuffer;


originalAudioBuffer = params.wavesurfer.backend.buffer;

var lengthInSamples = Math.floor( (end - start) *
originalAudioBuffer.sampleRate );

var offlineAudioContext = new webkitOfflineAudioContext(1, 2,
originalAudioBuffer.sampleRate );
 var
new_channel_data,empty_segment_data,original_channel_data,before_data,after_data;

var emptySegment = offlineAudioContext.createBuffer(
originalAudioBuffer.numberOfChannels,lengthInSamples,
originalAudioBuffer.sampleRate );

var newAudioBuffer = offlineAudioContext.createBuffer(
originalAudioBuffer.numberOfChannels,
(start === 0 ? (originalAudioBuffer.length - emptySegment.length) :
originalAudioBuffer.length)
, originalAudioBuffer.sampleRate);

for (var channel = 0; channel < originalAudioBuffer.numberOfChannels;
channel++) {

new_channel_data = newAudioBuffer.getChannelData(channel);
empty_segment_data = emptySegment.getChannelData(channel);
original_channel_data = originalAudioBuffer.getChannelData(channel);

before_data = original_channel_data.subarray(0, start *
originalAudioBuffer.sampleRate);
after_data = original_channel_data.subarray(Math.floor(end *
originalAudioBuffer.sampleRate), (originalAudioBuffer.length *
originalAudioBuffer.sampleRate));

if(start > 0){
new_channel_data.set(before_data);
new_channel_data.set(empty_segment_data,(start *
newAudioBuffer.sampleRate));
new_channel_data.set(after_data,(end * newAudioBuffer.sampleRate));
} else {
new_channel_data.set(after_data);
}

}

var arraybuffer = buffer2wav(newAudioBuffer);//Will create a new Blob with
the IntArray...


return (new Blob([arraybuffer], { type : 'audio/wav'}));

 }
}

On Thu, Mar 26, 2015 at 5:48 PM, Christopher Konopka <
notifications@github.com> wrote:

Sure.

"A function that creates/fills an empty buffer source by creating a copy
of the current buffer source that has a specific start and end point."

Some of the code is in the stack post.


Reply to this email directly or view it on GitHub
#419 (comment)
.

@cskonopka
Copy link
Author

Thanks! I will try it out in a little bit. Really appreciate the help. :)

@katspaugh
Copy link
Owner

@cskonopka closing it now. Feel free to reopen if you have more questions.

@cskonopka
Copy link
Author

@allannaranjo Sorry about the delay, a bunch of stuff came up and haven't been able to focus on this idea. Is it possible to provide more information? I understand the logic but I can't quite implement it properly.

@proehlen
Copy link

proehlen commented May 4, 2016

@allannaranjo I'm trying to do the same thing as in the original issue and I'm trying to implement your code example however you haven't provided the code for the buffer2wav function. Any chance you could add that code to the example?

Many thanks in advance.

@moshedri
Copy link

moshedri commented Dec 7, 2016

here is some script i found on the web that can replace thr buffer2wav function
note that it return a blob so the last line return "(new Blob([arraybuffer], { type : 'audio/wav'}));"

should be chance to the return value of this function

// Convert a audio-buffer segment to a Blob using WAVE representation
// The returned Object URL can be set directly as a source for an Auido element.
// (C) Ken Fyrstenberg / MIT license
function bufferToWave(abuffer, offset, len) {

  var numOfChan = abuffer.numberOfChannels,
      length = len * numOfChan * 2 + 44,
      buffer = new ArrayBuffer(length),
      view = new DataView(buffer),
      channels = [], i, sample,
      pos = 0;
      
  // write WAVE header
  setUint32(0x46464952);                         // "RIFF"
  setUint32(length - 8);                         // file length - 8
  setUint32(0x45564157);                         // "WAVE"
  
  setUint32(0x20746d66);                         // "fmt " chunk
  setUint32(16);                                 // length = 16
  setUint16(1);                                  // PCM (uncompressed)
  setUint16(numOfChan);
  setUint32(abuffer.sampleRate);
  setUint32(abuffer.sampleRate * 2 * numOfChan); // avg. bytes/sec
  setUint16(numOfChan * 2);                      // block-align
  setUint16(16);                                 // 16-bit (hardcoded in this demo)
  
  setUint32(0x61746164);                         // "data" - chunk
  setUint32(length - pos - 4);                   // chunk length
  
  // write interleaved data
  for(i = 0; i < abuffer.numberOfChannels; i++)
    channels.push(abuffer.getChannelData(i));
  
  while(pos < length) {
    for(i = 0; i < numOfChan; i++) {             // interleave channels
      sample = Math.max(-1, Math.min(1, channels[i][offset])); // clamp
      sample = (0.5 + sample < 0 ? sample * 32768 : sample * 32767)|0; // scale to 16-bit signed int
      view.setInt16(pos, sample, true);          // update data chunk
      pos += 2;
    }
    offset++                                     // next source sample
  }

  // create Blob
  return (URL || webkitURL).createObjectURL(new Blob([buffer], {type: "audio/wav"}));
  
  function setUint16(data) {
    view.setUint16(pos, data, true);
    pos += 2;
  }
  
  function setUint32(data) {
    view.setUint32(pos, data, true);
    pos += 4;
  }
}

took me a whole day to get this to work, hope this will save other some time :)

@bknill
Copy link

bknill commented Jan 18, 2018

@moshedri thanks for this function. I'm assuming len is the length of the new buffer? Can you tell me where offset comes from in the context of the previous function?

@moshedri
Copy link

you're welcome ,

it was a long time ago and as i mentioned above the code , i found it online
but i do remember that offset allow you to cut from the start of the sound file so if you want to convert the whole file you should pass in 0 as the offset , i even change this function in my own code to have offset =0 as default value

@skruyldz
Copy link

skruyldz commented Feb 1, 2018

I would like to read my .file extension file with wavesurfer.js as .wav, but I could not find a solution. Can you help me please @katspaugh

1 similar comment
@skruyldz
Copy link

skruyldz commented Feb 1, 2018

I would like to read my .file extension file with wavesurfer.js as .wav, but I could not find a solution. Can you help me please @katspaugh

@vikasmagar512
Copy link

Hi, I have implemented cut, copy, paste in wavesurfer. Please refer to this repo
https://github.com/vikasmagar512/wavesurfer-audio-editor

@johnlandish
Copy link

Hi, I have implemented cut, copy, paste in wavesurfer. Please refer to this repo
https://github.com/vikasmagar512/wavesurfer-audio-editor

How would i implement this in my project?

@vikasmagar512
Copy link

vikasmagar512 commented May 28, 2019

@johnlandish Here are the functions
Cut, Copy, Paste, bufferToWave. You can call these functions kind of pure functions.
Please refer this file

https://github.com/vikasmagar512/wavesurfer-audio-editor/blob/master/src/utils/waveSurferOperation.js

Happy to help...!!!

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

No branches or pull requests

10 participants