This repository was archived by the owner on Jul 21, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsampler.go
More file actions
105 lines (91 loc) · 2.2 KB
/
Copy pathsampler.go
File metadata and controls
105 lines (91 loc) · 2.2 KB
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
package component
import (
"github.com/gotracker/gomixing/sampling"
"github.com/gotracker/gomixing/volume"
"github.com/gotracker/voice/loop"
"github.com/gotracker/voice/pcm"
)
// Sampler is a sampler component
type Sampler struct {
sample pcm.Sample
pos sampling.Pos
keyOn bool
loopsEnabled bool
wholeLoop loop.Loop
sustainLoop loop.Loop
}
// Setup sets up the sampler
func (s *Sampler) Setup(sample pcm.Sample, wholeLoop loop.Loop, sustainLoop loop.Loop) {
s.sample = sample
s.wholeLoop = wholeLoop
s.sustainLoop = sustainLoop
}
// SetPos sets the current position of the sampler in the pcm data (and loops)
func (s *Sampler) SetPos(pos sampling.Pos) {
s.pos = pos
}
// GetPos returns the current position of the sampler in the pcm data (and loops)
func (s *Sampler) GetPos() sampling.Pos {
return s.pos
}
// Attack sets the key-on value (for loop processing)
func (s *Sampler) Attack() {
s.keyOn = true
s.loopsEnabled = true
}
// Release releases the key-on value (for loop processing)
func (s *Sampler) Release() {
s.keyOn = false
}
// Fadeout disables the loops (for loop processing)
func (s *Sampler) Fadeout() {
s.loopsEnabled = false
}
// GetSample returns a multi-channel sample at the specified position
func (s *Sampler) GetSample(pos sampling.Pos) volume.Matrix {
v0 := s.getConvertedSample(pos.Pos)
if v0.Channels == 0 {
if s.canLoop() {
v01 := s.getConvertedSample(pos.Pos)
panic(v01)
}
return v0
}
if pos.Frac == 0 {
return v0
}
v1 := s.getConvertedSample(pos.Pos + 1)
return v0.Lerp(v1, pos.Frac)
}
func (s *Sampler) canLoop() bool {
switch {
case !s.loopsEnabled:
return false
case s.keyOn && s.sustainLoop.Enabled():
return true
case s.wholeLoop.Enabled():
return true
}
return false
}
func (s *Sampler) getConvertedSample(pos int) volume.Matrix {
if s.sample == nil {
return volume.Matrix{}
}
sl := s.sample.Length()
if pos >= sl && !s.canLoop() {
return volume.Matrix{}
}
opos := pos
pos, _ = loop.CalcLoopPos(s.wholeLoop, s.sustainLoop, pos, sl, s.keyOn)
_ = opos
if pos < 0 || pos >= sl {
return volume.Matrix{}
}
s.sample.Seek(pos)
data, err := s.sample.Read()
if err != nil {
return volume.Matrix{}
}
return data
}