lamejs的使用

lamejs的简单使用

lamejs是一个用JS重写的mp3编码器。lamejs是对jump3r-code的重写,而后者是对libmp3lame的重写。

github项目地址:https://github.com/zhuker/lamejs

一、快速上手

先看一个简单的例子:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>example</title>
</head>
<body>
    <script src="lame.all.js"></script>
    <script>

        // channelNum {Number} 声道数
        // sampleRate {Number} PCM数据的采样率
        // samples {int16Array} 16位有符号的PCM数据
        function encodeMono (channelNum, sampleRate, samples) {
            var buffer = [];
            // 128是指输出的MP3音频的比特率bitrate,单位是kbps
            var mp3enc = new lamejs.Mp3Encoder(channelNum, sampleRate, 128);
            var remaining = samples.length;
            var maxSamples = 1152;
            for (var i = 0; remaining >= maxSamples; i += maxSamples) {
                var mono = samples.subarray(i, i + maxSamples);
                var mp3buf = mp3enc.encodeBuffer(mono);
                if (mp3buf.length > 0) {
                    buffer.push(new Int8Array(mp3buf));
                }
                remaining -= maxSamples;
            }
            var flushData = mp3enc.flush();
            if(flushData.length > 0){
                buffer.push(new Int8Array(flushData));
            }

            // 播放编码后的MP3
            console.log('done encoding, size=', buffer.length);
            var blob = new Blob(buffer, {type: 'audio/mp3'});
            var bUrl = window.URL.createObjectURL(blob);
            console.log('Blob created, URL:', bUrl);
            window.myAudioPlayer = document.createElement('audio');
            window.myAudioPlayer.src = bUrl;
            window.myAudioPlayer.setAttribute('controls', '');
            window.myAudioPlayer.play();
        }

        var url = "http://localhost/data/demo.pcm";
        var xhr = new XMLHttpRequest();
        xhr.open("GET", url, true);
        xhr.responseType = "arraybuffer";
        xhr.onload = function () {
            var samples = new Int16Array(xhr.response);
            encodeMono(1, 44100, samples);
        };
        xhr.send();
    </script>
</body>
</html>

我们还可以通过npm安装lamejs:

npm install lamejs

对应的引入方法如下:

var lamejs = require("lamejs"); // 也可以使用别的方法

对于上面提供的例子中,比较关键的信息是以下两点:

  • PCM数据的采样率、声道数
  • 编码后MP3的比特率

例子中提供的PCM数据是单声道,采样率为44100Hz,编码后MP3的比特率为128kbps。一般来说,比特率越高,传送的数据越大,MP3的音质越好。lamejs提供的最低比特率是8kbps,最大为320kbps,默认值为128kbps。

如果编码后的MP3进行播放时,声音是低沉冗长的,或者是刺耳的,极有可能是PCM的采样率或者声道数设置有问题。

二、双声道编码

上面的例子中,是对单声道的PCM数据进行编码。如果想要编码双声道,那么需要对PCM数据进行左右声道分离。双声道的PCM数据通常采用交错立体声的方式进行存储,假设PCM中每一个量化样本为16位,编码步骤大致如下:
在这里插入图片描述

// pcm {int16Array} 16位有符号的双声道PCM数据
function encodeStereo(pcm) {
    var leftChunk = pcm.filter(function (element, index, array) {
        return index % 2 === 0;
    });
    var rightChunk = pcm.filter(function (element, index, array) {
        return index % 2;
    });
    var mp3Buffer = mp3Encoder.encodeBuffer(leftChunk, rightChunk);
    return mp3Buffer;
}

需要注意的是leftChunkrightChunk的长度要保持一致。lamejs在编码执行encodeBuffer时,会对创建编码器时输入的声道数channelNum进行判断,如果是单声道,那么rightChunk将被赋值为leftChunk

function encoderBuffer (leftChunk, rightChunk) {
    if (channelNum === 1) {
        rightChunk = leftChunk;
    }
    // 忽略剩余的代码
}

三、WAV转MP3

WAV是一种无损的音频文件格式,其结构示意图如下图所示。
在这里插入图片描述
因为lamejs编码输入的是PCM数据,所以我们需要去掉WAV头部信息,得到PCM数据才能进行编码。lamejs已经提供了相应的解析方法。结合上面的例子,假设请求的是WAV文件,使用WavHeader.readHeader可以解析WAV文件的头部,得到声道数和采样率,以及PCM数据的偏移位置:

var audioData = request.response;
var wav = lamejs.WavHeader.readHeader(new DataView(audioData));
var samples = new Int16Array(audioData, wav.dataOffset, wav.dataLen / 2);
encodeMono(wav.channels, wav.sampleRate, samples);

以此类推,其他格式的音频数据使用lamejs转成MP3,可以先转为PCM数据,再进行MP3编码就可以实现了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章