bot.*Connection.EncodeOpusAndSend   F
last analyzed

Complexity

Conditions 15

Size

Total Lines 48
Code Lines 36

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 15
eloc 36
nop 1
dl 0
loc 48
rs 2.9998
c 0
b 0
f 0

How to fix   Complexity   

Complexity

Complex classes like bot.*Connection.EncodeOpusAndSend often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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
don't use ALL_CAPS in Go names; use CamelCase
Loading history...
19
	// FRAME_SIZE ...
20
	FRAME_SIZE int = 960
0 ignored issues
show
introduced by
don't use ALL_CAPS in Go names; use CamelCase
Loading history...
21
	// MAX_BYTES max bytes per sample
22
	MAX_BYTES int = (FRAME_SIZE * 2) * 2
0 ignored issues
show
introduced by
don't use ALL_CAPS in Go names; use CamelCase
Loading history...
23
)
24
25
func (connection *Connection) EncodeOpusAndSend(reader io.Reader) error {
0 ignored issues
show
introduced by
exported method Connection.EncodeOpusAndSend should have comment or be unexported
Loading history...
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