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

  }