Kirika/audio/format/vorbis/vorbis.go

118 lines
2.3 KiB
Go
Raw Normal View History

2022-07-28 13:01:20 +00:00
//go:build !disable_format_vorbis && !disable_codec_libvorbis && cgo
2022-03-05 10:08:51 +00:00
package vorbis
import (
"bytes"
2022-07-28 13:01:20 +00:00
"fmt"
2022-03-05 10:08:51 +00:00
"git.gammaspectra.live/S.O.N.G/Kirika/audio"
"git.gammaspectra.live/S.O.N.G/Kirika/audio/format"
2022-07-28 13:01:20 +00:00
libvorbis "git.gammaspectra.live/S.O.N.G/go-vorbis"
2022-03-05 10:08:51 +00:00
"io"
)
type Format struct {
}
func NewFormat() Format {
return Format{}
}
func (f Format) Name() string {
return "vorbis"
}
func (f Format) DecoderDescription() string {
2022-07-28 13:01:20 +00:00
return fmt.Sprintf("%s (S.O.N.G/go-vorbis)", libvorbis.Version())
}
func (f Format) EncoderDescription() string {
return f.DecoderDescription()
}
2022-03-05 10:08:51 +00:00
func (f Format) Open(r io.ReadSeekCloser) (audio.Source, error) {
2022-07-28 13:01:20 +00:00
reader, err := libvorbis.NewSeekCloserDecoder(r)
2022-03-05 10:08:51 +00:00
if err != nil {
return nil, err
2022-03-05 10:08:51 +00:00
}
2022-07-28 13:01:20 +00:00
info := reader.Information()
source := audio.NewSource[float32](16, int(info.Rate), info.Channels)
2022-03-05 10:08:51 +00:00
go func() {
defer source.Close()
2022-07-28 13:01:20 +00:00
defer reader.Close()
2022-03-05 10:08:51 +00:00
for {
2022-07-28 13:01:20 +00:00
buf, channelCount, err := reader.ReadFloat()
2022-03-05 10:08:51 +00:00
if err != nil {
return
}
2022-07-28 13:01:20 +00:00
if info.Channels != channelCount {
//Channel count changed!
return
2022-03-05 10:08:51 +00:00
}
2022-07-28 13:01:20 +00:00
source.IngestFloat32(buf)
2022-03-05 10:08:51 +00:00
}
}()
return source, nil
2022-03-05 10:08:51 +00:00
}
2022-07-28 13:01:20 +00:00
func (f Format) Encode(source audio.Source, writer io.WriteCloser, options map[string]interface{}) error {
var bitrate = 128
if options != nil {
var val interface{}
var ok bool
var intVal int
var int64Val int64
var strVal string
if val, ok = options["bitrate"]; ok {
if strVal, ok = val.(string); ok {
switch strVal {
case "256k":
bitrate = 256
case "192k":
bitrate = 192
case "128k":
bitrate = 128
default:
return fmt.Errorf("unknown setting bitrate=%s", strVal)
}
} else if intVal, ok = val.(int); ok {
bitrate = intVal
} else if int64Val, ok = val.(int64); ok {
bitrate = int(int64Val)
}
}
}
encoder, err := libvorbis.NewEncoderCBR(writer, source.GetChannels(), source.GetSampleRate(), -1, int64(bitrate*1000), -1)
if err != nil {
return err
}
defer encoder.Close()
for block := range source.ToFloat32().GetBlocks() {
err = encoder.WriteFloat(block)
if err != nil {
return err
}
}
encoder.Flush()
return nil
}
func (f Format) Identify(peek [format.IdentifyPeekBytes]byte, extension string) bool {
2022-03-05 10:08:51 +00:00
return bytes.Compare(peek[:4], []byte{'O', 'g', 'g', 'S'}) == 0 || extension == "vorbis" || extension == "ogg"
}