/
audio.go
119 lines (105 loc) · 2.59 KB
/
audio.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
113
114
115
116
117
118
119
package audio
import (
"errors"
"github.com/200sc/klangsynthese/audio"
"github.com/200sc/klangsynthese/font"
"github.com/oakmound/oak/oakerr"
)
// Audio is a struct of some audio data and the variables
// required to filter it through a sound font.
type Audio struct {
*font.Audio
toStop audio.Audio
X, Y *float64
}
// New returns an audio from a font, some audio data, and optional
// positional coordinates
func New(f *font.Font, d Data, coords ...*float64) *Audio {
a := new(Audio)
a.Audio = font.NewAudio(f, d)
if len(coords) > 0 {
a.X = coords[0]
if len(coords) > 1 {
a.Y = coords[1]
}
}
return a
}
// Play begin's an audio's playback
func (a *Audio) Play() <-chan error {
a2, err := a.Copy()
if err != nil {
return errChannel(err)
}
a3, err := a2.Filter(a.Font.Filters...)
if err != nil {
return errChannel(err)
}
a4, err := a3.(*Audio).FullAudio.Copy()
if err != nil {
return errChannel(err)
}
a.toStop = a4
return a4.Play()
}
func errChannel(err error) <-chan error {
ch := make(chan error)
go func() {
ch <- err
}()
return ch
}
// Stop stops an audio's playback
func (a *Audio) Stop() error {
if a == nil || a.toStop == nil {
return errors.New("Nil audio stopped")
}
return a.toStop.Stop()
}
// Copy returns a copy of the audio
func (a *Audio) Copy() (audio.Audio, error) {
a2, err := a.Audio.Copy()
if err != nil {
return nil, err
}
return New(a.Audio.Font, a2.(audio.FullAudio), a.X, a.Y), nil
}
// MustCopy acts like Copy, but panics on an error.
func (a *Audio) MustCopy() audio.Audio {
return New(a.Audio.Font, a.Audio.MustCopy().(audio.FullAudio), a.X, a.Y)
}
// Filter returns the audio with some set of filters applied to it.
func (a *Audio) Filter(fs ...audio.Filter) (audio.Audio, error) {
var ad audio.Audio = a
var err, consErr error
for _, f := range fs {
ad, err = f.Apply(ad)
if err != nil {
if consErr == nil {
consErr = err
} else {
consErr = oakerr.ConsError{First: err, Second: consErr}
}
}
}
return ad, consErr
}
// MustFilter acts like Filter but ignores errors.
func (a *Audio) MustFilter(fs ...audio.Filter) audio.Audio {
ad, _ := a.Filter(fs...)
return ad
}
// Xp returns a pointer to the x position of this audio, if it has one.
// It has no position, this returns nil.
func (a *Audio) Xp() *float64 {
return a.X
}
// Yp returns a pointer to the y position of this audio, if it has one.
// It has no position, this returns nil. If This is not nil, Xp will not be nil.
func (a *Audio) Yp() *float64 {
return a.Y
}
var (
// Guarantee that Audio can have positional filters applied to it
_ SupportsPos = &Audio{}
)