263 lines
6.8 KiB
Go
263 lines
6.8 KiB
Go
package Kirika
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/hex"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format/flac"
|
|
"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/hasher"
|
|
"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"
|
|
|
|
func doTest(format format.Format, 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()
|
|
source, err := format.Open(fp)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
|
|
//Decode
|
|
for range source.Blocks {
|
|
|
|
}
|
|
})
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFLACDecode(t *testing.T) {
|
|
doTest(flac.NewFormat(), ".flac", t)
|
|
}
|
|
func TestTTADecode(t *testing.T) {
|
|
doTest(tta.NewFormat(), ".tta", t)
|
|
}
|
|
func TestOpusDecode(t *testing.T) {
|
|
doTest(opus.NewFormat(), ".opus", t)
|
|
}
|
|
func TestMP3Decode(t *testing.T) {
|
|
doTest(mp3.NewFormat(), ".mp3", t)
|
|
}
|
|
|
|
func TestHasher24(t *testing.T) {
|
|
|
|
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) {
|
|
|
|
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)
|
|
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 != 437731779 {
|
|
t.Errorf("Wrong Sample Count %d != %d", sink.SamplesRead, 437731779)
|
|
}
|
|
}
|
|
|
|
func TestQueue(t *testing.T) {
|
|
|
|
const sampleRate = 41000
|
|
|
|
q := audio.NewQueue(sampleRate, 2, 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.Add(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) {
|
|
if len(q.GetQueue()) == 0 {
|
|
t.Log("Finished playback, closing\n")
|
|
q.Close()
|
|
}
|
|
t.Logf("Finished playback of %d %s: output %d samples\n", entry.Identifier, fullPath, entry.ReadSamples)
|
|
fp.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 != 218834361 {
|
|
t.Errorf("Wrong Sample Count %d != %d", sink.SamplesRead, 218834361)
|
|
}
|
|
}
|