forked from ionorg/ion-sfu
/
audiolevel.go
112 lines (99 loc) · 1.83 KB
/
audiolevel.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
package sfu
import (
"sort"
"sync"
)
type audioStream struct {
id string
sum int
total int
}
type audioLevel struct {
sync.RWMutex
streams []*audioStream
expected int
threshold uint8
previous []string
}
func newAudioLevel(threshold uint8, interval, filter int) *audioLevel {
if threshold > 127 {
threshold = 127
}
if filter < 0 {
filter = 0
}
if filter > 100 {
filter = 100
}
return &audioLevel{
threshold: threshold,
expected: interval * filter / 2000,
}
}
func (a *audioLevel) addStream(streamID string) {
a.Lock()
a.streams = append(a.streams, &audioStream{id: streamID})
a.Unlock()
}
func (a *audioLevel) removeStream(streamID string) {
a.Lock()
defer a.Unlock()
idx := -1
for i, s := range a.streams {
if s.id == streamID {
idx = i
break
}
}
if idx == -1 {
return
}
a.streams[idx] = a.streams[len(a.streams)-1]
a.streams[len(a.streams)-1] = nil
a.streams = a.streams[:len(a.streams)-1]
}
func (a *audioLevel) observe(streamID string, dBov uint8) {
a.RLock()
defer a.RUnlock()
for _, as := range a.streams {
if as.id == streamID {
if dBov <= a.threshold {
as.sum += int(dBov)
as.total++
}
return
}
}
}
func (a *audioLevel) calc() []string {
a.Lock()
defer a.Unlock()
sort.Slice(a.streams, func(i, j int) bool {
si, sj := a.streams[i], a.streams[j]
switch {
case si.total != sj.total:
return si.total > sj.total
default:
return si.sum < sj.sum
}
})
streamIDs := make([]string, 0, len(a.streams))
for _, s := range a.streams {
if s.total >= a.expected {
streamIDs = append(streamIDs, s.id)
}
s.total = 0
s.sum = 0
}
if len(a.previous) == len(streamIDs) {
for i, s := range a.previous {
if s != streamIDs[i] {
a.previous = streamIDs
return streamIDs
}
}
return nil
}
a.previous = streamIDs
return streamIDs
}