dndmusicbot/ffmpeg/pcm.go

107 lines
1.5 KiB
Go
Raw Normal View History

2022-11-18 21:18:12 +00:00
package ffmpeg
import (
"fmt"
"io"
"log"
2022-11-18 21:18:12 +00:00
"math"
"time"
"github.com/gopxl/beep"
2022-11-18 21:18:12 +00:00
)
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) {
2022-11-18 21:18:12 +00:00
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()
}
2022-11-18 21:18:12 +00:00
tmp := make([]byte, d.c+2)
for i := range samples {
if !d.Player.Started {
samples[i] = [2]float64{}
ok = true
break
}
2022-11-18 21:18:12 +00:00
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)
2022-11-18 21:18:12 +00:00
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
}