|
| 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