1 | package bot |
||
2 | |||
3 | import ( |
||
4 | "bufio" |
||
5 | "encoding/binary" |
||
6 | "errors" |
||
7 | "fmt" |
||
8 | "io" |
||
9 | "time" |
||
10 | |||
11 | "github.com/FlameInTheDark/gopus" |
||
12 | ) |
||
13 | |||
14 | const ( |
||
15 | // CHANNELS count of audio channels |
||
16 | CHANNELS int = 2 |
||
17 | // FRAME_RATE ... |
||
18 | FRAME_RATE int = 48000 |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
19 | // FRAME_SIZE ... |
||
20 | FRAME_SIZE int = 960 |
||
0 ignored issues
–
show
|
|||
21 | // MAX_BYTES max bytes per sample |
||
22 | MAX_BYTES int = (FRAME_SIZE * 2) * 2 |
||
0 ignored issues
–
show
|
|||
23 | ) |
||
24 | |||
25 | func (connection *Connection) EncodeOpusAndSend(reader io.Reader) error { |
||
0 ignored issues
–
show
|
|||
26 | if connection.playing { |
||
27 | return errors.New("song already playing") |
||
28 | } |
||
29 | |||
30 | connection.playing = true |
||
31 | _ = connection.voiceConnection.Speaking(true) |
||
32 | defer func() { _ = connection.voiceConnection.Speaking(false) }() |
||
33 | |||
34 | breader := bufio.NewReaderSize(reader, 16384) |
||
35 | var buffer [FRAME_SIZE * CHANNELS]int16 |
||
36 | encoder, err := gopus.NewEncoder(FRAME_RATE, CHANNELS, gopus.Audio) |
||
37 | if err != nil { |
||
38 | fmt.Println("Can's create a gopus encoder", err) |
||
39 | return err |
||
40 | } |
||
41 | |||
42 | voice := connection.voiceConnection |
||
43 | loop: |
||
44 | for { |
||
45 | select { |
||
46 | case _ = <-connection.quitChan: |
||
47 | break loop |
||
48 | default: |
||
49 | err = binary.Read(breader, binary.LittleEndian, &buffer) |
||
50 | if err == io.EOF || err == io.ErrUnexpectedEOF { |
||
51 | return nil |
||
52 | } else if err != nil { |
||
53 | return err |
||
54 | } |
||
55 | opus, err := encoder.Encode(buffer[:], FRAME_SIZE, MAX_BYTES) |
||
56 | if err != nil { |
||
57 | fmt.Println("Gopus encoding error,", err) |
||
58 | return err |
||
59 | } |
||
60 | if !voice.Ready || voice.OpusSend == nil { |
||
61 | fmt.Printf("Discordgo not ready for opus packets. %+v : %+v", voice.Ready, voice.OpusSend) |
||
62 | return err |
||
63 | } |
||
64 | select { |
||
65 | case voice.OpusSend <- opus: |
||
66 | case <-time.After(time.Second * 5): |
||
67 | break |
||
68 | } |
||
69 | } |
||
70 | } |
||
71 | |||
72 | return nil |
||
73 | } |
||
74 | |||
75 | // Stop stops playback |
||
76 | func (connection *Connection) Stop() { |
||
77 | connection.playing = false |
||
78 | connection.quitChan <- struct{}{} |
||
79 | } |
||
80 |