Kirika/audio/format/mp3/mp3.go
DataHoarder afecfbb4a7
All checks were successful
continuous-integration/drone/push Build is passing
Use float32 native output on mp3 decoders
2022-12-01 10:32:27 +01:00

60 lines
1.2 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"
)
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([]float32{})
if err != nil {
return nil, err
}
source := audio.NewSource[float32](16, decoder.SampleRate(), decoder.Channels())
go func() {
defer source.Close()
samples := make([]float32, BlockSize*decoder.Channels())
for {
n, err := decoder.Read(samples)
if err != nil {
return
}
source.IngestFloat32(slices.Clone(samples[:n]))
}
}()
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"
}