Compare commits

...

3 commits

Author SHA1 Message Date
DataHoarder 9ac1f64bb9
Use proper float32 analyzer on cmd/decode, add SHA256 and CRC32 hashes
All checks were successful
continuous-integration/drone/push Build is passing
2023-01-29 14:34:26 +01:00
DataHoarder 88915d15d4
Properly handle float32 samples for analyzer 2023-01-29 14:29:12 +01:00
DataHoarder e26156194d
Fix Int32ToBytes on cgo vector 2023-01-29 14:28:51 +01:00
3 changed files with 32 additions and 46 deletions

View file

@ -3,8 +3,10 @@ package format
import (
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
"io"
"runtime"
"sync"
"sync/atomic"
"unsafe"
)
const chanBuf = 16
@ -37,13 +39,17 @@ func NewAnalyzerChannel(source audio.Source, err error) (audio.Source, AnalyzerC
go func() {
defer close(channel)
if _, ok := sources[1].(audio.TypedSource[float32]); ok {
for block := range sources[1].ToInt32(source.GetBitDepth()).GetBlocks() {
if float32Source, ok := sources[1].(audio.TypedSource[float32]); ok {
for block := range float32Source.GetBlocks() {
//Convert float32 to int32 representation with 32 bit depth, so it hashes the same way
buf := make([]int32, len(block))
copy(buf, unsafe.Slice((*int32)(unsafe.Pointer(&block[0])), len(block)))
runtime.KeepAlive(block)
channel <- &AnalyzerPacket{
Samples: block,
Samples: buf,
Channels: source.GetChannels(),
SampleRate: source.GetSampleRate(),
BitDepth: source.GetBitDepth(),
BitDepth: 32,
}
}
} else {

View file

@ -1,20 +1,16 @@
package main
import (
"crypto/md5"
"encoding/hex"
"flag"
"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/guess"
"git.gammaspectra.live/S.O.N.G/Kirika/hasher"
"hash"
"log"
"os"
"runtime"
"strconv"
"time"
"unsafe"
)
func main() {
@ -49,7 +45,7 @@ func main() {
source, analyzer, err := guess.OpenAnalyzer(fp, decoders)
if err != nil {
source, err = guess.Open(fp, decoders)
source, analyzer, err = format.NewAnalyzerChannel(guess.Open(fp, decoders))
}
if err != nil {
@ -57,26 +53,18 @@ func main() {
return
}
var h *hasher.Hasher
analyzers := analyzer.Split(3)
if analyzer != nil {
h = hasher.NewHasher(analyzer, hasher.HashtypeMd5)
}
var rawFloat32Hasher hash.Hash
hCRC32 := hasher.NewHasher(analyzers[0], hasher.HashtypeCrc32)
hSHA256 := hasher.NewHasher(analyzers[1], hasher.HashtypeSha256)
hMD5 := hasher.NewHasher(analyzers[2], hasher.HashtypeMd5)
var sampleCount, blockCount uint64
if f32Source, ok := source.(audio.TypedSource[float32]); ok {
rawFloat32Hasher = md5.New()
log.Printf("Decoding as float32 @ %dHz %d channel(s)", f32Source.GetSampleRate(), f32Source.GetChannels())
for b := range f32Source.GetBlocks() {
blockCount++
sampleCount += uint64(len(b))
func() {
defer runtime.KeepAlive(b)
rawFloat32Hasher.Write(unsafe.Slice((*byte)(unsafe.Pointer(&b[0])), len(b)*int(unsafe.Sizeof(float32(0)))))
}()
}
sampleCount /= uint64(f32Source.GetChannels())
} else if i16Source, ok := source.(audio.TypedSource[int16]); ok {
@ -94,17 +82,11 @@ func main() {
}
sampleCount /= uint64(i32Source.GetChannels())
} else {
rawFloat32Hasher = md5.New()
f32Source = source.ToFloat32()
log.Printf("Decoding as float32 (generic) %d-bit @ %dHz %d channel(s)", f32Source.GetBitDepth(), f32Source.GetSampleRate(), f32Source.GetChannels())
for b := range f32Source.GetBlocks() {
blockCount++
sampleCount += uint64(len(b))
func() {
defer runtime.KeepAlive(b)
rawFloat32Hasher.Write(unsafe.Slice((*byte)(unsafe.Pointer(&b[0])), len(b)*int(unsafe.Sizeof(float32(0)))))
}()
}
sampleCount /= uint64(f32Source.GetChannels())
}
@ -115,24 +97,22 @@ func main() {
}
log.Printf("Duration %s", ((time.Duration(sampleCount) * time.Second) / time.Duration(source.GetSampleRate())).String())
if h != nil {
h.Wait()
log.Printf("MD5 hash: %s", hex.EncodeToString(h.GetResult()))
if _, ok := source.(audio.TypedSource[float32]); ok {
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_f32le -f md5 -", strconv.Quote(*inputFile))
} else {
switch source.GetBitDepth() {
case 8, 16, 24, 32:
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_s%dle -f md5 -", strconv.Quote(*inputFile), source.GetBitDepth())
default:
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_s32le -f md5 -", strconv.Quote(*inputFile))
}
}
} else if rawFloat32Hasher != nil {
log.Printf("MD5 hash: %s", hex.EncodeToString(rawFloat32Hasher.Sum(nil)))
if _, ok := source.(audio.TypedSource[float32]); ok {
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_f32le -f md5 -", strconv.Quote(*inputFile))
log.Printf("\tNote that you might need to specify a decoder with -c:a before -i to perfectly match the hash on lossy decoders, for example, libopus instead of opus")
hCRC32.Wait()
hSHA256.Wait()
hMD5.Wait()
log.Printf("CRC32 hash: %s", hex.EncodeToString(hCRC32.GetResult()))
log.Printf("SHA256 hash: %s", hex.EncodeToString(hSHA256.GetResult()))
log.Printf("MD5 hash: %s", hex.EncodeToString(hMD5.GetResult()))
if _, ok := source.(audio.TypedSource[float32]); ok {
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_f32le -f md5 -", strconv.Quote(*inputFile))
log.Printf("\tNote that you might need to specify a decoder with -c:a before -i to perfectly match the hash on lossy decoders, for example, libopus instead of opus")
} else {
switch source.GetBitDepth() {
case 8, 16, 24, 32:
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_s%dle -f md5 -", strconv.Quote(*inputFile), source.GetBitDepth())
default:
log.Printf("\tCheck via $ ffmpeg -hide_banner -loglevel error -i %s -vn -c:a pcm_s32le -f md5 -", strconv.Quote(*inputFile))
}
}

View file

@ -222,7 +222,7 @@ void audio_int32_to_bytes(int32_t* restrict data, size_t data_len, int8_t* restr
}
break;
case 32:
memcpy(buffer, data, data_len);
memcpy(buffer, data, sizeof(int32_t) * data_len);
break;
}
}