package audio import ( "bytes" "errors" "os" "testing" ) func TestDecodeMP3ToPCM16Mono(t *testing.T) { encoded, err := os.ReadFile("testdata/sine_16k_mono.mp3") if err != nil { t.Fatal(err) } pcm16k, sourceRate, err := DecodeMP3ToPCM16Mono(encoded, 16000, 1<<20) if err != nil { t.Fatal(err) } if sourceRate != 16000 { t.Fatalf("source sample rate = %d, want 16000", sourceRate) } if len(pcm16k) == 0 || len(pcm16k)%2 != 0 { t.Fatalf("decoded PCM16 length = %d, want nonempty complete samples", len(pcm16k)) } pcm8k, decodedRate, err := DecodeMP3ToPCM16Mono(encoded, 8000, 1<<20) if err != nil { t.Fatal(err) } if decodedRate != sourceRate { t.Fatalf("source sample rate changed between conversions: %d != %d", decodedRate, sourceRate) } if len(pcm16k) != 2*len(pcm8k) { t.Fatalf("16 kHz output has %d bytes, 8 kHz output has %d; want 2:1", len(pcm16k), len(pcm8k)) } } func TestDecodeMP3ToPCM16MonoSupportsMPEG25At8k(t *testing.T) { // Fixture is a 1-second 440-Hz mono MP3 generated with FFmpeg/libmp3lame at 8 kHz, including ID3v2 metadata. encoded, err := os.ReadFile("testdata/sine_8k_mono_mpeg25.mp3") if err != nil { t.Fatal(err) } if !bytes.HasPrefix(encoded, []byte("ID3")) { t.Fatal("fixture must include the provider-style ID3v2 header") } pcm16, sourceRate, err := DecodeMP3ToPCM16Mono(encoded, 16000, 1<<20) if err != nil { t.Fatal(err) } if sourceRate != 8000 { t.Fatalf("source sample rate = %d, want 8000", sourceRate) } if len(pcm16) == 0 || len(pcm16)%2 != 0 { t.Fatalf("decoded PCM16 length = %d, want nonempty complete samples", len(pcm16)) } } func TestDecodeMP3ToPCM16MonoRejectsInvalidAndOversizedAudio(t *testing.T) { if _, _, err := DecodeMP3ToPCM16Mono([]byte("not an MP3"), 16000, 1<<20); err == nil { t.Fatal("invalid MP3 was accepted") } else if errors.Unwrap(err) == nil { t.Fatalf("decoder failure cause was hidden: %v", err) } encoded, err := os.ReadFile("testdata/sine_16k_mono.mp3") if err != nil { t.Fatal(err) } if _, _, err := DecodeMP3ToPCM16Mono(encoded, 16000, 2048); err == nil { t.Fatal("decoded output beyond the limit was accepted") } }