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編碼就可以實現了。

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