Go で書き直した Ikemen
修订版 | 7bd84dc38b5304f074bea4ad7819601cfb52df0e (tree) |
---|---|
时间 | 2019-01-16 23:40:16 |
作者 | neatunsou <sisiy4excite@gmai...> |
Commiter | neatunsou |
mp3にとりあえず対応
@@ -5,3 +5,6 @@ go get -u github.com/go-gl/glfw/v3.2/glfw | ||
5 | 5 | go get -u github.com/go-gl/gl/v2.1/gl |
6 | 6 | go get -u github.com/jfreymuth/go-vorbis/ogg/vorbis |
7 | 7 | go get -u github.com/timshannon/go-openal/openal |
8 | +go get -u github.com/faiface/beep | |
9 | +go get -u github.com/hajimehoshi/oto | |
10 | +go get -u github.com/hajimehoshi/go-mp3 |
@@ -3,11 +3,18 @@ package main | ||
3 | 3 | import ( |
4 | 4 | "encoding/binary" |
5 | 5 | "fmt" |
6 | - "github.com/jfreymuth/go-vorbis/ogg/vorbis" | |
7 | - "github.com/timshannon/go-openal/openal" | |
8 | 6 | "io" |
9 | 7 | "math" |
10 | 8 | "os" |
9 | + "path/filepath" | |
10 | + "time" | |
11 | + | |
12 | + "github.com/jfreymuth/go-vorbis/ogg/vorbis" | |
13 | + "github.com/timshannon/go-openal/openal" | |
14 | + | |
15 | + "github.com/faiface/beep" | |
16 | + "github.com/faiface/beep/mp3" | |
17 | + "github.com/faiface/beep/speaker" | |
11 | 18 | ) |
12 | 19 | |
13 | 20 | const ( |
@@ -15,6 +22,11 @@ const ( | ||
15 | 22 | audioFrequency = 48000 |
16 | 23 | ) |
17 | 24 | |
25 | +// ------------------------------------------------------------------ | |
26 | +// Audio Source | |
27 | + | |
28 | +// AudioSource structure. | |
29 | +// It contains OpenAl's sound destination and buffer | |
18 | 30 | type AudioSource struct { |
19 | 31 | Src openal.Source |
20 | 32 | bufs openal.Buffers |
@@ -40,6 +52,9 @@ func (s *AudioSource) Delete() { | ||
40 | 52 | s.Src.Delete() |
41 | 53 | } |
42 | 54 | |
55 | +// ------------------------------------------------------------------ | |
56 | +// Mixer | |
57 | + | |
43 | 58 | type Mixer struct { |
44 | 59 | buf [audioOutLen * 2]float32 |
45 | 60 | sendBuf []int16 |
@@ -150,6 +165,9 @@ func (m *Mixer) Mix(wav []byte, fidx float64, bytesPerSample, channels int, | ||
150 | 165 | return float64(len(wav)) |
151 | 166 | } |
152 | 167 | |
168 | +// ------------------------------------------------------------------ | |
169 | +// Normalizer | |
170 | + | |
153 | 171 | type Normalizer struct { |
154 | 172 | mul float64 |
155 | 173 | l, r *NormalizerLR |
@@ -210,6 +228,9 @@ func (n *NormalizerLR) process(bai float64, sam *float32) float64 { | ||
210 | 228 | return bai |
211 | 229 | } |
212 | 230 | |
231 | +// ------------------------------------------------------------------ | |
232 | +// Vorbis | |
233 | + | |
213 | 234 | type Vorbis struct { |
214 | 235 | dec *vorbis.Vorbis |
215 | 236 | fp *os.File |
@@ -222,9 +243,12 @@ type Vorbis struct { | ||
222 | 243 | func newVorbis() *Vorbis { |
223 | 244 | return &Vorbis{openReq: make(chan string, 1), normalizer: NewNormalizer()} |
224 | 245 | } |
246 | + | |
247 | +// Opens a file asynchronously | |
225 | 248 | func (v *Vorbis) Open(file string) { |
226 | 249 | v.openReq <- file |
227 | 250 | } |
251 | + | |
228 | 252 | func (v *Vorbis) openFile(file string) bool { |
229 | 253 | v.clear() |
230 | 254 | var err error |
@@ -233,6 +257,7 @@ func (v *Vorbis) openFile(file string) bool { | ||
233 | 257 | } |
234 | 258 | return v.restart() |
235 | 259 | } |
260 | + | |
236 | 261 | func (v *Vorbis) restart() bool { |
237 | 262 | if v.fp == nil { |
238 | 263 | return false |
@@ -246,6 +271,7 @@ func (v *Vorbis) restart() bool { | ||
246 | 271 | v.buf = nil |
247 | 272 | return true |
248 | 273 | } |
274 | + | |
249 | 275 | func (v *Vorbis) clear() { |
250 | 276 | if v.dec != nil { |
251 | 277 | v.dec = nil |
@@ -255,6 +281,7 @@ func (v *Vorbis) clear() { | ||
255 | 281 | v.fp = nil |
256 | 282 | } |
257 | 283 | } |
284 | + | |
258 | 285 | func (v *Vorbis) samToAudioOut(buf [][]float32) (out []int16) { |
259 | 286 | var o1i int |
260 | 287 | if len(buf) == 1 { |
@@ -276,6 +303,7 @@ func (v *Vorbis) samToAudioOut(buf [][]float32) (out []int16) { | ||
276 | 303 | v.bufi -= float64(int(v.bufi)) |
277 | 304 | return |
278 | 305 | } |
306 | + | |
279 | 307 | func (v *Vorbis) read() []int16 { |
280 | 308 | select { |
281 | 309 | case file := <-v.openReq: |
@@ -302,6 +330,67 @@ func (v *Vorbis) read() []int16 { | ||
302 | 330 | return sys.nullSndBuf[:] |
303 | 331 | } |
304 | 332 | |
333 | +// ------------------------------------------------------------------ | |
334 | +// Bgm | |
335 | + | |
336 | +type Bgm struct { | |
337 | + filename string | |
338 | + vorbis *Vorbis | |
339 | + ctrlmp3 *beep.Ctrl | |
340 | +} | |
341 | + | |
342 | +func newBgm() *Bgm { | |
343 | + return &Bgm{ | |
344 | + vorbis: newVorbis(), | |
345 | + } | |
346 | +} | |
347 | + | |
348 | +func (bgm *Bgm) IsVorbis() bool { | |
349 | + return filepath.Ext(bgm.filename) == ".ogg" | |
350 | +} | |
351 | + | |
352 | +func (bgm *Bgm) IsMp3() bool { | |
353 | + return filepath.Ext(bgm.filename) == ".mp3" | |
354 | +} | |
355 | + | |
356 | +func (bgm *Bgm) Open(filename string) { | |
357 | + if filepath.Base(bgm.filename) != filepath.Base(filename) { | |
358 | + bgm.filename = filename | |
359 | + speaker.Clear() | |
360 | + | |
361 | + if bgm.IsVorbis() { | |
362 | + bgm.vorbis.Open(filename) | |
363 | + } else if bgm.IsMp3() { | |
364 | + bgm.ReadMp3() | |
365 | + } | |
366 | + } | |
367 | +} | |
368 | + | |
369 | +func (bgm *Bgm) ReadMp3() { | |
370 | + f, _ := os.Open(bgm.filename) | |
371 | + s, format, err := mp3.Decode(f) | |
372 | + if err != nil { | |
373 | + return | |
374 | + } | |
375 | + streamer := beep.Loop(-1, s) | |
376 | + bgm.ctrlmp3 = &beep.Ctrl{Streamer: streamer} | |
377 | + speaker.Init(format.SampleRate, format.SampleRate.N(time.Second/20)) | |
378 | + speaker.Play(bgm.ctrlmp3) | |
379 | + return | |
380 | +} | |
381 | +func (bgm *Bgm) Mp3Paused() { | |
382 | + speaker.Lock() | |
383 | + bgm.ctrlmp3.Paused = true | |
384 | + speaker.Unlock() | |
385 | + return | |
386 | +} | |
387 | +func (bgm *Bgm) ReadVorbis() []int16 { | |
388 | + return bgm.vorbis.read() | |
389 | +} | |
390 | + | |
391 | +// ------------------------------------------------------------------ | |
392 | +// Wave | |
393 | + | |
305 | 394 | type Wave struct { |
306 | 395 | SamplesPerSec uint32 |
307 | 396 | Channels uint16 |
@@ -400,12 +489,18 @@ func ReadWave(f *os.File, ofs int64) (*Wave, error) { | ||
400 | 489 | return &w, nil |
401 | 490 | } |
402 | 491 | |
492 | +// ------------------------------------------------------------------ | |
493 | +// Snd | |
494 | + | |
403 | 495 | type Snd struct { |
404 | 496 | table map[[2]int32]*Wave |
405 | 497 | ver, ver2 uint16 |
406 | 498 | } |
407 | 499 | |
408 | -func newSnd() *Snd { return &Snd{table: make(map[[2]int32]*Wave)} } | |
500 | +func newSnd() *Snd { | |
501 | + return &Snd{table: make(map[[2]int32]*Wave)} | |
502 | +} | |
503 | + | |
409 | 504 | func LoadSnd(filename string) (*Snd, error) { |
410 | 505 | s := newSnd() |
411 | 506 | f, err := os.Open(filename) |
@@ -478,6 +573,9 @@ func (s *Snd) play(gn [2]int32) bool { | ||
478 | 573 | return c.sound != nil |
479 | 574 | } |
480 | 575 | |
576 | +// ------------------------------------------------------------------ | |
577 | +// Sound | |
578 | + | |
481 | 579 | type Sound struct { |
482 | 580 | sound *Wave |
483 | 581 | volume int16 |
@@ -35,7 +35,7 @@ var sys = System{ | ||
35 | 35 | lifeMul: 1, team1VS2Life: 1, |
36 | 36 | turnsRecoveryRate: 1.0 / 300, |
37 | 37 | mixer: *newMixer(), |
38 | - bgm: *newVorbis(), | |
38 | + bgm: *newBgm(), | |
39 | 39 | sounds: newSounds(16), |
40 | 40 | allPalFX: *newPalFX(), |
41 | 41 | bgPalFX: *newPalFX(), |
@@ -87,7 +87,7 @@ type System struct { | ||
87 | 87 | debugScript string |
88 | 88 | debugDraw bool |
89 | 89 | mixer Mixer |
90 | - bgm Vorbis | |
90 | + bgm Bgm | |
91 | 91 | audioContext *openal.Context |
92 | 92 | nullSndBuf [audioOutLen * 2]int16 |
93 | 93 | sounds Sounds |
@@ -392,7 +392,15 @@ func (s *System) soundWrite() { | ||
392 | 392 | if bgmSrc.Src.BuffersProcessed() > 0 { |
393 | 393 | out := s.nullSndBuf[:] |
394 | 394 | if !s.nomusic { |
395 | - out = s.bgm.read() | |
395 | + if s.bgm.IsVorbis() { | |
396 | + out = s.bgm.ReadVorbis() | |
397 | + } else if s.bgm.IsMp3() && s.bgm.ctrlmp3 != nil { | |
398 | + s.bgm.ctrlmp3.Paused = false | |
399 | + } | |
400 | + } else { | |
401 | + if s.bgm.IsMp3() && s.bgm.ctrlmp3 != nil { | |
402 | + s.bgm.Mp3Paused() | |
403 | + } | |
396 | 404 | } |
397 | 405 | buf := bgmSrc.Src.UnqueueBuffer() |
398 | 406 | buf.SetDataInt16(openal.FormatStereo16, out, audioFrequency) |