package ffmpeg import ( "fmt" "io" "log" "math" "time" "github.com/gopxl/beep" ) type PCM struct { f beep.Format pos int sr int c int Player *FFmpeg Uri string Base float64 Volume float64 } func NewPCM(uri string, sampleRate int, channels int) (*PCM, error) { out := new(PCM) ff, err := NewFFmpeg(uri, sampleRate, channels) if err != nil { return nil, err } out.Player = ff format := beep.Format{ SampleRate: beep.SampleRate(sampleRate), NumChannels: channels, Precision: 2, } return &PCM{ format, 0, sampleRate, channels, ff, uri, 2, -2, }, nil } func (d *PCM) Stream(samples [][2]float64) (n int, ok bool) { if !d.Player.Started { d.Player.Start() } tmp := make([]byte, d.c+2) for i := range samples { if !d.Player.Started { samples[i] = [2]float64{} ok = true break } dn, err := d.Player.Out.Read(tmp) if dn == len(tmp) { samples[i], _ = d.f.DecodeSigned(tmp) d.pos += dn ok = true } if err == io.EOF { ok = false break } if err != nil { log.Println(err) ok = false break } gain := math.Pow(d.Base, d.Volume) samples[i][0] *= gain samples[i][1] *= gain } return len(samples), ok } func (d PCM) Err() error { return nil } func (d PCM) Position() int { t, _ := time.ParseDuration(fmt.Sprintf("%ds", ((d.pos / d.sr) / 4))) return int(t.Milliseconds()) } func (d PCM) Close() error { d.Player.Close() return nil } func (d PCM) Len() int { return int(d.Player.Len.Milliseconds()) } func (d PCM) Seek(p int) error { return nil }