Files
Maven/internal/audio/audio_test.go
T
2026-07-03 00:32:48 +02:00

104 lines
2.9 KiB
Go

package audio
import (
"bytes"
"encoding/binary"
"testing"
)
func TestAudioDuration(t *testing.T) {
t.Parallel()
// 16k mono int16 ⇒ 2 bytes/sample ⇒ 32000 bytes/second.
a := Audio{Format: PCM16kMono, Bytes: make([]byte, 32000)}
if got, want := a.Duration(), 1.0; got != want {
t.Fatalf("Duration: got %v, want %v", got, want)
}
// 4 seconds
a.Bytes = make([]byte, 128000)
if got, want := a.Duration(), 4.0; got != want {
t.Fatalf("Duration: got %v, want %v", got, want)
}
}
func TestAudioDurationEmptyAndBad(t *testing.T) {
t.Parallel()
if (Audio{}).Duration() != 0 {
t.Fatalf("empty audio: Duration should be 0")
}
a := Audio{Format: Format{}, Bytes: make([]byte, 32000)}
if a.Duration() != 0 {
t.Fatalf("zero format: Duration should be 0")
}
a = Audio{Format: Format{SampleRate: 16000, Channels: 1, SampleBits: 16, Encoding: "opus"}, Bytes: make([]byte, 32000)}
if a.Duration() != 0 {
t.Fatalf("unsupported encoding: Duration should be 0")
}
}
func TestFormatIsValid(t *testing.T) {
t.Parallel()
if !PCM16kMono.IsValid() {
t.Fatalf("PCM16kMono should be valid")
}
if (Format{SampleRate: 8000, Channels: 1, SampleBits: 16, Encoding: "pcm_s16le"}).IsValid() {
t.Fatalf("8k should be rejected")
}
if (Format{SampleRate: 16000, Channels: 2, SampleBits: 16, Encoding: "pcm_s16le"}).IsValid() {
t.Fatalf("stereo should be rejected")
}
}
func TestWAVRoundTrip(t *testing.T) {
t.Parallel()
// 0.5s of square wave (alternating samples) — sndfile/aplay can play it.
const nsamp = 8000
pcm := make([]byte, nsamp*2)
for i := 0; i < nsamp; i++ {
var v int16 = -16384
if i%2 == 0 {
v = 16384
}
binary.LittleEndian.PutUint16(pcm[i*2:], uint16(v))
}
wav, err := WAVFromPCM(PCM16kMono, pcm)
if err != nil {
t.Fatalf("WAVFromPCM: %v", err)
}
if len(wav) != 44+len(pcm) {
t.Fatalf("wav length: got %d, want %d", len(wav), 44+len(pcm))
}
if string(wav[0:4]) != "RIFF" || string(wav[8:12]) != "WAVE" {
t.Fatalf("missing RIFF/WAVE marker: %q", wav[0:12])
}
f, pcm2, err := PCMFromWAV(wav)
if err != nil {
t.Fatalf("PCMFromWAV: %v", err)
}
if !f.IsValid() {
t.Fatalf("parsed format invalid: %+v", f)
}
if !bytes.Equal(pcm, pcm2) {
t.Fatalf("PCM mismatch after round-trip: in=%d bytes, out=%d bytes", len(pcm), len(pcm2))
}
}
func TestPCMFromWAVRejectsNonCanonical(t *testing.T) {
t.Parallel()
// too short
if _, _, err := PCMFromWAV([]byte("RIFF")); err == nil {
t.Fatalf("short input should error")
}
// bad RIFF marker
bad := make([]byte, 44)
copy(bad[0:4], []byte("RIFF"))
copy(bad[8:12], []byte("XXXX"))
if _, _, err := PCMFromWAV(bad); err == nil {
t.Fatalf("non-WAVE marker should error")
}
// format code 3 (float), canonical otherwise
wav, _ := WAVFromPCM(PCM16kMono, []byte{0, 0})
binary.LittleEndian.PutUint16(wav[20:22], 3) // IEEE float, not PCM
if _, _, err := PCMFromWAV(wav); err == nil {
t.Fatalf("non-PCM format should error")
}
}