最近有一個需求是需要把 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") }
參考資料
《AWS CDK 完全學習手冊:打造雲端基礎架構程式碼 IaC》
第 12 屆 iT 邦幫忙鐵人賽 DevOps 組冠的《用 CDK 定 義 AWS 架構》
第 11 屆 iT 邦幫忙鐵人賽《LINE bot 好好玩 30 天玩轉 LINE API》
一個熱愛分享的雲端工程師!