src/music/audio.go (view raw)
1package music
2
3import (
4 "github.com/FoxeiZ/dca"
5 "github.com/bwmarrin/discordgo"
6)
7
8type Audio struct {
9 session *dca.EncodeSession
10 stream *dca.StreamingSession
11 Done chan error
12 onFinish func()
13 paused bool
14}
15
16var audioEncodeOptions = &dca.EncodeOptions{
17 Channels: 2,
18 FrameRate: 48000,
19 FrameDuration: 20,
20 Bitrate: 96,
21 Application: dca.AudioApplicationLowDelay,
22 CompressionLevel: 10,
23 PacketLoss: 1,
24 BufferedFrames: 100,
25 VBR: true,
26 StartTime: 0,
27 VolumeFloat: 1,
28 RawOutput: true,
29}
30
31func NewAudio(url string, vc *discordgo.VoiceConnection) (as *Audio, err error) {
32 as = &Audio{
33 session: nil,
34 stream: nil,
35 paused: false,
36 Done: make(chan error),
37 }
38
39 as.session, err = dca.EncodeFile(url, audioEncodeOptions)
40 if err != nil {
41 return
42 }
43
44 as.stream = dca.NewStream(as.session, vc, as.Done)
45 return
46}
47
48func (a *Audio) Pause() {
49 if a.stream == nil || a.paused {
50 return
51 }
52
53 a.stream.SetPaused(true)
54 a.paused = true
55}
56
57func (a *Audio) Resume() {
58 if a.stream == nil || !a.paused {
59 return
60 }
61
62 a.stream.SetPaused(false)
63 a.paused = false
64}
65
66func (a *Audio) Stop() {
67 if a.stream == nil {
68 return
69 }
70
71 a.stream.FinishNow()
72 a.session.Stop()
73 a.session.Cleanup()
74 a.stream = nil
75 a.session = nil
76}
77
78func (a *Audio) Finished() (bool, error) {
79 return a.stream.Finished()
80}
81
82func (a *Audio) Monitor(onFinish func()) {
83 go func() {
84 for err := range a.Done {
85 if err != nil {
86 logger.Errorf("Playback error: %v", err)
87 break
88 }
89 }
90
91 a.Stop()
92
93 if onFinish != nil {
94 onFinish()
95 }
96 }()
97}