// 程序化音效合成:正弦脉冲与噪声脉冲(无音频文件的占位实现,音频.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