Files
am-downloader/sniff.go
T

59 lines
1.3 KiB
Go

package main
import (
"encoding/binary"
"errors"
"io"
"os"
)
func detectAudioFormat(path string) (string, error) {
f, err := os.Open(path)
if err != nil {
return "", err
}
defer f.Close()
b := make([]byte, 64*1024)
n, err := f.Read(b)
if err != nil && err != io.EOF {
return "", err
}
b = b[:n]
if len(b) >= 4 && string(b[:4]) == "fLaC" {
return "flac", nil
}
if len(b) >= 12 && string(b[:4]) == "RIFF" && string(b[8:12]) == "WAVE" {
return "wav", nil
}
if len(b) >= 12 && string(b[:4]) == "FORM" && (string(b[8:12]) == "AIFF" || string(b[8:12]) == "AIFC") {
return "aiff", nil
}
if len(b) >= 4 && string(b[:4]) == "OggS" {
return "ogg", nil
}
if len(b) >= 12 && string(b[4:8]) == "ftyp" {
return "m4a", nil
}
start := 0
if len(b) >= 10 && string(b[:3]) == "ID3" {
size := int(b[6]&0x7f)<<21 | int(b[7]&0x7f)<<14 | int(b[8]&0x7f)<<7 | int(b[9]&0x7f)
start = 10 + size
if start > len(b) {
start = 10
}
}
for i := start; i+4 <= len(b) && i < start+4096; i++ {
if b[i] == 0xff && b[i+1]&0xe0 == 0xe0 {
h := binary.BigEndian.Uint32(b[i : i+4])
layer := (h >> 17) & 3
if layer == 1 {
return "mp3", nil
}
if b[i+1]&0x06 == 0x06 {
return "aac", nil
}
}
}
return "", errors.New("unknown audio format")
}