48 lines
1.4 KiB
Go
48 lines
1.4 KiB
Go
package media
|
|
|
|
import "encoding/binary"
|
|
|
|
func validateAudio(codec string, declaredDurationMS int, prefix []byte) string {
|
|
if codec != "wav_pcm_s16le" {
|
|
return "CODEC_VALIDATION_UNAVAILABLE"
|
|
}
|
|
if len(prefix) < 44 || string(prefix[:4]) != "RIFF" || string(prefix[8:12]) != "WAVE" {
|
|
return "INVALID_AUDIO_CONTAINER"
|
|
}
|
|
var byteRate, dataSize uint32
|
|
var audioFormat, bitsPerSample uint16
|
|
for offset := 12; offset+8 <= len(prefix); {
|
|
chunkID := string(prefix[offset : offset+4])
|
|
chunkSize := int(binary.LittleEndian.Uint32(prefix[offset+4 : offset+8]))
|
|
dataStart := offset + 8
|
|
if chunkID == "data" {
|
|
dataSize = uint32(chunkSize)
|
|
break
|
|
}
|
|
if chunkSize < 0 || dataStart+chunkSize > len(prefix) {
|
|
break
|
|
}
|
|
switch chunkID {
|
|
case "fmt ":
|
|
if chunkSize < 16 {
|
|
return "INVALID_AUDIO_CONTAINER"
|
|
}
|
|
audioFormat = binary.LittleEndian.Uint16(prefix[dataStart : dataStart+2])
|
|
byteRate = binary.LittleEndian.Uint32(prefix[dataStart+8 : dataStart+12])
|
|
bitsPerSample = binary.LittleEndian.Uint16(prefix[dataStart+14 : dataStart+16])
|
|
}
|
|
offset = dataStart + chunkSize
|
|
if offset%2 != 0 {
|
|
offset++
|
|
}
|
|
}
|
|
if audioFormat != 1 || bitsPerSample != 16 || byteRate == 0 || dataSize == 0 {
|
|
return "UNSUPPORTED_AUDIO_ENCODING"
|
|
}
|
|
actualDurationMS := int((uint64(dataSize) * 1000) / uint64(byteRate))
|
|
if actualDurationMS != declaredDurationMS {
|
|
return "DURATION_MISMATCH"
|
|
}
|
|
return ""
|
|
}
|