You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
66 lines
2.3 KiB
66 lines
2.3 KiB
extends Node
|
|
## 简易音效:用 AudioStreamWAV 程序合成 4 种音效。
|
|
## 每次播放 new 一个 AudioStreamPlayer,结束后自动释放。
|
|
## 之后要替换成 .wav 素材,把 _generate_xxx() 换成 load() 资源即可。
|
|
|
|
const SAMPLE_RATE: int = 22050
|
|
|
|
func play_hit() -> void:
|
|
_play(_make_sin(880.0, 0.05, 0.4))
|
|
|
|
func play_break() -> void:
|
|
_play(_make_noise(0.18, 0.5))
|
|
|
|
func play_lost() -> void:
|
|
_play(_make_sweep(440.0, 110.0, 0.4, 0.5))
|
|
|
|
func play_win() -> void:
|
|
_play(_make_sweep(523.0, 1046.0, 0.5, 0.5))
|
|
|
|
# ───────── 合成函数 ─────────
|
|
|
|
func _make_sin(freq: float, duration: float, volume: float) -> AudioStreamWAV:
|
|
return _build(duration, func(t: float, d: float) -> float:
|
|
var env: float = 1.0 - t / d # 线性衰减
|
|
return sin(TAU * freq * t) * volume * env
|
|
)
|
|
|
|
func _make_noise(duration: float, volume: float) -> AudioStreamWAV:
|
|
return _build(duration, func(t: float, d: float) -> float:
|
|
var env: float = 1.0 - t / d
|
|
return randf_range(-volume, volume) * env
|
|
)
|
|
|
|
func _make_sweep(from_freq: float, to_freq: float, duration: float, volume: float) -> AudioStreamWAV:
|
|
return _build(duration, func(t: float, d: float) -> float:
|
|
var progress: float = t / d
|
|
var f: float = lerp(from_freq, to_freq, progress)
|
|
var env: float = (1.0 - progress) * (1.0 - progress) # 平方衰减
|
|
return sin(TAU * f * t) * volume * env
|
|
)
|
|
|
|
# 构造一个 AudioStreamWAV;sample_fn(t, duration) 返回 [-1, 1] 的振幅
|
|
func _build(duration: float, sample_fn: Callable) -> AudioStreamWAV:
|
|
var sample_count: int = int(SAMPLE_RATE * duration)
|
|
var data := PackedByteArray()
|
|
data.resize(sample_count * 2) # 16-bit 单声道
|
|
for i in range(sample_count):
|
|
var t: float = float(i) / SAMPLE_RATE
|
|
var s: float = clamp(sample_fn.call(t, duration), -1.0, 1.0)
|
|
# 16-bit: 范围 [-32768, 32767]
|
|
var sample_i: int = int(s * 32767.0)
|
|
data[2 * i] = sample_i & 0xFF
|
|
data[2 * i + 1] = (sample_i >> 8) & 0xFF
|
|
var stream := AudioStreamWAV.new()
|
|
stream.format = AudioStreamWAV.FORMAT_16_BITS
|
|
stream.mix_rate = SAMPLE_RATE
|
|
stream.stereo = false
|
|
stream.data = data
|
|
return stream
|
|
|
|
func _play(stream: AudioStream) -> void:
|
|
var player := AudioStreamPlayer.new()
|
|
player.stream = stream
|
|
add_child(player)
|
|
player.play()
|
|
player.finished.connect(player.queue_free)
|
|
|