Golang 實作 A-law 轉 Linear

最近有一個需求是需要把 A-law 轉換成 PCM 不過在 Golang 好像沒有找到比較合用的 package 所以就自己實作了這段拉!

準備 A-law 檔

下載 wav 測試檔

基本上我在網路上找了滿久想要找 A-law 的音檔好像找不到,所以就直接找了一個 wav 檔,然後把它用 FFmpeg 轉換成 A-law 再測試,先下載 wav 測試檔

wget http://www.music.helsinki.fi/tmt/opetus/uusmedia/esim/a2002011001-e02-8kHz.wav

使用 FFmpeg 轉成 A-law 檔

ffmpeg -i a2002011001-e02-8kHz.wav -ar 8000 -ac 1 -ab 64 -f alaw output.g711

如此我們就得到一個 A-law 的檔案拉!

如果想要確定有沒有正確我們可以使用 Audacity 讀取確定轉碼有沒有正確,不過這個不是這篇的重點就先帶過!

Golang 程式

有了檔案我們就來看看 Golang 怎麼實作吧!

今天的重點是 audio.Alaw2linear 這個 function 放入 1 byte 的 A-law 資料會回傳 2 bytes 的 PCM 使用方法如:

pcm := audio.Alaw2linear(aLaw)

但在儲存需要把 int16 分別儲存到 byte 裡面

package main

import (
	"fmt"
	"github.com/clarencetw/audio"
	"io/ioutil"
	"os"
)

func main() {
	rf, err := ioutil.ReadFile("./output.g711")
	if err != nil {
		panic(err)
	}

	linear := make([]byte, len(rf)*2)
	for i, j := 0, 0; i < len(rf); i, j = i+1, j+2 {
		lt := audio.Alaw2linear(rf[i])
		linear[j] = byte(lt)
		linear[j+1] = byte(lt >> 8)
	}

	wf, err := os.OpenFile("./output.raw", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		panic(err)
	}
	defer wf.Close()

	wn, err := wf.Write(linear)
	if err != nil {
		panic(err)
	}
	fmt.Println("Wrote byte = ", wn, "file name = ./output.raw")
}

參考資料