| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869 |
- package main
- import (
- "bytes"
- "encoding/binary"
- "math"
- )
- // tone returns the WAV test pack's tone (0.8 s at 440 Hz, then 0.2 s at
- // 880 Hz as an end marker) as a WAV file of integer PCM, optionally with the
- // WAVE_FORMAT_EXTENSIBLE header many audio tools write. bits is 16 or 24.
- func tone(rate, bits, channels int, ext bool) []byte {
- le := binary.LittleEndian
- width := bits / 8
- var data bytes.Buffer
- fade := 0.005 * float64(rate)
- for i := 0; i < rate; i++ {
- t := float64(i) / float64(rate)
- f := 440.0
- if t >= 0.8 {
- f = 880
- }
- env := math.Min(1, math.Min(float64(i)/fade, float64(rate-1-i)/fade))
- v := 0.5 * env * math.Sin(2*math.Pi*f*t)
- s := int32(math.Round(v * float64(int32(1)<<(bits-1)-1)))
- var b [4]byte
- le.PutUint32(b[:], uint32(s))
- for c := 0; c < channels; c++ {
- data.Write(b[:width])
- }
- }
- align := channels * width
- var fmtc bytes.Buffer
- tag := uint16(1)
- if ext {
- tag = 0xFFFE
- }
- for _, v := range []any{tag, uint16(channels), uint32(rate), uint32(rate * align), uint16(align), uint16(bits)} {
- binary.Write(&fmtc, le, v)
- }
- if ext {
- mask := uint32(4) // front centre
- if channels == 2 {
- mask = 3 // front left, front right
- }
- for _, v := range []any{uint16(22), uint16(bits), mask} {
- binary.Write(&fmtc, le, v)
- }
- // KSDATAFORMAT_SUBTYPE_PCM 00000001-0000-0010-8000-00aa00389b71
- fmtc.Write([]byte{1, 0, 0, 0, 0, 0, 0x10, 0, 0x80, 0, 0, 0xaa, 0, 0x38, 0x9b, 0x71})
- }
- var body bytes.Buffer
- body.WriteString("WAVEfmt ")
- binary.Write(&body, le, uint32(fmtc.Len()))
- body.Write(fmtc.Bytes())
- body.WriteString("data")
- binary.Write(&body, le, uint32(data.Len()))
- body.Write(data.Bytes())
- if data.Len()%2 == 1 {
- body.WriteByte(0)
- }
- var out bytes.Buffer
- out.WriteString("RIFF")
- binary.Write(&out, le, uint32(body.Len()))
- out.Write(body.Bytes())
- return out.Bytes()
- }
|