Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ resampler(input, targetSampleRate, oncomplete);

`targetSampleRate` : The target sample rate after the re-sampling process. This number is limted based on the browser implementation (usually >=3000, <=192000)

`targetBitDepth` : The target bit depth after the re-sampling process. This number is limted based on the browser implementation (usually >=16, <=32)

`oncomplete`: Callback when the resampling process is completed. The argument to this callback is an Object which supports the following methods:

`getAudioBuffer` : Returns the resampler AudioBuffer
Expand All @@ -33,7 +35,7 @@ resampler(input, targetSampleRate, oncomplete);
```
resampler = require('audio-resampler');
var URL = "https://dl.dropboxusercontent.com/u/957/audio/sine.wav"
resampler(URL, 192000, function(event){
resampler(URL, 192000, 24, function(event){
event.getFile(function(fileEvent){
var a = document.createElement("a");
document.body.appendChild(a);
Expand Down
173 changes: 89 additions & 84 deletions bundle.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ window.addEventListener('load', function(){
spinner.style.display = "inherit";
input.disabled = true;
disableDragDrop(dropzone);
resampler(file, targetSampleRate, function(event){
resampler(file, targetSampleRate, 24, function(event){
event.getFile(function(fileEvent){
console.log(fileEvent);
spinner.style.display = "none";
Expand Down Expand Up @@ -95,95 +95,100 @@ var wal = new WebAudioLoader({
cache: false
});

function resampler(input, targetSampleRate, oncomplete) {
function resampler(input, targetSampleRate, targetBitDepth, oncomplete) {

if (!input && !targetSampleRate) {
return returnError('Error: First argument should be either a File, URL or AudioBuffer');
}
if (!input && !targetSampleRate && !targetBitDepth) {
return returnError('Error: First argument should be either a File, URL or AudioBuffer');
}

var inputType = Object.prototype.toString.call(input);
if (inputType !== '[object String]' &&
inputType !== '[object File]' &&
inputType !== '[object AudioBuffer]' &&
inputType !== '[object Object]') {
return returnError('Error: First argument should be either a File, URL or AudioBuffer');
}
var inputType = Object.prototype.toString.call(input);
if (inputType !== '[object String]' &&
inputType !== '[object File]' &&
inputType !== '[object AudioBuffer]' &&
inputType !== '[object Object]') {
return returnError('Error: First argument should be either a File, URL or AudioBuffer');
}

if (typeof targetSampleRate !== 'number' ||
targetSampleRate > 192000 || targetSampleRate < 3000) {
return returnError('Error: Second argument should be a numeric sample rate between 3000 and 192000');
}
if (typeof targetSampleRate !== 'number' ||
targetSampleRate > 192000 || targetSampleRate < 3000) {
return returnError('Error: Second argument should be a numeric sample rate between 3000 and 192000');
}

if (inputType === '[object String]' || inputType === '[object File]') {
console.log('Loading/decoding input', input);
wal.load(input, {
onload: function(err, audioBuffer) {
if (err) {
return returnError(err);
}
resampleAudioBuffer(audioBuffer);
}
});
} else if (inputType === '[object AudioBuffer]') {
resampleAudioBuffer(input);
} else if (inputType === '[object Object]' && input.leftBuffer && input.sampleRate) {
var numCh_ = input.rightBuffer ? 2 : 1;
var audioBuffer_ = audioContext.createBuffer(numCh_, input.leftBuffer.length, input.sampleRate);
resampleAudioBuffer(audioBuffer_);
} else {
return returnError('Error: Unknown input type');
}
if (typeof targetBitDepth !== 'number' ||
targetBitDepth > 32 || targetBitDepth < 16) {
return returnError('Error: Third argument should be a numeric bit depth between 16 and 32');
}

function returnError(errMsg) {
console.error(errMsg);
if (typeof oncomplete === 'function') {
oncomplete(new Error(errMsg));
}
return;
}
if (inputType === '[object String]' || inputType === '[object File]') {
console.log('Loading/decoding input', input);
wal.load(input, {
onload: function(err, audioBuffer) {
if (err) {
return returnError(err);
}
resampleAudioBuffer(audioBuffer);
}
});
} else if (inputType === '[object AudioBuffer]') {
resampleAudioBuffer(input);
} else if (inputType === '[object Object]' && input.leftBuffer && input.sampleRate) {
var numCh_ = input.rightBuffer ? 2 : 1;
var audioBuffer_ = audioContext.createBuffer(numCh_, input.leftBuffer.length, input.sampleRate);
resampleAudioBuffer(audioBuffer_);
} else {
return returnError('Error: Unknown input type');
}

function resampleAudioBuffer(audioBuffer) {


var numCh_ = audioBuffer.numberOfChannels;
var numFrames_ = audioBuffer.length * targetSampleRate / audioBuffer.sampleRate;

var offlineContext_ = new OfflineAudioContext(numCh_, numFrames_, targetSampleRate);
var bufferSource_ = offlineContext_.createBufferSource();
bufferSource_.buffer = audioBuffer;

offlineContext_.oncomplete = function(event) {
var resampeledBuffer = event.renderedBuffer;
console.log('Done Rendering');
if (typeof oncomplete === 'function') {
oncomplete({
getAudioBuffer: function() {
return resampeledBuffer;
},
getFile: function(fileCallback) {
var audioData = {
sampleRate: resampeledBuffer.sampleRate,
channelData: []
};
for (var i = 0; i < resampeledBuffer.numberOfChannels; i++) {
audioData.channelData[i] = resampeledBuffer.getChannelData(i);
}
WavEncoder.encode(audioData).then(function(buffer) {
var blob = new Blob([buffer], {
type: "audio/wav"
});
fileCallback(URL.createObjectURL(blob));
});
}
});
}
};

console.log('Starting Offline Rendering');
bufferSource_.connect(offlineContext_.destination);
bufferSource_.start(0);
offlineContext_.startRendering();
}
function returnError(errMsg) {
console.error(errMsg);
if (typeof oncomplete === 'function') {
oncomplete(new Error(errMsg));
}
return;
}

function resampleAudioBuffer(audioBuffer) {


var numCh_ = audioBuffer.numberOfChannels;
var numFrames_ = audioBuffer.length * targetSampleRate / audioBuffer.sampleRate;

var offlineContext_ = new OfflineAudioContext(numCh_, numFrames_, targetSampleRate);
var bufferSource_ = offlineContext_.createBufferSource();
bufferSource_.buffer = audioBuffer;

offlineContext_.oncomplete = function(event) {
var resampeledBuffer = event.renderedBuffer;
console.log('Done Rendering');
if (typeof oncomplete === 'function') {
oncomplete({
getAudioBuffer: function() {
return resampeledBuffer;
},
getFile: function(fileCallback) {
var audioData = {
sampleRate: resampeledBuffer.sampleRate,
channelData: []
};
for (var i = 0; i < resampeledBuffer.numberOfChannels; i++) {
audioData.channelData[i] = resampeledBuffer.getChannelData(i);
}
WavEncoder.encode(audioData, { float: false, bitDepth: targetBitDepth }).then(function(buffer) {
var blob = new Blob([buffer], {
type: "audio/wav"
});
fileCallback(URL.createObjectURL(blob));
});
}
});
}
};

console.log('Starting Offline Rendering');
bufferSource_.connect(offlineContext_.destination);
bufferSource_.start(0);
offlineContext_.startRendering();
}
}


Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ window.addEventListener('load', function(){
spinner.style.display = "inherit";
input.disabled = true;
disableDragDrop(dropzone);
resampler(file, targetSampleRate, function(event){
resampler(file, targetSampleRate, 24, function(event){
event.getFile(function(fileEvent){
console.log(fileEvent);
spinner.style.display = "none";
Expand Down
11 changes: 8 additions & 3 deletions lib/resampler.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ var wal = new WebAudioLoader({
cache: false
});

function resampler(input, targetSampleRate, oncomplete) {
function resampler(input, targetSampleRate, targetBitDepth, oncomplete) {

if (!input && !targetSampleRate) {
if (!input && !targetSampleRate && !targetBitDepth) {
return returnError('Error: First argument should be either a File, URL or AudioBuffer');
}

Expand All @@ -33,6 +33,11 @@ function resampler(input, targetSampleRate, oncomplete) {
return returnError('Error: Second argument should be a numeric sample rate between 3000 and 192000');
}

if (typeof targetBitDepth !== 'number' ||
targetBitDepth > 32 || targetBitDepth < 16) {
return returnError('Error: Third argument should be a numeric bit depth between 16 and 32');
}

if (inputType === '[object String]' || inputType === '[object File]') {
console.log('Loading/decoding input', input);
wal.load(input, {
Expand Down Expand Up @@ -87,7 +92,7 @@ function resampler(input, targetSampleRate, oncomplete) {
for (var i = 0; i < resampeledBuffer.numberOfChannels; i++) {
audioData.channelData[i] = resampeledBuffer.getChannelData(i);
}
WavEncoder.encode(audioData).then(function(buffer) {
WavEncoder.encode(audioData, { float: false, bitDepth: targetBitDepth }).then(function(buffer) {
var blob = new Blob([buffer], {
type: "audio/wav"
});
Expand Down