Skip to content

Commit acf84e3

Browse files
committed
Extract PC speaker simulation to GoBeep86
1 parent 4c88385 commit acf84e3

5 files changed

Lines changed: 154 additions & 1696 deletions

File tree

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ require (
1919
replace github.com/sinshu/go-meltysynth => github.com/Distortions81/go-meltysynth v0.1.2
2020

2121
require (
22+
github.com/Distortions81/GoBeep86 v0.0.0
2223
github.com/ebitengine/gomobile v0.0.0-20260211053922-3d992dae95d1 // indirect
2324
github.com/ebitengine/hideconsole v1.0.0 // indirect
2425
github.com/ebitengine/oto/v3 v3.4.0 // indirect
@@ -27,3 +28,5 @@ require (
2728
github.com/klauspost/cpuid/v2 v2.3.0 // indirect
2829
golang.org/x/sync v0.20.0 // indirect
2930
)
31+
32+
replace github.com/Distortions81/GoBeep86 => ../GoBeep86
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package audiofx
2+
3+
import "time"
4+
5+
type ebitenPlayer interface {
6+
Play()
7+
Pause()
8+
Rewind() error
9+
SetBufferSize(time.Duration)
10+
SetVolume(float64)
11+
IsPlaying() bool
12+
Close() error
13+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package audiofx
2+
3+
import (
4+
"math"
5+
6+
"gddoom/internal/sound"
7+
)
8+
9+
var pcSpeakerToneMixPattern = []int{0, 1, 0}
10+
11+
func pcSpeakerToneInterleaveHoldTicks(effectTone sound.PCSpeakerTone, musicTone sound.PCSpeakerTone, tickRate int) int {
12+
if tickRate <= 0 {
13+
tickRate = 560
14+
}
15+
holdSeconds := 1.0 / pcSpeakerToneInterleaveTargetHz
16+
lowestHz := math.MaxFloat64
17+
for _, tone := range [...]sound.PCSpeakerTone{effectTone, musicTone} {
18+
divisor := tone.ToneDivisor()
19+
if !tone.Active || divisor == 0 {
20+
continue
21+
}
22+
hz := float64(sound.PCSpeakerPITHz()) / float64(divisor)
23+
if hz > 0 && hz < lowestHz {
24+
lowestHz = hz
25+
}
26+
}
27+
if lowestHz != math.MaxFloat64 {
28+
minSeconds := 1.0 / lowestHz
29+
if minSeconds > holdSeconds {
30+
holdSeconds = minSeconds
31+
}
32+
}
33+
hold := int(math.Ceil(holdSeconds * float64(tickRate)))
34+
if hold < 1 {
35+
return 1
36+
}
37+
return hold
38+
}
39+
40+
func toneAtTick(seq []sound.PCSpeakerTone, seqTickRate int, outTickRate int, tick int) (sound.PCSpeakerTone, bool) {
41+
if len(seq) == 0 || tick < 0 {
42+
return sound.PCSpeakerTone{}, false
43+
}
44+
seqTickRate = normalizePCSpeakerTickRate(seqTickRate)
45+
outTickRate = normalizePCSpeakerTickRate(outTickRate)
46+
idx := int((int64(tick) * int64(seqTickRate)) / int64(outTickRate))
47+
if idx < 0 || idx >= len(seq) {
48+
return sound.PCSpeakerTone{}, false
49+
}
50+
return seq[idx], true
51+
}
52+
53+
func totalTicksAtRate(seqLen int, seqTickRate int, outTickRate int) int {
54+
if seqLen <= 0 {
55+
return 0
56+
}
57+
seqTickRate = normalizePCSpeakerTickRate(seqTickRate)
58+
outTickRate = normalizePCSpeakerTickRate(outTickRate)
59+
return int(math.Ceil(float64(seqLen) * float64(outTickRate) / float64(seqTickRate)))
60+
}
61+
62+
func normalizePCSpeakerTickRate(rate int) int {
63+
if rate <= 0 {
64+
return 140
65+
}
66+
return rate
67+
}

0 commit comments

Comments
 (0)