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 (
"bytes"
"encoding/binary"
"errors"
"fmt"
"io"
"os"
@ -11,15 +11,18 @@ import (
"github.com/pion/opus/pkg/oggreader"
)
func main() {
decoder := opus.NewDecoder()
func convertFloatToByteSlice(i []float32) []byte {
buf := new(bytes.Buffer)
binary.Write(buf, binary.LittleEndian, i)
return buf.Bytes()
}
homeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
func main() {
if len(os.Args) != 3 {
panic("Usage: <in-file> <out-file>")
}
file, err := os.Open(homeDir + "/opus/silk.ogg")
file, err := os.Open(os.Args[1])
if err != nil {
panic(err)
}
@ -29,12 +32,19 @@ func main() {
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 {
pageData, _, err := ogg.ParseNextPage()
segments, _, err := ogg.ParseNextPage()
if errors.Is(err, io.EOF) {
break
} else if bytes.HasPrefix(pageData, []byte("OpusTags")) {
} else if bytes.HasPrefix(segments[0], []byte("OpusTags")) {
continue
}
@ -42,11 +52,12 @@ func main() {
panic(err)
}
bandwidth, isStereo, err := decoder.Decode(pageData, out)
if err != nil {
panic(err)
}
for i := range segments {
if _, _, err = decoder.Decode(segments[i], out); err != nil {
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) {
payload, pageHeader, err := o.ParseNextPage()
segments, pageHeader, err := o.ParseNextPage()
if err != nil {
return nil, err
}
@ -103,27 +103,27 @@ func (o *OggReader) readHeaders() (*OggHeader, error) {
return nil, errBadIDPageType
}
if len(payload) != idPagePayloadLength {
if len(segments[0]) != idPagePayloadLength {
return nil, errBadIDPageLength
}
if s := string(payload[:8]); s != idPageSignature {
if s := string(segments[0][:8]); s != idPageSignature {
return nil, errBadIDPagePayloadSignature
}
header.Version = payload[8]
header.Channels = payload[9]
header.PreSkip = binary.LittleEndian.Uint16(payload[10:12])
header.SampleRate = binary.LittleEndian.Uint32(payload[12:16])
header.OutputGain = binary.LittleEndian.Uint16(payload[16:18])
header.ChannelMap = payload[18]
header.Version = segments[0][8]
header.Channels = segments[0][9]
header.PreSkip = binary.LittleEndian.Uint16(segments[0][10:12])
header.SampleRate = binary.LittleEndian.Uint32(segments[0][12:16])
header.OutputGain = binary.LittleEndian.Uint16(segments[0][16:18])
header.ChannelMap = segments[0][18]
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.
func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) {
func (o *OggReader) ParseNextPage() ([][]byte, *OggPageHeader, error) {
h := make([]byte, pageHeaderLen)
n, err := io.ReadFull(o.stream, h)
@ -149,14 +149,15 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) {
return nil, nil, err
}
payloadSize := 0
for _, s := range sizeBuffer {
payloadSize += int(s)
}
segments := [][]byte{}
payload := make([]byte, payloadSize)
if _, err = io.ReadFull(o.stream, payload); err != nil {
return nil, nil, err
for _, s := range sizeBuffer {
segment := make([]byte, int(s))
if _, err = io.ReadFull(o.stream, segment); err != nil {
return nil, nil, err
}
segments = append(segments, segment)
}
if o.doChecksum {
@ -177,8 +178,11 @@ func (o *OggReader) ParseNextPage() ([]byte, *OggPageHeader, error) {
for _, s := range sizeBuffer {
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 {
@ -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