Skip to content

Commit 8bf3631

Browse files
committed
load audio from resources
1 parent bb09f9b commit 8bf3631

File tree

7 files changed

+82
-28
lines changed

7 files changed

+82
-28
lines changed

audio/audio.go

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,28 @@ func GetStat() Stat {
6363
return system.Stat()
6464
}
6565

66-
// SaveAudio stores audio system state to byte slice. State is stored in binary form.
66+
// Save stores audio system state to byte slice. State is stored in binary form.
6767
// The format is described in Synthesizer.Save source code.
68-
func SaveAudio() ([]byte, error) {
68+
func Save() ([]byte, error) {
6969
return system.Save()
7070
}
7171

72-
// LoadAudio restores audio system state from byte slice. State is restored from binary form.
72+
// Load restores audio system state from byte slice. State is restored from binary form.
7373
// The format is described in Synthesizer.Save source code.
74-
func LoadAudio(b []byte) error {
75-
return system.Load(b)
74+
func Load(b []byte) error {
75+
if err := system.Load(b); err != nil {
76+
return err
77+
}
78+
79+
for sfxNo := range Sfx {
80+
Sfx[sfxNo] = system.GetSfx(sfxNo)
81+
}
82+
83+
for patternNo := range Pat {
84+
Pat[patternNo] = system.GetMusic(patternNo)
85+
}
86+
87+
return nil
7688
}
7789

7890
var system System = &Synthesizer{}
@@ -246,10 +258,6 @@ type PatternSfx struct {
246258
Enabled bool // Not implemented yet.
247259
}
248260

249-
func byteToBool(b byte) bool {
250-
return b == 1
251-
}
252-
253261
// SetSystem is executed by the back-end to replace audio system with his own implementation.
254262
func SetSystem(s System) {
255263
system = s

audio/internal.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,27 @@ func singleNoteSamples(speed byte) int {
5050

5151
return int(speed) * 183
5252
}
53+
54+
func minInt[T ~int | ~uint8](x, y T) T {
55+
if x < y {
56+
return x
57+
}
58+
59+
return y
60+
}
61+
62+
func midInt[T ~int](x, y, z T) T {
63+
if x > y {
64+
x, y = y, x
65+
}
66+
67+
if y > z {
68+
y = z
69+
}
70+
71+
if x > y {
72+
y = x
73+
}
74+
75+
return y
76+
}

audio/live.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"time"
99

10-
"github.com/elgopher/pi"
1110
"github.com/elgopher/pi/audio/internal"
1211
)
1312

@@ -36,7 +35,7 @@ func (l *LiveReader) ReadSamples(buf []float64) int {
3635
maxRealSample := int(now.Sub(l.started) / sampleDuration)
3736
maxCallerSample := l.lastSample + len(buf)
3837

39-
maxSample := pi.MinInt(maxRealSample, maxCallerSample)
38+
maxSample := minInt(maxRealSample, maxCallerSample)
4039
samplesToRead := maxSample - l.lastSample
4140

4241
samplesToDrop := maxRealSample - maxCallerSample - int(l.BufferSize/sampleDuration) + 1
@@ -60,7 +59,7 @@ func (l *LiveReader) dropSamples(samplesToDrop int) {
6059
}
6160

6261
for samplesToDrop > 0 {
63-
n := pi.MinInt(samplesToDrop, len(l.reusedBuffer))
62+
n := minInt(samplesToDrop, len(l.reusedBuffer))
6463
l.ReadSamplesFunc(l.reusedBuffer[:n])
6564
samplesToDrop -= n
6665
}

audio/synth.go

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"bytes"
88
"fmt"
99

10-
"github.com/elgopher/pi"
1110
"github.com/elgopher/pi/audio/internal"
1211
)
1312

@@ -108,7 +107,7 @@ func (s *Synthesizer) Play(sfxNo, ch, offset, length int) {
108107
ch = s.findAvailableChannel()
109108
}
110109

111-
offset = pi.MidInt(offset, 0, 31)
110+
offset = midInt(offset, 0, 31)
112111

113112
s.channels[ch].playing = true
114113

@@ -209,24 +208,24 @@ func (s *Synthesizer) SetSfx(sfxNo int, effect SoundEffect) {
209208
s.sfx = map[byte]SoundEffect{}
210209
}
211210

212-
effect.LoopStart = pi.MinInt(63, effect.LoopStart)
213-
effect.LoopStop = pi.MinInt(63, effect.LoopStop)
214-
effect.Detune = pi.MinInt(2, effect.Detune)
215-
effect.Reverb = pi.MinInt(2, effect.Reverb)
216-
effect.Dampen = pi.MinInt(2, effect.Dampen)
211+
effect.LoopStart = minInt(63, effect.LoopStart)
212+
effect.LoopStop = minInt(63, effect.LoopStop)
213+
effect.Detune = minInt(2, effect.Detune)
214+
effect.Reverb = minInt(2, effect.Reverb)
215+
effect.Dampen = minInt(2, effect.Dampen)
217216

218217
for i := 0; i < len(effect.Notes); i++ {
219218
volume := effect.Notes[i].Volume
220-
effect.Notes[i].Volume = pi.MinInt(7, volume)
219+
effect.Notes[i].Volume = minInt(7, volume)
221220

222221
pitch := effect.Notes[i].Pitch
223-
effect.Notes[i].Pitch = pi.MinInt(63, pitch)
222+
effect.Notes[i].Pitch = minInt(63, pitch)
224223

225224
instrument := effect.Notes[i].Instrument
226-
effect.Notes[i].Instrument = pi.MinInt(15, instrument)
225+
effect.Notes[i].Instrument = minInt(15, instrument)
227226

228227
eff := effect.Notes[i].Effect
229-
effect.Notes[i].Effect = pi.MinInt(7, eff)
228+
effect.Notes[i].Effect = minInt(7, eff)
230229
}
231230

232231
s.sfx[byte(sfxNo)] = effect
@@ -253,7 +252,7 @@ func (s *Synthesizer) SetMusic(patternNo int, pattern Pattern) {
253252

254253
for i := 0; i < len(pattern.Sfx); i++ {
255254
sfxNo := pattern.Sfx[i].SfxNo
256-
pattern.Sfx[i].SfxNo = pi.MinInt(maxSfxNo, sfxNo)
255+
pattern.Sfx[i].SfxNo = minInt(maxSfxNo, sfxNo)
257256
}
258257

259258
s.pattern[byte(patternNo)] = pattern
@@ -347,6 +346,10 @@ func (s *Synthesizer) Load(state []byte) error {
347346
return nil
348347
}
349348

349+
func byteToBool(b byte) bool {
350+
return b == 1
351+
}
352+
350353
func (s *Synthesizer) Save() ([]byte, error) {
351354
buffer := bytes.NewBuffer(nil)
352355

devtools/internal/lib/github_com-elgopher-pi-audio.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

ebitengine/audio.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func startAudio() (stop func(), ready <-chan struct{}, _ error) {
4848
// (again via MessageChannel) instead of directly calling synthesizer. Audio Worklet processor will use
4949
// pi.Synthesizer. Based on incoming events it will update the pi.Synthesizer.
5050

51-
state, err := audio.SaveAudio()
51+
state, err := audio.Save()
5252
if err != nil {
5353
return stop, nil, fmt.Errorf("problem saving audio state: %w", err)
5454
}

pi.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,11 @@ package pi
3535

3636
import (
3737
_ "embed"
38+
"errors"
39+
"fmt"
3840
"io/fs"
3941

42+
"github.com/elgopher/pi/audio"
4043
"github.com/elgopher/pi/font"
4144
)
4245

@@ -65,7 +68,7 @@ var Time float64
6568

6669
var GameLoopStopped bool
6770

68-
// Load loads files: sprite-sheet.png and custom-font.png from resources parameter.
71+
// Load loads files: sprite-sheet.png, custom-font.png and audio.sfx from resources parameter.
6972
//
7073
// Load looks for images with hard-coded names, eg for sprite-sheet it loads "sprite-sheet.png".
7174
// Your file name must be exactly the same. And it cannot be inside subdirectory.
@@ -124,6 +127,23 @@ func loadGameResources(resources fs.ReadFileFS) error {
124127
return err
125128
}
126129

130+
if err := loadAudio(resources); err != nil {
131+
return err
132+
}
133+
134+
return nil
135+
}
136+
137+
func loadAudio(resources fs.ReadFileFS) error {
138+
fileContents, err := resources.ReadFile("audio.sfx")
139+
if errors.Is(err, fs.ErrNotExist) {
140+
return nil
141+
}
142+
143+
if err = audio.Load(fileContents); err != nil {
144+
return fmt.Errorf("error loading audio.sfx: %w", err)
145+
}
146+
127147
return nil
128148
}
129149

0 commit comments

Comments
 (0)