DataHoarder
65d4ec2313
Some checks reported errors
continuous-integration/drone/push Build was killed
63 lines
1.3 KiB
Go
63 lines
1.3 KiB
Go
//go:build !disable_format_mp3 && cgo
|
|
|
|
package mp3
|
|
|
|
import (
|
|
"bytes"
|
|
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
|
|
mp3Lib "git.gammaspectra.live/S.O.N.G/minimp3"
|
|
"golang.org/x/exp/slices"
|
|
"io"
|
|
"unsafe"
|
|
)
|
|
|
|
const BlockSize = 1024 * 128
|
|
|
|
type Format struct {
|
|
}
|
|
|
|
func NewFormat() Format {
|
|
return Format{}
|
|
}
|
|
|
|
func (f Format) Name() string {
|
|
return "mp3"
|
|
}
|
|
|
|
func (f Format) DecoderDescription() string {
|
|
return "S.O.N.G/minimp3"
|
|
}
|
|
|
|
func (f Format) Open(r io.ReadSeekCloser) (audio.Source, error) {
|
|
decoder := mp3Lib.NewDecoder(r)
|
|
|
|
_, err := decoder.Read([]byte{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
source := audio.NewSource[int16](16, decoder.SampleRate(), decoder.Channels())
|
|
|
|
go func() {
|
|
defer source.Close()
|
|
samples := make([]int16, BlockSize*decoder.Channels())
|
|
const SizeofInt16 = int(unsafe.Sizeof(int16(0)))
|
|
for {
|
|
n, err := decoder.Read(unsafe.Slice((*byte)(unsafe.Pointer(&samples[0])), len(samples)*SizeofInt16))
|
|
if err != nil {
|
|
return
|
|
}
|
|
n /= SizeofInt16
|
|
|
|
source.IngestInt16(slices.Clone(samples[:n]), 16)
|
|
}
|
|
}()
|
|
|
|
return source, nil
|
|
}
|
|
|
|
func (f Format) Identify(peek []byte, extension string) bool {
|
|
//match ID3 / sync header
|
|
return peek[0] == 0xff && (peek[1]>>5) == 0b111 || (bytes.Compare(peek[:3], []byte{'I', 'D', '3'}) == 0 && extension != "flac") || extension == "mp3"
|
|
}
|