Upgrade oggreader to be segment aware

This commit is contained in:
Sean DuBois 2022-09-20 22:29:27 -04:00
parent 7b32fb7f78
commit 38e75cb5cf
2 changed files with 51 additions and 36 deletions

View file

@ -2,8 +2,8 @@ package main
import ( import (
"bytes" "bytes"
"encoding/binary"
"errors" "errors"
"fmt"
"io" "io"
"os" "os"
@ -11,15 +11,18 @@ import (
"github.com/pion/opus/pkg/oggreader" "github.com/pion/opus/pkg/oggreader"
) )
func main() { func convertFloatToByteSlice(i []float32) []byte {
decoder := opus.NewDecoder() buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, i)
return buf.Bytes()
}
homeDir, err := os.UserHomeDir() func main() {
if err != nil { if len(os.Args) != 3 {
panic(err) panic("Usage: <in-file> <out-file>")
} }
file, err := os.Open(homeDir + "/opus/silk.ogg") file, err := os.Open(os.Args[1])
if err != nil { if err != nil {
panic(err) panic(err)
} }
@ -29,12 +32,19 @@ func main() {
panic(err) panic(err)
} }
out := make([]float64, 320) out := make([]float32, 320)
f, err := os.Create(os.Args[2])
if err != nil {
panic(err)
}
decoder := opus.NewDecoder()
for { for {
pageData, _, err := ogg.ParseNextPage() segments, _, err := ogg.ParseNextPage()
if errors.Is(err, io.EOF) { if errors.Is(err, io.EOF) {
break break
} else if bytes.HasPrefix(pageData, []byte("OpusTags")) { } else if bytes.HasPrefix(segments[0], []byte("OpusTags")) {
continue continue
} }
@ -42,11 +52,12 @@ func main() {
panic(err) panic(err)
} }
bandwidth, isStereo, err := decoder.Decode(pageData, out) for i := range segments {
if err != nil { if _, _, err = decoder.Decode(segments[i], out); err != nil {
panic(err) panic(err)
} }
fmt.Printf("bandwidth(%s) isStereo(%t) framesCount(%d)\n", bandwidth.String(), isStereo, len(out)) f.Write(floatarrtobytes(out))
}
} }
} }

View file

@ -89,7 +89,7 @@ func newWith(in io.Reader, doChecksum bool) (*OggReader, *OggHeader, error) {
} }
func (o *OggReader) readHeaders() (*OggHeader, error) { func (o *OggReader) readHeaders() (*OggHeader, error) {
payload, pageHeader, err := o.ParseNextPage() segments, pageHeader, err := o.ParseNextPage()
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -103,27 +103,27 @@ func (o *OggReader) readHeaders() (*OggHeader, error) {
return nil, errBadIDPageType return nil, errBadIDPageType
} }
if len(payload) != idPagePayloadLength { if len(segments[0]) != idPagePayloadLength {
return nil, errBadIDPageLength return nil, errBadIDPageLength
} }
if s := string(payload[:8]); s != idPageSignature { if s := string(segments[0][:8]); s != idPageSignature {
return nil, errBadIDPagePayloadSignature return nil, errBadIDPagePayloadSignature
} }
header.Version = payload[8] header.Version = segments[0][8]
header.Channels = payload[9] header.Channels = segments[0][9]
header.PreSkip = binary.LittleEndian.Uint16(payload[10:12]) header.PreSkip = binary.LittleEndian.Uint16(segments[0][10:12])
header.SampleRate = binary.LittleEndian.Uint32(payload[12:16]) header.SampleRate = binary.LittleEndian.Uint32(segments[0][12:16])
header.OutputGain = binary.LittleEndian.Uint16(payload[16:18]) header.OutputGain = binary.LittleEndian.Uint16(segments[0][16:18])
header.ChannelMap = payload[18] header.ChannelMap = segments[0][18]
return header, nil return header, nil
} }
// ParseNextPage reads from stream and returns Ogg page payload, header, // ParseNextPage reads from stream and returns Ogg page segments, header,
// and an error if there is incomplete page data. // and an error if there is incomplete page data.
func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) { func (o *OggReader) ParseNextPage() ([][]byte, *OggPageHeader, error) {
h := make([]byte, pageHeaderLen) h := make([]byte, pageHeaderLen)
n, err := io.ReadFull(o.stream, h) n, err := io.ReadFull(o.stream, h)
@ -149,14 +149,15 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) {
return nil, nil, err return nil, nil, err
} }
payloadSize := 0 segments := [][]byte{}
for _, s := range sizeBuffer {
payloadSize += int(s)
}
payload := make([]byte, payloadSize) for _, s := range sizeBuffer {
if _, err = io.ReadFull(o.stream, payload); err != nil { segment := make([]byte, int(s))
return nil, nil, err if _, err = io.ReadFull(o.stream, segment); err != nil {
return nil, nil, err
}
segments = append(segments, segment)
} }
if o.doChecksum { if o.doChecksum {
@ -177,8 +178,11 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) {
for _, s := range sizeBuffer { for _, s := range sizeBuffer {
updateChecksum(s) updateChecksum(s)
} }
for index := range payload {
updateChecksum(payload[index]) for i := range segments {
for index := range segments[i] {
updateChecksum(segments[i][index])
}
} }
if binary.LittleEndian.Uint32(h[22:22+4]) != checksum { if binary.LittleEndian.Uint32(h[22:22+4]) != checksum {
@ -186,7 +190,7 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) {
} }
} }
return payload, pageHeader, nil return segments, pageHeader, nil
} }
// ResetReader resets the internal stream of OggReader. This is useful // ResetReader resets the internal stream of OggReader. This is useful