Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

163
Visualizações
How do I decode MP3 with js-mp3 and play in AudioContext?

Because of a bug in Safari 15 that sometimes causes AudioContext.decodeAudioData to fail (see Safari 15 fails to decode audio data that previous versions decoded without problems) for normal MP3 files I'm trying to do a workaround. The workaround is decoding the files with the library https://github.com/soundbus-technologies/js-mp3 , then creating an AudioBuffer from that data and playing that.

The problem is that js-mp3 returns one ArrayBuffer with PCM data, and creating an AudioBuffer requires two seperate arrays, one for each channel, and the sampleRate and sample frame length. What I've got so far is:


function concatTypedArrays(a, b) { // a, b TypedArray of same type
    var c = new (a.constructor)(a.length + b.length);
    c.set(a, 0);
    c.set(b, a.length);
    return c;
};

// responseData is an ArrayBuffer with the MP3 file...
let decoder = Mp3.newDecoder(responseData);
let pcmArrayBuffer = decoder.decode();

//Trying to read the frames to get the two channels. Maybe get it correctly from
//the pcmArrayBuffer instead?
    
decoder.source.pos = 0;
let left = new Float32Array(), right = new Float32Array();
console.log('Frame count: ' + decoder.frameStarts.length);
let result;
let i = 0;
let samplesDecoded = 0;
                    
while (true) {

    let result = decoder.readFrame();
    if (result.err) {
        break;
    } else {
        console.log('READ FRAME ' + (++i));
        samplesDecoded += 1152; //Think this is the right sample count per frame for MPEG1 files
        left = concatTypedArrays(left, decoder.frame.v_vec[0]);
        right = concatTypedArrays(left, decoder.frame.v_vec[1]);
    }
}

let audioContext = new AudioContext();
let buffer = audioContext.createBuffer(2, samplesDecoded, decoder.sampleRate);
let source = audioContext.createBufferSource();
source.buffer = buffer;
source.connect(audioContext.destination);
source.start(0);

Now, this sort of works, in that I do hear sounds and I can hear they are the right sounds but they are weirdly distorted. An example sound file I'm trying to play is https://cardgames.io/mahjong/sounds/selecttile.mp3

Any ideas what is wrong here? Or how to convert the single PCM array buffer that is returned from the .decode() function correctly to the format needed to play it properly?

about 4 years ago · Juan Pablo Isaza
1 Respostas
Responde à pergunta

0

The example that fdcpp linked above shows that the ArrayBuffer returned by decoder.decode() can be used to write it to a WAV file without any further modification. This means the data must be interleaved PCM data.

It should therefore work when converting the data back to floating point values. Additionally it must be put into planar arrays as expected by the Web Audio API.

const interleavedPcmData = new DataView(pcmArrayBuffer);
const numberOfChannels = decoder.frame.header.numberOfChannels();
const audioBuffer = new AudioBuffer({
    length: pcmArrayBuffer.byteLength / 2 / numberOfChannels,
    numberOfChannels,
    sampleRate: decoder.sampleRate
});
const planarChannelDatas = [];

for (let i = 0; i < numberOfChannels; i += 1) {
    planarChannelDatas.push(audioBuffer.getChannelData(i));
}

for (let i = 0; i < interleavedPcmData.byteLength; i += 2) {
    const channelNumber = i / 2 % numberOfChannels;
    const value = interleavedPcmData.getInt16(i, true);

    planarChannelDatas[channelNumber][Math.floor(i / 2 / numberOfChannels)]
        = value < 0
            ? value / 32768
            : value / 32767;
}
about 4 years ago · Juan Pablo Isaza Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda