Reputation: 4003
How could I convert sample rate of a buffer from 44100 to 48000 Hz in a browser?
I found a library https://github.com/taisel/XAudioJS/blob/master/resampler.js that should allow me to do that, but don't have an idea how to use it.
Upvotes: 1
Views: 5300
Reputation: 4003
There seemed to be a bug in mobile safari which didn't decode the loaded audio correctly when the sample rate for the audio context was different than the sample rate for the audio file. Moreover, the sample rate for the audio context changed randomly from 44100 to 48000 usually but not always depending if the website was loading with the iPhone sound switched on or off.
The workaround for this issue is to read the sample rate of the audio context and then to load different audio files for each sample rate, like this:
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var audio_context = new AudioContext();
var actual_sample_rate = audio_context.sampleRate;
if (actual_sample_rate != 48000) {
actual_sample_rate = 44100;
}
function finished_loading_sounds(sounds) {
buffers['piano_do'] = {
buffer: sounds.piano,
rate: 1
};
// ...do something when the sounds are loaded...
}
var buffer_loader = new BufferLoader(
audio_context,
{
piano: "audio/" + actual_sample_rate + "/piano.m4a",
},
finished_loading_sounds
);
buffer_loader.load();
The buffer loader is defined like in this tutorial.
To change the sample rate for the audio file, one can use Audacity.
UPDATE
It seems that even when you try to load a file with the correct sample rate, occasionally the sound still gets distorted on iOS devices.
To fix the issue, I found a hack for your AudioContext:
function createAudioContext(desiredSampleRate) {
var AudioCtor = window.AudioContext || window.webkitAudioContext;
desiredSampleRate = typeof desiredSampleRate === 'number'
? desiredSampleRate
: 44100;
var context = new AudioCtor();
// Check if hack is necessary. Only occurs in iOS6+ devices
// and only when you first boot the iPhone, or play a audio/video
// with a different sample rate
if (/(iPhone|iPad)/i.test(navigator.userAgent) && context.sampleRate !== desiredSampleRate) {
var buffer = context.createBuffer(1, 1, desiredSampleRate);
var dummy = context.createBufferSource();
dummy.buffer = buffer;
dummy.connect(context.destination);
dummy.start(0);
dummy.disconnect();
context.close(); // dispose old context
context = new AudioCtor();
}
return context;
}
Then to use it, create the audio context as follows:
var audio_context = createAudioContext(44100);
Upvotes: 1
Reputation: 6056
Use an offline audio context. Something like the following may work:
var c = new OfflineAudioContext(1, len, 48000);
var b = c.createBuffer(1, len, 44100);
b.copyToChannel(yourSourceBuffer, 0);
var s = c.createBufferSource();
s.buffer = b;
s.connect(context.destination);
s.start();
c.startRendering().then(function (result) {
// result contains the new buffer resampled to 48000
});
Depending the implementation, the quality of the resampled signal can vary quite a bit.
Upvotes: 4