Kirika/audio/format/mp3/mp3.go
2022-02-22 10:35:08 +01:00

59 lines
1.3 KiB
Go

package mp3
/*
#cgo CFLAGS: -I"${SRCDIR}/../../../cgo" -march=native -Ofast -std=c99
#include "audio.h"
*/
import "C"
import (
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
mp3Lib "github.com/kvark128/minimp3"
"io"
"unsafe"
)
type Format struct {
}
func NewFormat() Format {
return Format{}
}
func (f Format) Open(r io.ReadSeekCloser, blockSize int) (*audio.Stream, error) {
decoder := mp3Lib.NewDecoder(r)
_, err := decoder.Read([]byte{})
if err != nil {
return nil, err
}
newChannel := make(chan []float32)
go func() {
defer close(newChannel)
samples := make([]int16, blockSize*2)
const SizeofInt16 = int(unsafe.Sizeof(int16(0)))
byteSlice := unsafe.Slice((*byte)(unsafe.Pointer(&samples[0])), len(samples)*SizeofInt16)
for {
n, err := decoder.Read(byteSlice)
if err != nil {
return
}
n /= SizeofInt16
buf := make([]float32, n)
//convert 16-bit to f32 samples
C.audio_int16_to_float32((*C.int16_t)(&samples[0]), C.size_t(n), (*C.float)(&buf[0]), C.int(16))
newChannel <- buf
}
}()
return audio.NewStream(newChannel, decoder.Channels(), float64(decoder.SampleRate()), blockSize), nil
}
func (f Format) Identify(peek []byte, extension string) bool {
return /*bytes.Compare(peek[:4], []byte{'f', 'L', 'a', 'C'}) == 0 || */ extension == "mp3"
}