-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathlistener.go
96 lines (73 loc) · 2.33 KB
/
listener.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
package precise
import (
"errors"
"gorgonia.org/tensor"
)
var (
ErrModelClosed = errors.New("model closed")
)
func NewListener(model Model, p Params) (*Listener, error) {
l := &Listener{
params: p,
model: model,
windowAudio: make([]int16, 0),
mfccs: tensor.New(tensor.Of(tensor.Float32), tensor.WithShape(p.NFeatures(), p.NMFCC)),
}
config := DefaultThreshold
config.Center = p.ThresholdCenter
l.decoder = NewThresholdDecoder(p.ThresholdConfig, config)
return l, nil
}
type Listener struct {
params Params
model Model
windowAudio []int16
mfccs *tensor.Dense
decoder *ThresholdDecoder
}
func (p *Listener) updateVectors(audio []int16) tensor.Tensor {
p.windowAudio = append(p.windowAudio, audio...)
if len(p.windowAudio) >= p.params.WindowSamples() {
var newFeatures tensor.Tensor
newFeatures = mfccSpec(p.windowAudio, p.params)
p.windowAudio = p.windowAudio[newFeatures.Shape()[0]*p.params.HopSamples():]
if newFeatures.Shape()[0] > p.mfccs.Shape()[0] {
// TODO: Slice only necessary features, this is done in Rust as:
// nrows = len, dim = mfccs.Dim()?
// new_features = new_features.slice(s![new_features.nrows() - self.mfccs.dim().0..,..]).to_owned();
newFeatures = tensorMust(newFeatures.Slice(tensor.S(newFeatures.Shape()[0]-p.mfccs.Shape()[0], newFeatures.Shape()[0])))
}
// TODO: Concatenate mfccs
// Rust example:
// Axis = dimension? (0, top level)
// nrows = len?
// self.mfccs = concatenate![Axis(0), self.mfccs.slice(s![new_features.nrows()..,..]).to_owned(), new_features];
// self.mfccs = np.concatenate((self.mfccs[len(new_features):], new_features))
if newFeatures.Shape()[0] == p.mfccs.Shape()[0] {
p.mfccs = newFeatures.(*tensor.Dense)
} else {
slicedMfccs := tensorMust(p.mfccs.Slice(tensor.S(newFeatures.Shape()[0], p.mfccs.Shape()[0])))
p.mfccs = tensorMust(tensor.Concat(0, slicedMfccs, newFeatures.(*tensor.Dense)))
}
}
return p.mfccs
}
func (p *Listener) Update(audio []int16) (float32, error) {
if p.model == nil {
return -1, ErrModelClosed
}
mfccs := p.updateVectors(audio)
rawOutput, err := p.model.Predict(mfccs)
if err != nil {
return -1, err
}
return p.decoder.Decode(rawOutput), nil
}
func (p *Listener) Close() error {
err := p.model.Close()
if err != nil {
return err
}
p.model = nil
return nil
}