918 lines
20 KiB
Go
918 lines
20 KiB
Go
package Kirika
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/sha256"
|
|
"encoding/hex"
|
|
"fmt"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/aac"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/flac"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/guess"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/mp3"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/opus"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/tta"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/packetizer"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/replaygain"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/hasher"
|
|
"io"
|
|
"os"
|
|
"path"
|
|
"testing"
|
|
)
|
|
|
|
var TestSampleLocations = []string{
|
|
"resources/samples/cYsmix - Haunted House/",
|
|
"resources/samples/Babbe Music - RADIANT DANCEFLOOR/",
|
|
}
|
|
|
|
const TestSingleSample24 = "resources/samples/cYsmix - Haunted House/11. The Great Rigid Desert.flac"
|
|
|
|
const TestSingleSample16 = "resources/samples/Babbe Music - RADIANT DANCEFLOOR/01. ENTER.flac"
|
|
const TestSingleSample16TTA = "resources/samples/Babbe Music - RADIANT DANCEFLOOR/01. ENTER.tta"
|
|
|
|
func doTest(ext string, t *testing.T) {
|
|
for _, location := range TestSampleLocations {
|
|
entries, err := os.ReadDir(location)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
for _, f := range entries {
|
|
if path.Ext(f.Name()) == ext {
|
|
fullPath := path.Join(location, f.Name())
|
|
t.Run(f.Name(), func(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(fullPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
decoders, err := guess.GetDecoders(fp, fullPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
source, err := guess.Open(fp, decoders)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
//Decode
|
|
for range source.Blocks {
|
|
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFLACDecode(t *testing.T) {
|
|
doTest(".flac", t)
|
|
}
|
|
func TestTTADecode(t *testing.T) {
|
|
doTest(".tta", t)
|
|
}
|
|
func TestOpusDecode(t *testing.T) {
|
|
doTest(".opus", t)
|
|
}
|
|
func TestMP3Decode(t *testing.T) {
|
|
doTest(".mp3", t)
|
|
}
|
|
func TestVorbisDecode(t *testing.T) {
|
|
doTest(".vorbis", t)
|
|
}
|
|
|
|
func TestReplayGainNormalization24(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
source = replaygain.NewNormalizationFilter(5).Process(source)
|
|
|
|
gain, peak, err := replaygain.GetTrackReplayGain(source)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
expect := "-0.033242 dB, 0.627992"
|
|
result := fmt.Sprintf("%f dB, %f", gain, peak)
|
|
if result != expect {
|
|
t.Errorf("Wrong ReplayGain %s != %s", result, expect)
|
|
}
|
|
}
|
|
|
|
func TestReplayGain24(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
gain, peak, err := replaygain.GetTrackReplayGain(source)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
expect := "-11.590850 dB, 1.000000"
|
|
result := fmt.Sprintf("%f dB, %f", gain, peak)
|
|
if result != expect {
|
|
t.Errorf("Wrong ReplayGain %s != %s", result, expect)
|
|
}
|
|
}
|
|
|
|
func TestReplayGain16(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fp, err := os.Open(TestSingleSample16)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
gain, peak, err := replaygain.GetTrackReplayGain(source)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
expect := "-7.748202 dB, 0.942137"
|
|
result := fmt.Sprintf("%f dB, %f", gain, peak)
|
|
if result != expect {
|
|
t.Errorf("Wrong ReplayGain %s != %s", result, expect)
|
|
}
|
|
}
|
|
|
|
func TestAlbumReplayGain(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
location := TestSampleLocations[1]
|
|
entries, err := os.ReadDir(location)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
var sources []audio.Source
|
|
for _, f := range entries {
|
|
if path.Ext(f.Name()) == ".flac" {
|
|
fullPath := path.Join(location, f.Name())
|
|
|
|
fp, err := os.Open(fullPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
decoders, err := guess.GetDecoders(fp, fullPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
source, err := guess.Open(fp, decoders)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
sources = append(sources, source)
|
|
}
|
|
}
|
|
|
|
albumGain, albumPeak, trackGains, trackPeaks, err := replaygain.GetAlbumReplayGain(sources)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
expect := "-8.539780 dB, 0.970916, [-7.748202 -9.020742 -9.192557 -8.015611 -8.303189 -9.071835 -9.356090 -8.114885 -7.760444 -7.317174 -8.339798 -8.906274 -8.001073], [0.942137 0.970916 0.970916 0.970916 0.942106 0.970916 0.970916 0.965606 0.970916 0.970916 0.942137 0.970916 0.942137]"
|
|
result := fmt.Sprintf("%f dB, %f, %f, %f", albumGain, albumPeak, trackGains, trackPeaks)
|
|
if result != expect {
|
|
t.Errorf("Wrong ReplayGain %s != %s", result, expect)
|
|
}
|
|
}
|
|
|
|
func TestHasher24(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, analyzerChannel, err := flac.NewFormat().OpenAnalyzer(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
chans := analyzerChannel.Split(2)
|
|
|
|
crc32 := hasher.NewHasher(chans[0], hasher.HashtypeCrc32)
|
|
sha256 := hasher.NewHasher(chans[1], hasher.HashtypeSha256)
|
|
//Decode
|
|
for range source.Blocks {
|
|
|
|
}
|
|
crc32.Wait()
|
|
sha256.Wait()
|
|
|
|
expectCrc32, _ := hex.DecodeString("A54636CD")
|
|
if bytes.Compare(crc32.GetResult(), expectCrc32) != 0 {
|
|
t.Errorf("Wrong CRC32 %08X != %08X", crc32.GetResult(), expectCrc32)
|
|
}
|
|
|
|
expectSha256, _ := hex.DecodeString("9B6715ED75B6C8074B749C630AC9C626994080DEACBEA363976391366DA4E4FA")
|
|
if bytes.Compare(sha256.GetResult(), expectSha256) != 0 {
|
|
t.Errorf("Wrong SHA256 %08X != %08X", sha256.GetResult(), expectSha256)
|
|
}
|
|
|
|
}
|
|
|
|
func TestHasher16(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fp, err := os.Open(TestSingleSample16)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, analyzerChannel, err := flac.NewFormat().OpenAnalyzer(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
channels := analyzerChannel.Split(4)
|
|
cueToolsCrc32 := hasher.NewHasher(channels[0].SkipStartSamples(hasher.Int16SamplesPerSector*10), hasher.HashtypeCrc32)
|
|
arChannels := channels[1].SkipStartSamples(hasher.Int16SamplesPerSector*5 - 1).Split(2)
|
|
accurateRipV1 := hasher.NewHasher(arChannels[0], hasher.HashtypeAccurateRipV1Start)
|
|
accurateRipV2 := hasher.NewHasher(arChannels[1], hasher.HashtypeAccurateRipV2Start)
|
|
crc32 := hasher.NewHasher(channels[2], hasher.HashtypeCrc32)
|
|
sha256Result := hasher.NewHasher(channels[3], hasher.HashtypeSha256)
|
|
|
|
//Decode
|
|
for range source.Blocks {
|
|
|
|
}
|
|
cueToolsCrc32.Wait()
|
|
accurateRipV1.Wait()
|
|
accurateRipV2.Wait()
|
|
crc32.Wait()
|
|
sha256Result.Wait()
|
|
|
|
expectCueToolsCrc32, _ := hex.DecodeString("18701E02")
|
|
if bytes.Compare(cueToolsCrc32.GetResult(), expectCueToolsCrc32) != 0 {
|
|
t.Errorf("Wrong CTDB CRC32 %08X != %08X", cueToolsCrc32.GetResult(), expectCueToolsCrc32)
|
|
}
|
|
|
|
expectAccurateRipV1, _ := hex.DecodeString("5593DA89")
|
|
if bytes.Compare(accurateRipV1.GetResult(), expectAccurateRipV1) != 0 {
|
|
t.Errorf("Wrong AccurateRip V1 %08X != %08X", accurateRipV1.GetResult(), expectAccurateRipV1)
|
|
}
|
|
|
|
expectAccurateRipV2, _ := hex.DecodeString("DAA40E75")
|
|
if bytes.Compare(accurateRipV2.GetResult(), expectAccurateRipV2) != 0 {
|
|
t.Errorf("Wrong AccurateRip V2 %08X != %08X", accurateRipV2.GetResult(), expectAccurateRipV2)
|
|
}
|
|
|
|
expectCrc32, _ := hex.DecodeString("50CE5057")
|
|
if bytes.Compare(crc32.GetResult(), expectCrc32) != 0 {
|
|
t.Errorf("Wrong CRC32 %08X != %08X", crc32.GetResult(), expectCrc32)
|
|
}
|
|
|
|
expectSha256, _ := hex.DecodeString("FEDF080D500D1A49DF8366BE619918D2A5D00413B7C7613A39DC00659FA25AC6")
|
|
if bytes.Compare(sha256Result.GetResult(), expectSha256) != 0 {
|
|
t.Errorf("Wrong SHA256 %X != %X", sha256Result.GetResult(), expectSha256)
|
|
}
|
|
|
|
}
|
|
|
|
func TestHasher16TTA(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
fp, err := os.Open(TestSingleSample16TTA)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, analyzerChannel, err := tta.NewFormat().OpenAnalyzer(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
channels := analyzerChannel.Split(4)
|
|
cueToolsCrc32 := hasher.NewHasher(channels[0].SkipStartSamples(hasher.Int16SamplesPerSector*10), hasher.HashtypeCrc32)
|
|
arChannels := channels[1].SkipStartSamples(hasher.Int16SamplesPerSector*5 - 1).Split(2)
|
|
accurateRipV1 := hasher.NewHasher(arChannels[0], hasher.HashtypeAccurateRipV1Start)
|
|
accurateRipV2 := hasher.NewHasher(arChannels[1], hasher.HashtypeAccurateRipV2Start)
|
|
crc32 := hasher.NewHasher(channels[2], hasher.HashtypeCrc32)
|
|
sha256 := hasher.NewHasher(channels[3], hasher.HashtypeSha256)
|
|
|
|
//Decode
|
|
for range source.Blocks {
|
|
|
|
}
|
|
cueToolsCrc32.Wait()
|
|
accurateRipV1.Wait()
|
|
accurateRipV2.Wait()
|
|
crc32.Wait()
|
|
sha256.Wait()
|
|
|
|
expectCueToolsCrc32, _ := hex.DecodeString("18701E02")
|
|
if bytes.Compare(cueToolsCrc32.GetResult(), expectCueToolsCrc32) != 0 {
|
|
t.Errorf("Wrong CTDB CRC32 %08X != %08X", cueToolsCrc32.GetResult(), expectCueToolsCrc32)
|
|
}
|
|
|
|
expectAccurateRipV1, _ := hex.DecodeString("5593DA89")
|
|
if bytes.Compare(accurateRipV1.GetResult(), expectAccurateRipV1) != 0 {
|
|
t.Errorf("Wrong AccurateRip V1 %08X != %08X", accurateRipV1.GetResult(), expectAccurateRipV1)
|
|
}
|
|
|
|
expectAccurateRipV2, _ := hex.DecodeString("DAA40E75")
|
|
if bytes.Compare(accurateRipV2.GetResult(), expectAccurateRipV2) != 0 {
|
|
t.Errorf("Wrong AccurateRip V2 %08X != %08X", accurateRipV2.GetResult(), expectAccurateRipV2)
|
|
}
|
|
|
|
expectCrc32, _ := hex.DecodeString("50CE5057")
|
|
if bytes.Compare(crc32.GetResult(), expectCrc32) != 0 {
|
|
t.Errorf("Wrong CRC32 %08X != %08X", crc32.GetResult(), expectCrc32)
|
|
}
|
|
|
|
expectSha256, _ := hex.DecodeString("FEDF080D500D1A49DF8366BE619918D2A5D00413B7C7613A39DC00659FA25AC6")
|
|
if bytes.Compare(sha256.GetResult(), expectSha256) != 0 {
|
|
t.Errorf("Wrong SHA256 %X != %X", sha256.GetResult(), expectSha256)
|
|
}
|
|
|
|
}
|
|
|
|
func TestFilterChain(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
const sampleRate = 16000
|
|
|
|
result := audio.NewFilterChain(source, audio.MonoFilter{}, audio.NewResampleFilter(sampleRate, audio.BandlimitedFastest, 0), audio.StereoFilter{})
|
|
|
|
sink := audio.NewForwardSink(audio.NewNullSink())
|
|
sink.Process(result)
|
|
|
|
if result.SampleRate != sampleRate {
|
|
t.Errorf("Wrong SampleRate %d != %d", result.SampleRate, sampleRate)
|
|
}
|
|
if result.Channels != 2 {
|
|
t.Errorf("Wrong Channel Count %d != %d", result.SampleRate, 2)
|
|
}
|
|
if sink.SamplesRead != 6284999 {
|
|
t.Errorf("Wrong Sample Count %d != %d", sink.SamplesRead, 6284999)
|
|
}
|
|
}
|
|
|
|
func TestEncodeFLAC(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "encode_test_*.flac")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
err = flac.NewFormat().Encode(source, target, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestPacketizeFLAC(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
reader, writer := io.Pipe()
|
|
|
|
shaHasher := sha256.New()
|
|
shaPacketHasher := sha256.New()
|
|
encodeReader := io.TeeReader(reader, shaHasher)
|
|
|
|
go func() {
|
|
defer writer.Close()
|
|
err = flac.NewFormat().Encode(source, writer, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}()
|
|
|
|
pipePacketizer := packetizer.NewFLACPacketizer(encodeReader)
|
|
packetCount := 0
|
|
packetBytes := 0
|
|
for {
|
|
packet := pipePacketizer.GetPacket()
|
|
if packet == nil {
|
|
break
|
|
}
|
|
packetCount++
|
|
packetBytes += len(packet.GetData())
|
|
shaPacketHasher.Write(packet.GetData())
|
|
}
|
|
if packetCount != 4231 {
|
|
t.Errorf("Wrong Packet Count %d != %d", packetCount, 4231)
|
|
}
|
|
if packetBytes != 51513533 {
|
|
t.Errorf("Wrong Packet Bytes %d != %d", packetBytes, 51513533)
|
|
}
|
|
if bytes.Compare(shaHasher.Sum([]byte{}), shaPacketHasher.Sum([]byte{})) != 0 {
|
|
t.Errorf("Mismatch on byte output %X != %X", shaPacketHasher.Sum([]byte{}), shaHasher.Sum([]byte{}))
|
|
}
|
|
}
|
|
|
|
func TestEncodeTTA(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "encode_test_*.tta")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
err = tta.NewFormat().Encode(source, target, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestEncodeMP3(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "encode_test_*.mp3")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
err = mp3.NewFormat().Encode(source, target, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestPacketizeMP3(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
reader, writer := io.Pipe()
|
|
|
|
go func() {
|
|
defer writer.Close()
|
|
err = mp3.NewFormat().Encode(source, writer, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}()
|
|
|
|
pipePacketizer := packetizer.NewMp3Packetizer(reader)
|
|
packetCount := 0
|
|
packetBytes := 0
|
|
for {
|
|
packet := pipePacketizer.GetPacket()
|
|
if packet == nil {
|
|
break
|
|
}
|
|
packetCount++
|
|
packetBytes += len(packet.GetData())
|
|
}
|
|
if packetCount != 15040 {
|
|
t.Errorf("Wrong Packet Count %d != %d", packetCount, 15040)
|
|
}
|
|
if packetBytes != 13901254 {
|
|
t.Errorf("Wrong Packet Bytes %d != %d", packetBytes, 13901254)
|
|
}
|
|
}
|
|
|
|
func TestEncodeOpus(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "encode_test_*.opus")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
options := make(map[string]interface{})
|
|
options["bitrate"] = "256k"
|
|
|
|
err = opus.NewFormat().Encode(audio.NewResampleFilter(opus.FixedSampleRate, audio.Linear, 0).Process(source), target, options)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestPacketizeOgg(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
reader, writer := io.Pipe()
|
|
|
|
go func() {
|
|
defer writer.Close()
|
|
err = opus.NewFormat().Encode(audio.NewResampleFilter(opus.FixedSampleRate, audio.Linear, 0).Process(source), writer, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}()
|
|
|
|
pipePacketizer := packetizer.NewOggPacketizer(reader)
|
|
packetCount := 0
|
|
packetBytes := 0
|
|
for {
|
|
packet := pipePacketizer.GetPacket()
|
|
if packet == nil {
|
|
break
|
|
}
|
|
packetCount++
|
|
packetBytes += len(packet.GetData())
|
|
}
|
|
if packetCount != 395 {
|
|
t.Errorf("Wrong Packet Count %d != %d", packetCount, 395)
|
|
}
|
|
if packetBytes != 5962688 {
|
|
t.Errorf("Wrong Packet Bytes %d != %d", packetBytes, 5962688)
|
|
}
|
|
}
|
|
|
|
func TestEncodeAAC(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "encode_test_*.aac")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
options := make(map[string]interface{})
|
|
options["bitrate"] = "256k"
|
|
|
|
err = aac.NewFormat().Encode(source, target, options)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestDecodeAAC(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "decode_test_*.aac")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
options := make(map[string]interface{})
|
|
options["bitrate"] = "256k"
|
|
|
|
err = aac.NewFormat().Encode(source, target, options)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target.Seek(0, io.SeekStart)
|
|
|
|
source, err = aac.NewFormat().Open(target)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
//Decode
|
|
for range source.Blocks {
|
|
|
|
}
|
|
}
|
|
|
|
func TestPacketizeADTS(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
reader, writer := io.Pipe()
|
|
|
|
go func() {
|
|
defer writer.Close()
|
|
err = aac.NewFormat().Encode(source, writer, nil)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}()
|
|
|
|
pipePacketizer := packetizer.NewAdtsPacketizer(reader)
|
|
packetCount := 0
|
|
packetBytes := 0
|
|
for {
|
|
packet := pipePacketizer.GetPacket()
|
|
if packet == nil {
|
|
break
|
|
}
|
|
packetCount++
|
|
packetBytes += len(packet.GetData())
|
|
}
|
|
if packetCount != 16920 {
|
|
t.Errorf("Wrong Packet Count %d != %d", packetCount, 16920)
|
|
}
|
|
if packetBytes != 6436973 {
|
|
t.Errorf("Wrong Packet Bytes %d != %d", packetBytes, 6436973)
|
|
}
|
|
}
|
|
|
|
func TestEncodeAACHE(t *testing.T) {
|
|
t.Parallel()
|
|
fp, err := os.Open(TestSingleSample24)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
defer fp.Close()
|
|
source, err := flac.NewFormat().Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
target, err := os.CreateTemp("/tmp", "encode_test_*.aac")
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
defer func() {
|
|
name := target.Name()
|
|
target.Close()
|
|
os.Remove(name)
|
|
}()
|
|
|
|
options := make(map[string]interface{})
|
|
options["bitrate"] = "256k"
|
|
options["mode"] = "hev2"
|
|
|
|
err = aac.NewFormat().Encode(source, target, options)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
}
|
|
|
|
func TestQueue(t *testing.T) {
|
|
t.Parallel()
|
|
|
|
const sampleRate = 44100
|
|
|
|
q := audio.NewQueue(sampleRate, 2)
|
|
flacFormat := flac.NewFormat()
|
|
|
|
for _, location := range TestSampleLocations {
|
|
entries, err := os.ReadDir(location)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
for _, f := range entries {
|
|
if path.Ext(f.Name()) == ".flac" {
|
|
fullPath := path.Join(location, f.Name())
|
|
fp, err := os.Open(fullPath)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
source, err := flacFormat.Open(fp)
|
|
if err != nil {
|
|
fp.Close()
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
q.AddTail(source, func(q *audio.Queue, entry *audio.QueueEntry) {
|
|
t.Logf("Started playback of %d %s\n", entry.Identifier, fullPath)
|
|
}, func(q *audio.Queue, entry *audio.QueueEntry) {
|
|
t.Logf("Finished playback of %d %s: output %d samples\n", entry.Identifier, fullPath, entry.ReadSamples)
|
|
}, func(q *audio.Queue, entry *audio.QueueEntry) {
|
|
fp.Close()
|
|
if q.GetQueueSize() == 0 {
|
|
t.Log("Finished playback, closing\n")
|
|
q.Close()
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
|
|
//Decode
|
|
result := q.GetSource()
|
|
|
|
sink := audio.NewForwardSink(audio.NewNullSink())
|
|
sink.Process(result)
|
|
|
|
q.Wait()
|
|
|
|
if result.SampleRate != sampleRate {
|
|
t.Errorf("Wrong SampleRate %d != %d", result.SampleRate, sampleRate)
|
|
}
|
|
if result.Channels != 2 {
|
|
t.Errorf("Wrong Channel Count %d != %d", result.SampleRate, 2)
|
|
}
|
|
if sink.SamplesRead != 470828559 {
|
|
t.Errorf("Wrong Sample Count %d != %d", sink.SamplesRead, 470828559)
|
|
}
|
|
}
|