Files
pixel-platformer/game/render/audioBackend.py
T

72 lines
1.8 KiB
Python

import array
import math
import pygame
toneTable = {
"jump": (660, 90),
"doubleJump": (820, 90),
"dash": (300, 80),
"stomp": (200, 120),
"pickup": (900, 70),
"hurt": (160, 160),
"die": (110, 300),
"shoot": (420, 70),
"checkpoint": (1040, 120),
"levelComplete": (760, 260),
"spark": (520, 40),
}
def synthTone(frequency, milliseconds, volume=0.25):
mixerInfo = pygame.mixer.get_init()
if mixerInfo is None:
return None
sampleRate, _, channels = mixerInfo
frames = int(sampleRate * milliseconds / 1000.0)
amplitude = int(32767 * volume)
samples = array.array("h")
for index in range(frames):
envelope = 1.0 - index / frames
value = int(amplitude * envelope * (1.0 if math.sin(2.0 * math.pi * frequency * index / sampleRate) >= 0 else -1.0))
for _ in range(max(1, channels)):
samples.append(value)
return pygame.mixer.Sound(buffer=samples.tobytes())
class PygameAudio:
def __init__(self):
self.enabled = False
self.sounds = {}
try:
if pygame.mixer.get_init() is None:
pygame.mixer.init()
for name, (frequency, duration) in toneTable.items():
sound = synthTone(frequency, duration)
if sound is not None:
self.sounds[name] = sound
self.enabled = bool(self.sounds)
except pygame.error:
self.enabled = False
def sink(self, event):
if not self.enabled:
return
sound = self.sounds.get(event.name)
if sound is not None:
sound.play()
class NullAudio:
enabled = False
def sink(self, event):
pass
def buildAudioSink():
backend = PygameAudio()
if backend.enabled:
return backend.sink
return NullAudio().sink