Go语言调用ffmpeg-api实现音频重采样
package main
//#include
import "C"
import (
"flag"
"fmt"
"github.com/google/logger"
"github.com/xueqing/ffmpeg-demo/logutil"
"github.com/xueqing/goav/libswresample"
"github.com/youpy/go-wav"
"io"
"os"
"reflect"
"unsafe"
)
func main() {
var (
inputUrl string = "http://www.jb51.net/article/data/1.wav"
inNumChannels int64 = 1
inSampleRate int = 16000
//inBitsPerSample uint16 = 16
outNumChannels int64 = 1
outSampleRate int = 48000
outBitsPerSample uint16 = 16
swr *libswresample.SwrContext = libswresample.SwrAlloc()
)
flag.Parse()
logutil.Init(true, false, "resample.log")
defer logutil.Close()
swr.SwrAllocSetOpts(outNumChannels,
libswresample.AvSampleFormat(1),
outSampleRate,
inNumChannels,
libswresample.AvSampleFormat(1),
inSampleRate,
0,
0)
swr.SwrInit()
defer swr.SwrClose()
_inputFile, err := os.Open(inputUrl)
if err != nil {
logger.Errorf("open input file error(%v)", err)
return
}
defer _inputFile.Close()
_reader := wav.NewReader(_inputFile)
format, err := _reader.Format()
if err != nil {
logger.Errorf("input file format error(%v)", err)
return
}
fmt.Printf("input file format info -> AudioFormat:%v,NumChannels:%v,SampleRate:%v,ByteRate:%v,BlockAlign:%v,BitsPerSample:%v", int(format.AudioFormat), format.NumChannels, format.SampleRate, format.ByteRate, format.BlockAlign, format.BitsPerSample)
_tempFile, err := os.CreateTemp("", "*.wav")
if err != nil {
logger.Errorf("create temp file error(%v)", err)
return
}
logger.Infof("Create tempFile %v", _tempFile.Name())
defer func() {
_tempFile.Close()
}()
_samples := []wav.Sample{}
n := 4096
for {
spls, err := _reader.ReadSamples(uint32(n))
if err == io.EOF {
break
}
_samples = append(_samples, spls...)
}
_result := ResampleByFFmpegApi2(swr, _samples)
_writer := wav.NewWriter(_tempFile, uint32(len(_result)), uint16(outNumChannels), uint32(outSampleRate), outBitsPerSample)
err4 := _writer.WriteSamples(_result)
if err4 != nil {
logger.Errorf("write file error(%v)", err4)
err = err4
return
}
}
func ResampleByFFmpegApi2(swr *libswresample.SwrContext, samples []wav.Sample) []wav.Sample {
var (
_inArr **uint8
_outArr **uint8
_inptr []uint16
_outptr []uint16
)
_inArr = (**uint8)(C.malloc(C.sizeof_int))
defer C.free(unsafe.Pointer(_inArr))
_inptr = make([]uint16, len(samples))
_outArr = (**uint8)(C.malloc(C.sizeof_int))
defer C.free(unsafe.Pointer(_outArr))
_outptr = make([]uint16, len(samples)*3)
//fmt.Println(unsafe.Sizeof(uint16(0)))
for i, v := range samples {
_inptr[i] = uint16(v.Values[0])
}
*_inArr = (*uint8)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&_inptr)).Data))
*_outArr = (*uint8)(unsafe.Pointer((*reflect.SliceHeader)(unsafe.Pointer(&_outptr)).Data))
ret := swr.SwrConvert(_outArr, len(samples)*3, _inArr, len(samples))
if ret > 0 {
fmt.Println(ret)
}
_result := make([]wav.Sample, ret)
for i := 0; i < ret; i++ {
_result[i] = wav.Sample{[2]int{int(_outptr[i]), 0}}
}
return _result
}