audio/mp3: Remove global variables 'reader*'

This commit is contained in:
Hajime Hoshi 2017-06-18 18:34:58 +09:00
parent cf05a581a4
commit 63f1dceb8b
4 changed files with 53 additions and 51 deletions

View File

@ -21,13 +21,6 @@ import (
"io" "io"
) )
var (
reader io.Reader
readerCache []uint8
readerPos int
readerEOF bool
)
func (f *frame) decodeL3() []uint8 { func (f *frame) decodeL3() []uint8 {
out := make([]uint8, 576*4*2) out := make([]uint8, 576*4*2)
nch := f.header.numberOfChannels() nch := f.header.numberOfChannels()
@ -50,31 +43,38 @@ func (f *frame) decodeL3() []uint8 {
return out return out
} }
func getByte() (uint8, error) { type source struct {
for len(readerCache) == 0 && !readerEOF { reader io.Reader
readerCache []uint8
readerPos int
readerEOF bool
}
func (s *source) getByte() (uint8, error) {
for len(s.readerCache) == 0 && !s.readerEOF {
buf := make([]uint8, 4096) buf := make([]uint8, 4096)
n, err := reader.Read(buf) n, err := s.reader.Read(buf)
readerCache = append(readerCache, buf[:n]...) s.readerCache = append(s.readerCache, buf[:n]...)
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
readerEOF = true s.readerEOF = true
} else { } else {
return 0, err return 0, err
} }
} }
} }
if len(readerCache) == 0 { if len(s.readerCache) == 0 {
return 0, io.EOF return 0, io.EOF
} }
b := readerCache[0] b := s.readerCache[0]
readerCache = readerCache[1:] s.readerCache = s.readerCache[1:]
readerPos++ s.readerPos++
return b, nil return b, nil
} }
func getBytes(buf []int) (int, error) { func (s *source) getBytes(buf []int) (int, error) {
for i := range buf { for i := range buf {
v, err := getByte() v, err := s.getByte()
buf[i] = int(v) buf[i] = int(v)
if err == io.EOF { if err == io.EOF {
return i, io.EOF return i, io.EOF
@ -83,18 +83,20 @@ func getBytes(buf []int) (int, error) {
return len(buf), nil return len(buf), nil
} }
func getFilepos() int { func (s *source) getFilepos() int {
return readerPos return s.readerPos
} }
var eof = errors.New("mp3: expected EOF") var eof = errors.New("mp3: expected EOF")
func decode(r io.Reader, w io.Writer) error { func decode(r io.Reader, w io.Writer) error {
reader = r s := &source{
reader: r,
}
var f *frame var f *frame
for { for {
var err error var err error
f, err = f.readNextFrame() f, err = s.readNextFrame(f)
if err == nil { if err == nil {
out := f.decodeL3() out := f.decodeL3()
if _, err := w.Write(out); err != nil { if _, err := w.Write(out); err != nil {

View File

@ -26,7 +26,7 @@ var mpeg1ScalefacSizes = [16][2]int{
{2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}, {4, 2}, {4, 3}, {2, 1}, {2, 2}, {2, 3}, {3, 1}, {3, 2}, {3, 3}, {4, 2}, {4, 3},
} }
func readMainL3(prev *mainDataBytes, header *mpeg1FrameHeader, sideInfo *mpeg1SideInfo) (*mpeg1MainData, *mainDataBytes, error) { func (s *source) readMainL3(prev *mainDataBytes, header *mpeg1FrameHeader, sideInfo *mpeg1SideInfo) (*mpeg1MainData, *mainDataBytes, error) {
nch := header.numberOfChannels() nch := header.numberOfChannels()
// Calculate header audio data size // Calculate header audio data size
framesize := header.frameSize() framesize := header.frameSize()
@ -48,7 +48,7 @@ func readMainL3(prev *mainDataBytes, header *mpeg1FrameHeader, sideInfo *mpeg1Si
// two frames. main_data_begin indicates how many bytes from previous // two frames. main_data_begin indicates how many bytes from previous
// frames that should be used. This buffer is later accessed by the // frames that should be used. This buffer is later accessed by the
// getMainBits function in the same way as the side info is. // getMainBits function in the same way as the side info is.
m, err := getMainData(prev, main_data_size, sideInfo.main_data_begin) m, err := s.getMainData(prev, main_data_size, sideInfo.main_data_begin)
if err != nil { if err != nil {
// This could be due to not enough data in reservoir // This could be due to not enough data in reservoir
return nil, nil, err return nil, nil, err
@ -151,7 +151,7 @@ type mainDataBytes struct {
pos int pos int
} }
func getMainData(prev *mainDataBytes, size int, offset int) (*mainDataBytes, error) { func (s *source) getMainData(prev *mainDataBytes, size int, offset int) (*mainDataBytes, error) {
if size > 1500 { if size > 1500 {
return nil, fmt.Errorf("mp3: size = %d", size) return nil, fmt.Errorf("mp3: size = %d", size)
} }
@ -164,7 +164,7 @@ func getMainData(prev *mainDataBytes, size int, offset int) (*mainDataBytes, err
n := 0 n := 0
var err error var err error
for n < size && err == nil { for n < size && err == nil {
nn, err2 := getBytes(buf) nn, err2 := s.getBytes(buf)
n += nn n += nn
err = err2 err = err2
} }
@ -191,7 +191,7 @@ func getMainData(prev *mainDataBytes, size int, offset int) (*mainDataBytes, err
n := 0 n := 0
var err error var err error
for n < size && err == nil { for n < size && err == nil {
nn, err2 := getBytes(buf) nn, err2 := s.getBytes(buf)
n += nn n += nn
err = err2 err = err2
} }

View File

@ -21,12 +21,12 @@ import (
"io" "io"
) )
func readCRC() error { func (s *source) readCRC() error {
buf := make([]int, 2) buf := make([]int, 2)
n := 0 n := 0
var err error var err error
for n < 2 && err == nil { for n < 2 && err == nil {
nn, err2 := getBytes(buf[n:]) nn, err2 := s.getBytes(buf[n:])
n += nn n += nn
err = err2 err = err2
} }
@ -42,14 +42,14 @@ func readCRC() error {
return nil return nil
} }
func (f *frame) readNextFrame() (*frame, error) { func (s *source) readNextFrame(prev *frame) (*frame, error) {
h, err := readHeader() h, err := s.readHeader()
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Get CRC word if present // Get CRC word if present
if h.protection_bit == 0 { if h.protection_bit == 0 {
if err := readCRC(); err != nil { if err := s.readCRC(); err != nil {
return nil, err return nil, err
} }
} }
@ -57,7 +57,7 @@ func (f *frame) readNextFrame() (*frame, error) {
return nil, fmt.Errorf("mp3: only layer3 (want %d; got %d) is supported!", mpeg1Layer3, h.layer) return nil, fmt.Errorf("mp3: only layer3 (want %d; got %d) is supported!", mpeg1Layer3, h.layer)
} }
// Get side info // Get side info
s, err := readSideInfo(h) si, err := s.readSideInfo(h)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -65,17 +65,17 @@ func (f *frame) readNextFrame() (*frame, error) {
// signal to calling function so that decoding isn't done! // signal to calling function so that decoding isn't done!
// Get main data(scalefactors and Huffman coded frequency data) // Get main data(scalefactors and Huffman coded frequency data)
var prevM *mainDataBytes var prevM *mainDataBytes
if f != nil { if prev != nil {
prevM = f.mainDataBytes prevM = prev.mainDataBytes
} }
md, mdb, err := readMainL3(prevM, h, s) md, mdb, err := s.readMainL3(prevM, h, si)
if err != nil { if err != nil {
return nil, err return nil, err
} }
nf := &frame{ nf := &frame{
prev: f, prev: prev,
header: h, header: h,
sideInfo: s, sideInfo: si,
mainData: md, mainData: md,
mainDataBytes: mdb, mainDataBytes: mdb,
} }
@ -102,13 +102,13 @@ func isHeader(header uint32) bool {
return true return true
} }
func readHeader() (*mpeg1FrameHeader, error) { func (s *source) readHeader() (*mpeg1FrameHeader, error) {
// Get the next four bytes from the bitstream // Get the next four bytes from the bitstream
buf := make([]int, 4) buf := make([]int, 4)
n := 0 n := 0
var err error var err error
for n < 4 && err == nil { for n < 4 && err == nil {
nn, err2 := getBytes(buf[n:]) nn, err2 := s.getBytes(buf[n:])
n += nn n += nn
err = err2 err = err2
} }
@ -133,7 +133,7 @@ func readHeader() (*mpeg1FrameHeader, error) {
b2 = b3 b2 = b3
b3 = b4 b3 = b4
// Get one new byte from the bitstream // Get one new byte from the bitstream
b, err := getByte() b, err := s.getByte()
if err != nil { if err != nil {
if err == io.EOF { if err == io.EOF {
return nil, fmt.Errorf("mp3: unexpected EOF at readHeader") return nil, fmt.Errorf("mp3: unexpected EOF at readHeader")
@ -162,23 +162,23 @@ func readHeader() (*mpeg1FrameHeader, error) {
// Check for invalid values and impossible combinations // Check for invalid values and impossible combinations
if h.id != 3 { if h.id != 3 {
return nil, fmt.Errorf("mp3: ID must be 3. Header word is 0x%08x at file pos %d", return nil, fmt.Errorf("mp3: ID must be 3. Header word is 0x%08x at file pos %d",
header, getFilepos()) header, s.getFilepos())
} }
if h.bitrate_index == 0 { if h.bitrate_index == 0 {
return nil, fmt.Errorf("mp3: Free bitrate format NIY! Header word is 0x%08x at file pos %d", return nil, fmt.Errorf("mp3: Free bitrate format NIY! Header word is 0x%08x at file pos %d",
header, getFilepos()) header, s.getFilepos())
} }
if h.bitrate_index == 15 { if h.bitrate_index == 15 {
return nil, fmt.Errorf("mp3: bitrate_index = 15 is invalid! Header word is 0x%08x at file pos %d", return nil, fmt.Errorf("mp3: bitrate_index = 15 is invalid! Header word is 0x%08x at file pos %d",
header, getFilepos()) header, s.getFilepos())
} }
if h.sampling_frequency == 3 { if h.sampling_frequency == 3 {
return nil, fmt.Errorf("mp3: sampling_frequency = 3 is invalid! Header word is 0x%08x at file pos %d", return nil, fmt.Errorf("mp3: sampling_frequency = 3 is invalid! Header word is 0x%08x at file pos %d",
header, getFilepos()) header, s.getFilepos())
} }
if h.layer == mpeg1LayerReserved { if h.layer == mpeg1LayerReserved {
return nil, fmt.Errorf("mp3: layer = %d is invalid! Header word is 0x%08x at file pos %d", return nil, fmt.Errorf("mp3: layer = %d is invalid! Header word is 0x%08x at file pos %d",
mpeg1LayerReserved, header, getFilepos()) mpeg1LayerReserved, header, s.getFilepos())
} }
return h, nil return h, nil
} }

View File

@ -21,7 +21,7 @@ import (
"io" "io"
) )
func readSideInfo(header *mpeg1FrameHeader) (*mpeg1SideInfo, error) { func (src *source) readSideInfo(header *mpeg1FrameHeader) (*mpeg1SideInfo, error) {
nch := header.numberOfChannels() nch := header.numberOfChannels()
// Calculate header audio data size // Calculate header audio data size
framesize := header.frameSize() framesize := header.frameSize()
@ -40,7 +40,7 @@ func readSideInfo(header *mpeg1FrameHeader) (*mpeg1SideInfo, error) {
main_data_size -= 2 main_data_size -= 2
} }
// Read sideinfo from bitstream into buffer used by getSideBits() // Read sideinfo from bitstream into buffer used by getSideBits()
s, err := getSideinfo(sideinfo_size) s, err := src.getSideinfo(sideinfo_size)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -107,12 +107,12 @@ type sideInfoBytes struct {
idx int // Index into the current byte(0-7) idx int // Index into the current byte(0-7)
} }
func getSideinfo(size int) (*sideInfoBytes, error) { func (src *source) getSideinfo(size int) (*sideInfoBytes, error) {
buf := make([]int, size) buf := make([]int, size)
n := 0 n := 0
var err error var err error
for n < size && err == nil { for n < size && err == nil {
nn, err2 := getBytes(buf[n:]) nn, err2 := src.getBytes(buf[n:])
n += nn n += nn
err = err2 err = err2
} }
@ -121,7 +121,7 @@ func getSideinfo(size int) (*sideInfoBytes, error) {
return nil, fmt.Errorf("mp3: unexpected EOF at getSideinfo") return nil, fmt.Errorf("mp3: unexpected EOF at getSideinfo")
} }
return nil, fmt.Errorf("mp3: couldn't read sideinfo %d bytes at pos %d: %v", return nil, fmt.Errorf("mp3: couldn't read sideinfo %d bytes at pos %d: %v",
size, getFilepos(), err) size, src.getFilepos(), err)
} }
s := &sideInfoBytes{ s := &sideInfoBytes{
vec: buf[:n], vec: buf[:n],