Files
ngzz-mc/internal/audio/synth.go

70 lines
1.5 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 程序化音效合成:正弦脉冲与噪声脉冲(无音频文件的占位实现,音频.md §6)。
package audio
import (
"math"
"math/rand"
"time"
"github.com/faiface/beep"
)
// sineBurst 正弦脉冲(频率 Hz、时长秒)。
func sineBurst(freq float64, dur float64) *burst {
n := int(44100 * dur)
return &burst{n: n, gen: func(t int) float64 {
env := 1 - float64(t)/float64(n) // 线性衰减包络
return env * 0.5 * math.Sin(2*math.Pi*freq*float64(t)/44100)
}}
}
// noiseBurst 噪声脉冲(破坏音效感)。
func noiseBurst(dur float64) *burst {
n := int(44100 * dur)
rng := rand.New(rand.NewSource(42))
return &burst{n: n, gen: func(t int) float64 {
env := 1 - float64(t)/float64(n)
return env * 0.4 * (rng.Float64()*2 - 1)
}}
}
// burst 有限长度合成流。
type burst struct {
n int
pos int
gen func(t int) float64
}
// Stream beep.Streamer:填充采样。
func (b *burst) Stream(samples [][2]float64) (int, bool) {
i := 0
for ; i < len(samples) && b.pos < b.n; i++ {
v := b.gen(b.pos)
samples[i][0] = v
samples[i][1] = v
b.pos++
}
return i, b.pos >= b.n
}
// Err 无错误。
func (b *burst) Err() error { return nil }
// Len 时长采样数。
func (b *burst) Len() int { return b.n }
// Position 当前位置。
func (b *burst) Position() int { return b.pos }
// Seek 跳转。
func (b *burst) Seek(p int) error {
if p < 0 || p > b.n {
p = 0
}
b.pos = p
return nil
}
var _ beep.StreamSeeker = (*burst)(nil)
var _ = time.Second