decoder.go 1.26 KiB
package prober
import (
"encoding/binary"
"io"
"os"
"os/exec"
)
const (
analysisSampleRate = "44100"
analysisChannels = "1"
)
// The decoder uses sox(1) to decode the audio data to mono float64
// samples at a fixed sample rate (in the same format expected by the
// floatReader). We shell out to sox due to the lack of simple audio
// libraries for Go that would do the job...
type decoder struct {
io.ReadCloser
cmd *exec.Cmd
}
func newDecoder(r io.Reader, ext string) (*decoder, error) {
var args []string
if ext == ".mp3" {
args = append(args, "-t", "mp3")
}
args = append(args, "-", "-r", analysisSampleRate, "-c", analysisChannels, "-b", "64", "-e", "float", "--endian", "little", "-t", "raw", "-")
cmd := exec.Command("sox", args...)
cmd.Stdin = r
cmd.Stderr = os.Stderr
stdout, err := cmd.StdoutPipe()
if err != nil {
return nil, err
}
if err := cmd.Start(); err != nil {
return nil, err
}
return &decoder{
ReadCloser: stdout,
cmd: cmd,
}, nil
}
func (d *decoder) Close() error {
d.ReadCloser.Close()
return d.cmd.Wait()
}
// The floatReader reads float64 arrays from an io.Reader.
type floatReader struct {
io.Reader
}
func (r floatReader) ReadFloats(buf []float64) error {
return binary.Read(r.Reader, binary.LittleEndian, buf)
}