src/music/audio.go (view raw)
1package music
2
3import (
4 "github.com/ClintonCollins/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.session.Stop()
72 a.session.Cleanup()
73 a.stream = nil
74 a.session = nil
75}
76
77func (a *Audio) Finished() (bool, error) {
78 return a.stream.Finished()
79}
80
81func (a *Audio) Monitor(onFinish func()) {
82 go func() {
83 for err := range a.Done {
84 if err != nil {
85 logger.Errorf("Playback error: %v", err)
86 break
87 }
88 }
89
90 a.Stop()
91
92 if onFinish != nil {
93 onFinish()
94 }
95 }()
96}