audio/mp3: Add Decoder struct

This commit is contained in:
Hajime Hoshi 2017-06-18 20:42:59 +09:00
parent 63f1dceb8b
commit e9c6bec432
3 changed files with 111 additions and 31 deletions

View File

@ -18,23 +18,51 @@
package mp3
import (
"bytes"
"io"
"github.com/hajimehoshi/ebiten/audio"
)
type Stream struct {
inner *bytes.Reader
inner *Decoder
data []uint8
pos int64
eof bool
}
// Read is implementation of io.Reader's Read.
func (s *Stream) Read(p []byte) (int, error) {
return s.inner.Read(p)
func (s *Stream) Read(buf []byte) (int, error) {
for int64(len(s.data)) <= s.pos && !s.eof {
buf := make([]uint8, 4096)
n, err := s.inner.Read(buf)
s.data = append(s.data, buf[:n]...)
if err != nil {
if err == io.EOF {
s.eof = true
break
}
return 0, err
}
}
if int64(len(s.data)) <= s.pos && s.eof {
return 0, io.EOF
}
n := copy(buf, s.data[s.pos:])
s.pos += int64(n)
return n, nil
}
// Seek is implementation of io.Seeker's Seek.
func (s *Stream) Seek(offset int64, whence int) (int64, error) {
return s.inner.Seek(offset, whence)
switch whence {
case io.SeekStart:
s.pos = offset
case io.SeekCurrent:
s.pos += offset
case io.SeekEnd:
panic("not implemented")
}
return s.pos, nil
}
// Read is implementation of io.Closer's Close.
@ -44,16 +72,16 @@ func (s *Stream) Close() error {
// Size returns the size of decoded stream in bytes.
func (s *Stream) Size() int64 {
return int64(s.inner.Len())
return int64(s.inner.Length())
}
func Decode(context *audio.Context, src audio.ReadSeekCloser) (*Stream, error) {
var buf bytes.Buffer
if err := decode(src, &buf); err != nil {
d, err := decode(src)
if err != nil {
return nil, err
}
s := &Stream{
inner: bytes.NewReader(buf.Bytes()),
inner: d,
}
// TODO: Resampling
return s, nil

View File

@ -17,7 +17,6 @@
package mp3
import (
"errors"
"io"
)
@ -50,6 +49,17 @@ type source struct {
readerEOF bool
}
func (s *source) rewind() error {
seeker := s.reader.(io.Seeker)
if _, err := seeker.Seek(0, io.SeekStart); err != nil {
return err
}
s.readerCache = nil
s.readerPos = 0
s.readerEOF = false
return nil
}
func (s *source) getByte() (uint8, error) {
for len(s.readerCache) == 0 && !s.readerEOF {
buf := make([]uint8, 4096)
@ -58,9 +68,9 @@ func (s *source) getByte() (uint8, error) {
if err != nil {
if err == io.EOF {
s.readerEOF = true
} else {
return 0, err
break
}
return 0, err
}
}
if len(s.readerCache) == 0 {
@ -87,27 +97,68 @@ func (s *source) getFilepos() int {
return s.readerPos
}
var eof = errors.New("mp3: expected EOF")
type Decoder struct {
source *source
length int64
buf []uint8
frame *frame
eof bool
}
func decode(r io.Reader, w io.Writer) error {
func (d *Decoder) Read(buf []uint8) (int, error) {
for len(d.buf) == 0 && !d.eof {
var err error
d.frame, err = d.source.readNextFrame(d.frame)
if err != nil {
if err == io.EOF {
d.eof = true
}
return 0, err
}
d.buf = append(d.buf, d.frame.decodeL3()...)
}
if d.eof {
return 0, io.EOF
}
n := copy(buf, d.buf)
d.buf = d.buf[n:]
return n, nil
}
// Length returns the total size in bytes.
//
// Length returns -1 when the total size is not available
// e.g. when the given source is not io.Seeker.
func (d *Decoder) Length() int64 {
return d.length
}
func decode(r io.Reader) (*Decoder, error) {
s := &source{
reader: r,
}
var f *frame
for {
var err error
f, err = s.readNextFrame(f)
if err == nil {
out := f.decodeL3()
if _, err := w.Write(out); err != nil {
return err
}
continue
}
if err == eof {
break
}
return err
d := &Decoder{
source: s,
length: -1,
}
return nil
if _, ok := r.(io.Seeker); ok {
l := int64(0)
var f *frame
for {
var err error
f, err = s.readNextFrame(f)
if err != nil {
if err == io.EOF {
break
}
return nil, err
}
l += 576 * 4 * 2
}
if err := s.rewind(); err != nil {
return nil, err
}
d.length = l
}
return d, nil
}

View File

@ -115,7 +115,8 @@ func (s *source) readHeader() (*mpeg1FrameHeader, error) {
if n < 4 {
if err == io.EOF {
if n == 0 {
return nil, eof
// Expected EOF
return nil, io.EOF
}
return nil, fmt.Errorf("mp3: unexpected EOF at readHeader")
}