Use libflac go bindings, updated audio to work with float32 slice channels instead of single values
This commit is contained in:
parent
67b8ffe931
commit
e222202792
|
@ -96,6 +96,24 @@ func TestHibiki(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
/*
|
||||
file2, err := os.Create("test_w.flac")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer file2.Close()
|
||||
|
||||
resampledStream, err := flacStream.DoResample(1, utilities.PANAKO_SAMPLE_RATE, audio.RESAMPLER_QUALITY_MEDIUM)
|
||||
|
||||
err = flacFormat.Encode(resampledStream, file2)
|
||||
if err != nil {
|
||||
log.Panic(err)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
*/
|
||||
|
||||
store := NewTestPanakoKeyValueStore()
|
||||
strategy := panako.NewStrategy(store, false)
|
||||
|
||||
|
@ -115,27 +133,6 @@ func TestHibiki(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
/*
|
||||
file2, err := os.Create("test_w.raw")
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
defer file2.Close()
|
||||
|
||||
resampledStream, err := radioStream.DoResample(1, utilities.PANAKO_SAMPLE_RATE, audio.RESAMPLER_QUALITY_MEDIUM)
|
||||
|
||||
c := resampledStream.GetAsChannel()
|
||||
for {
|
||||
f, more := <-c
|
||||
if !more {
|
||||
break
|
||||
}
|
||||
binary.Write(file2, binary.LittleEndian, f)
|
||||
}
|
||||
|
||||
os.Exit(0)
|
||||
*/
|
||||
prints := strategy.StreamToFingerprints(radioStream)
|
||||
|
||||
flacTest, err := os.Open("test2.flac")
|
||||
|
|
7
go.mod
7
go.mod
|
@ -4,13 +4,10 @@ go 1.18
|
|||
|
||||
require (
|
||||
git.gammaspectra.live/S.O.N.G/goborator v0.0.0-20220126140813-481f5df7947e
|
||||
github.com/cocoonlife/goflac v0.0.0-20170210142907-50ea06ed5a9d
|
||||
github.com/dh1tw/gosamplerate v0.1.2
|
||||
github.com/gammazero/deque v0.1.0
|
||||
github.com/hajimehoshi/go-mp3 v0.3.2
|
||||
github.com/mewkiz/flac v1.0.7
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/icza/bitio v1.0.0 // indirect
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 // indirect
|
||||
)
|
||||
require github.com/cocoonlife/testify v0.0.0-20160218172820-792cc1faeb64 // indirect
|
||||
|
|
19
go.sum
19
go.sum
|
@ -1,30 +1,19 @@
|
|||
git.gammaspectra.live/S.O.N.G/goborator v0.0.0-20220126140813-481f5df7947e h1:dEzZ+/k/7BizZ+1FFkhtmmu4E2PhuDyq1Q3eelIMZOw=
|
||||
git.gammaspectra.live/S.O.N.G/goborator v0.0.0-20220126140813-481f5df7947e/go.mod h1:ySjuueqe5HUqvf7lWS51Cy5UP2tgJWsezOv8UIm2arA=
|
||||
github.com/d4l3k/messagediff v1.2.2-0.20190829033028-7e0a312ae40b/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||
github.com/cocoonlife/goflac v0.0.0-20170210142907-50ea06ed5a9d h1:utj98F6D5jVv2tHYMsYzM6Z5sG71/W12Ivkd/SnFiN0=
|
||||
github.com/cocoonlife/goflac v0.0.0-20170210142907-50ea06ed5a9d/go.mod h1:swNVb00X8NOH/qeHuqnqiyfecAnWlThLX+NbH8r6yHw=
|
||||
github.com/cocoonlife/testify v0.0.0-20160218172820-792cc1faeb64 h1:LjPYdzoFSAJ5Tr/ElL8kzTJghXgpnOjJVbgd1UvZB1o=
|
||||
github.com/cocoonlife/testify v0.0.0-20160218172820-792cc1faeb64/go.mod h1:LoCAz53rbPcqs8Da2BjB/yDy4gxMtiSQmqnYI/DGH+U=
|
||||
github.com/dh1tw/gosamplerate v0.1.2 h1:oyqtZk67xB9B4l+vIZCZ3F0RYV/z66W58VOah11/ktI=
|
||||
github.com/dh1tw/gosamplerate v0.1.2/go.mod h1:zooTyHpoR7hE+FLfdE3yjLHb2QA2NpMusNfuaZqEACM=
|
||||
github.com/gammazero/deque v0.1.0 h1:f9LnNmq66VDeuAlSAapemq/U7hJ2jpIWa4c09q8Dlik=
|
||||
github.com/gammazero/deque v0.1.0/go.mod h1:KQw7vFau1hHuM8xmI9RbgKFbAsQFWmBpqQ2KenFLk6M=
|
||||
github.com/go-audio/audio v1.0.0/go.mod h1:6uAu0+H2lHkwdGsAY+j2wHPNPpPoeg5AaEFh9FlA+Zs=
|
||||
github.com/go-audio/riff v1.0.0/go.mod h1:l3cQwc85y79NQFCRB7TiPoNiaijp6q8Z0Uv38rVG498=
|
||||
github.com/go-audio/wav v1.0.0/go.mod h1:3yoReyQOsiARkvPl3ERCi8JFjihzG6WhjYpZCf5zAWE=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.2 h1:xSYNE2F3lxtOu9BRjCWHHceg7S91IHfXfXp5+LYQI7s=
|
||||
github.com/hajimehoshi/go-mp3 v0.3.2/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
|
||||
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
|
||||
github.com/icza/bitio v1.0.0 h1:squ/m1SHyFeCA6+6Gyol1AxV9nmPPlJFT8c2vKdj3U8=
|
||||
github.com/icza/bitio v1.0.0/go.mod h1:0jGnlLAx8MKMr9VGnn/4YrvZiprkvBelsVIbA9Jjr9A=
|
||||
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6 h1:8UsGZ2rr2ksmEru6lToqnXgA8Mz1DP11X4zSJ159C3k=
|
||||
github.com/icza/mighty v0.0.0-20180919140131-cfd07d671de6/go.mod h1:xQig96I1VNBDIWGCdTt54nHt6EeI639SmHycLYL7FkA=
|
||||
github.com/mewkiz/flac v1.0.7 h1:uIXEjnuXqdRaZttmSFM5v5Ukp4U6orrZsnYGGR3yow8=
|
||||
github.com/mewkiz/flac v1.0.7/go.mod h1:yU74UH277dBUpqxPouHSQIar3G1X/QIclVbFahSd1pU=
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2 h1:EyTNMdePWaoWsRSGQnXiSoQu0r6RS1eA557AwJhlzHU=
|
||||
github.com/mewkiz/pkg v0.0.0-20190919212034-518ade7978e2/go.mod h1:3E2FUC/qYUfM8+r9zAwpeHJzqRVVMIYnpzD/clwWxyA=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/image v0.0.0-20190220214146-31aff87c08e9/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190429190828-d89cdac9e872/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
|
|
@ -50,13 +50,6 @@ func (s *Strategy) StoreStream(resourceId int64, stream *audio.Stream) float64 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (s *Strategy) StreamSliceToFingerprints(stream *audio.Stream, startTimeOffset, duration float64) []*Fingerprint {
|
||||
stream.AdvanceSeconds(startTimeOffset) //This can err but it's fine
|
||||
stream.SetMaxDuration(duration)
|
||||
|
||||
return s.StreamToFingerprints(stream)
|
||||
}
|
||||
|
||||
func (s *Strategy) StreamToFingerprints(stream *audio.Stream) []*Fingerprint {
|
||||
resample, err := stream.DoResample(1, utilities.PANAKO_SAMPLE_RATE, audio.RESAMPLER_QUALITY_MEDIUM)
|
||||
if err != nil {
|
||||
|
|
|
@ -3,7 +3,8 @@ package flac
|
|||
import (
|
||||
"bytes"
|
||||
"git.gammaspectra.live/S.O.N.G/Hibiki/utilities/audio"
|
||||
flacLib "github.com/mewkiz/flac"
|
||||
"git.gammaspectra.live/S.O.N.G/Hibiki/utilities/audio/format"
|
||||
libflac "github.com/cocoonlife/goflac"
|
||||
"io"
|
||||
)
|
||||
|
||||
|
@ -14,97 +15,79 @@ func NewFormat() Format {
|
|||
return Format{}
|
||||
}
|
||||
|
||||
func (f Format) Open(r io.ReadSeeker) (*audio.Stream, error) {
|
||||
stream, err := flacLib.Parse(r)
|
||||
func (f Format) Open(r io.ReadSeekCloser) (*audio.Stream, error) {
|
||||
decoder, err := libflac.NewDecoderReader(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newChannel := make(chan float32)
|
||||
newChannel := make(chan []float32)
|
||||
|
||||
go func() {
|
||||
defer stream.Close()
|
||||
defer decoder.Close()
|
||||
defer close(newChannel)
|
||||
|
||||
frameNumber := 0
|
||||
|
||||
for {
|
||||
currentFrame, err := stream.ParseNext()
|
||||
currentFrame, err := decoder.ReadFrame()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for sample := 0; sample < currentFrame.Subframes[0].NSamples; sample++ {
|
||||
//Interleave samples
|
||||
for _, subFrame := range currentFrame.Subframes {
|
||||
//convert to f32 samples
|
||||
newChannel <- float32(subFrame.Samples[sample]) / float32((int64(1)<<(currentFrame.BitsPerSample-1))-1)
|
||||
}
|
||||
//log.Printf("frame %d %d %d %d\n", frameNumber, currentFrame.Channels, currentFrame.Depth, currentFrame.Rate)
|
||||
|
||||
bitDepth := decoder.Depth
|
||||
|
||||
if currentFrame.Depth != 0 {
|
||||
bitDepth = currentFrame.Depth
|
||||
}
|
||||
|
||||
buf := make([]float32, len(currentFrame.Buffer))
|
||||
|
||||
for i, sample := range currentFrame.Buffer {
|
||||
//convert to f32 samples
|
||||
buf[i] = float32(sample) / float32((int64(1)<<(bitDepth-1))-1)
|
||||
}
|
||||
|
||||
newChannel <- buf
|
||||
|
||||
frameNumber++
|
||||
}
|
||||
}()
|
||||
|
||||
return audio.NewStream(newChannel, int(stream.Info.NChannels), float64(stream.Info.SampleRate)), nil
|
||||
return audio.NewStream(newChannel, decoder.Channels, float64(decoder.Rate)), nil
|
||||
}
|
||||
|
||||
/*
|
||||
func (f Format) Encode(stream *audio.Stream, writer io.Writer) error {
|
||||
bitsPerSample := uint8(16)
|
||||
func (f Format) Encode(stream *audio.Stream, writer format.WriteSeekCloser) error {
|
||||
bitsPerSample := 16
|
||||
|
||||
encoder, err := flacLib.NewEncoder(writer, &meta.StreamInfo{
|
||||
SampleRate: uint32(stream.GetSampleRate()),
|
||||
NChannels: uint8(stream.GetChannels()),
|
||||
BitsPerSample: bitsPerSample,
|
||||
BlockSizeMin: 16,
|
||||
BlockSizeMax: 65535,
|
||||
FrameSizeMin: 0,
|
||||
FrameSizeMax: 0,
|
||||
})
|
||||
encoder, err := libflac.NewEncoderWriter(writer, stream.GetChannels(), bitsPerSample, int(stream.GetSampleRate()))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
defer encoder.Close()
|
||||
|
||||
for {
|
||||
block, more := stream.GetBlock()
|
||||
|
||||
if stream.GetChannels() > 1 {
|
||||
|
||||
} else {
|
||||
samples := make([]int32, len(block))
|
||||
for i, v := range block {
|
||||
samples[i] = int32(v * float32((int64(1)<<(bitsPerSample-1))-1))
|
||||
}
|
||||
|
||||
err = encoder.WriteFrame(&frame.Frame{
|
||||
Header: frame.Header{
|
||||
BlockSize: uint16(len(samples)),
|
||||
SampleRate: 0,
|
||||
BitsPerSample: bitsPerSample,
|
||||
HasFixedBlockSize: true,
|
||||
},
|
||||
Subframes: []*frame.Subframe{
|
||||
{
|
||||
SubHeader: frame.SubHeader{
|
||||
Pred: frame.PredVerbatim,
|
||||
},
|
||||
Samples: samples,
|
||||
NSamples: len(samples),
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for block := range stream.GetAsBlockChannel() {
|
||||
samples := make([]int32, len(block))
|
||||
for i, v := range block {
|
||||
samples[i] = int32(v * float32((int64(1)<<(bitsPerSample-1))-1))
|
||||
}
|
||||
err = encoder.WriteFrame(libflac.Frame{
|
||||
Rate: int(stream.GetSampleRate()),
|
||||
Channels: stream.GetChannels(),
|
||||
Depth: bitsPerSample,
|
||||
Buffer: samples,
|
||||
})
|
||||
|
||||
if !more {
|
||||
break
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}*/
|
||||
}
|
||||
|
||||
func (f Format) Identify(peek []byte, extension string) bool {
|
||||
return bytes.Compare(peek[:4], []byte{'f', 'L', 'a', 'C'}) == 0 && extension == "flac"
|
||||
|
|
|
@ -10,10 +10,16 @@ type Format interface {
|
|||
Identify(peek []byte, extension string) bool
|
||||
|
||||
// Open Opens a stream and decodes it into an audio.Stream
|
||||
Open(r io.ReadSeeker) (audio.Stream, error)
|
||||
Open(r io.ReadSeekCloser) (audio.Stream, error)
|
||||
}
|
||||
|
||||
type WriteSeekCloser interface {
|
||||
io.Writer
|
||||
io.Closer
|
||||
io.Seeker
|
||||
}
|
||||
|
||||
type Encoder interface {
|
||||
// Encode Receives a stream and encodes it into an io.Reader
|
||||
Encode(stream *audio.Stream) (io.Reader, error)
|
||||
// Encode Receives a stream and encodes it into a writer
|
||||
Encode(stream *audio.Stream, writer WriteSeekCloser) error
|
||||
}
|
||||
|
|
|
@ -15,24 +15,32 @@ func NewFormat() Format {
|
|||
return Format{}
|
||||
}
|
||||
|
||||
func (f Format) Open(r io.ReadSeeker) (*audio.Stream, error) {
|
||||
func (f Format) Open(r io.ReadSeekCloser) (*audio.Stream, error) {
|
||||
decoder, err := mp3Lib.NewDecoder(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
newChannel := make(chan float32)
|
||||
newChannel := make(chan []float32)
|
||||
|
||||
go func() {
|
||||
defer close(newChannel)
|
||||
for {
|
||||
sample := make([]float32, 2)
|
||||
|
||||
var i int16
|
||||
err = binary.Read(decoder, binary.LittleEndian, &i)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sample[0] = float32(i) / float32(math.MaxInt16)
|
||||
err = binary.Read(decoder, binary.LittleEndian, &i)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
sample[1] = float32(i) / float32(math.MaxInt16)
|
||||
|
||||
newChannel <- float32(i) / float32(math.MaxInt16)
|
||||
newChannel <- sample
|
||||
}
|
||||
}()
|
||||
|
||||
|
|
|
@ -9,7 +9,6 @@ type Resampler struct {
|
|||
converter gosamplerate.Src
|
||||
ratio float64
|
||||
channels int
|
||||
buffer []float32
|
||||
}
|
||||
|
||||
const (
|
||||
|
@ -31,34 +30,12 @@ func NewResampler(from, to float64, channels, quality int) (Resampler, error) {
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (r *Resampler) GetBlock() []float32 {
|
||||
if len(r.buffer) > utilities.PANAKO_AUDIO_BLOCK_SIZE*r.channels {
|
||||
s := r.buffer[0 : utilities.PANAKO_AUDIO_BLOCK_SIZE*r.channels]
|
||||
r.buffer = r.buffer[utilities.PANAKO_AUDIO_BLOCK_SIZE*r.channels:]
|
||||
return s
|
||||
} else {
|
||||
s := r.buffer
|
||||
r.buffer = r.buffer[:0]
|
||||
return s
|
||||
}
|
||||
func (r *Resampler) Process(block []float32) ([]float32, error) {
|
||||
return r.converter.Process(block, r.ratio, false)
|
||||
}
|
||||
|
||||
func (r *Resampler) Process(block []float32) error {
|
||||
b, err := r.converter.Process(block, r.ratio, false)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.buffer = append(r.buffer, b...)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *Resampler) Finish() error {
|
||||
b, err := r.converter.Process([]float32{}, r.ratio, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
r.buffer = append(r.buffer, b...)
|
||||
return nil
|
||||
func (r *Resampler) Finish() ([]float32, error) {
|
||||
return r.converter.Process([]float32{}, r.ratio, true)
|
||||
}
|
||||
|
||||
func (r *Resampler) Reset() {
|
||||
|
|
|
@ -6,14 +6,13 @@ import (
|
|||
)
|
||||
|
||||
type Stream struct {
|
||||
source chan float32
|
||||
channels int
|
||||
sampleRate float64
|
||||
samplesRead int
|
||||
stopAtSample int
|
||||
source chan []float32
|
||||
channels int
|
||||
sampleRate float64
|
||||
buffer []float32
|
||||
}
|
||||
|
||||
func NewStream(source chan float32, channels int, sampleRate float64) *Stream {
|
||||
func NewStream(source chan []float32, channels int, sampleRate float64) *Stream {
|
||||
return &Stream{
|
||||
source: source,
|
||||
channels: channels,
|
||||
|
@ -46,45 +45,31 @@ func (s *Stream) GetAsChannel() chan float32 {
|
|||
|
||||
func (s *Stream) GetAsBlockChannel() chan []float32 {
|
||||
newChannel := make(chan []float32)
|
||||
|
||||
go func() {
|
||||
defer close(newChannel)
|
||||
for {
|
||||
v, more := s.GetBlock()
|
||||
if !more {
|
||||
return
|
||||
for buf := range s.source {
|
||||
s.buffer = append(s.buffer, buf...)
|
||||
for len(s.buffer) >= utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels {
|
||||
newChannel <- s.buffer[0 : utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels]
|
||||
s.buffer = s.buffer[utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels:]
|
||||
}
|
||||
newChannel <- v
|
||||
}
|
||||
}()
|
||||
return newChannel
|
||||
}
|
||||
|
||||
func (s *Stream) Get() (float32, bool) {
|
||||
if s.stopAtSample != 0 && s.samplesRead >= s.stopAtSample {
|
||||
return 0, false
|
||||
}
|
||||
v, more := <-s.source
|
||||
if more {
|
||||
s.samplesRead++
|
||||
}
|
||||
return v, more
|
||||
}
|
||||
|
||||
func (s *Stream) GetBlock() ([]float32, bool) {
|
||||
buf := make([]float32, 0, utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels)
|
||||
|
||||
for {
|
||||
f, more := s.Get()
|
||||
if !more { //EOF
|
||||
return buf, more
|
||||
}
|
||||
|
||||
buf = append(buf, f)
|
||||
|
||||
if len(buf) == utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels {
|
||||
return buf, true
|
||||
var more bool
|
||||
if len(s.buffer) == 0 {
|
||||
s.buffer, more = <-s.source
|
||||
if !more {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
f := s.buffer[0]
|
||||
s.buffer = s.buffer[1:]
|
||||
return f, true
|
||||
}
|
||||
|
||||
func (s *Stream) AdvanceSeconds(seconds float64) bool {
|
||||
|
@ -98,10 +83,6 @@ func (s *Stream) AdvanceSeconds(seconds float64) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (s *Stream) SetMaxDuration(seconds float64) {
|
||||
s.stopAtSample = s.secondsIndex(seconds)
|
||||
}
|
||||
|
||||
func (s *Stream) secondsIndex(seconds float64) int {
|
||||
return int(seconds * s.sampleRate)
|
||||
}
|
||||
|
@ -120,13 +101,13 @@ func (s *Stream) DoResample(channels int, sampleRate float64, quality int) (*Str
|
|||
return nil, err
|
||||
}
|
||||
|
||||
newChannel := make(chan float32)
|
||||
newChannel := make(chan []float32)
|
||||
|
||||
go func() {
|
||||
defer rs.Delete()
|
||||
defer close(newChannel)
|
||||
|
||||
handleTransform := func(buf []float32, end bool) error {
|
||||
handleTransform := func(buf []float32) error {
|
||||
if channels != s.channels && channels == 1 {
|
||||
newBuf := make([]float32, 0, utilities.PANAKO_AUDIO_BLOCK_SIZE)
|
||||
for i := 0; i < len(buf)/s.channels && i < utilities.PANAKO_AUDIO_BLOCK_SIZE; i++ {
|
||||
|
@ -138,59 +119,41 @@ func (s *Stream) DoResample(channels int, sampleRate float64, quality int) (*Str
|
|||
}
|
||||
|
||||
if len(newBuf) > 0 {
|
||||
err = rs.Process(newBuf)
|
||||
b, err := rs.Process(newBuf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newChannel <- b
|
||||
}
|
||||
} else {
|
||||
err = rs.Process(buf)
|
||||
b, err := rs.Process(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newChannel <- b
|
||||
}
|
||||
|
||||
if end {
|
||||
err = rs.Finish()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
for {
|
||||
b := rs.GetBlock()
|
||||
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, d := range b {
|
||||
newChannel <- d
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var buf []float32
|
||||
var more bool
|
||||
var buffer []float32
|
||||
|
||||
for {
|
||||
buf, more = s.GetBlock()
|
||||
if !more { //EOF
|
||||
break
|
||||
}
|
||||
|
||||
if len(buf) == utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels {
|
||||
err = handleTransform(buf, false)
|
||||
for buf := range s.GetAsBlockChannel() {
|
||||
buffer = append(buffer, buf...)
|
||||
for len(buffer) >= utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels {
|
||||
err = handleTransform(buffer[0 : utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels])
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
buffer = buffer[utilities.PANAKO_AUDIO_BLOCK_SIZE*s.channels:]
|
||||
}
|
||||
}
|
||||
|
||||
err = handleTransform(buf, true)
|
||||
b, err := rs.Finish()
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
newChannel <- b
|
||||
}()
|
||||
|
||||
return NewStream(newChannel, channels, sampleRate), nil
|
||||
|
|
Loading…
Reference in a new issue