func (d *Decoder) readNextPage(frame *[][]float32, pcm [][][]float32) (n int, err error) { if ret := vorbis.OggSyncPageout(&d.syncState, &d.page); ret < 0 { d.onError(errors.New("vorbis: corrupt or missing data in bitstream")) return 0, nil // non-fatal } else if ret == 0 { // need more data return d.readChunk(d.input) } // page is synced at this point vorbis.OggStreamPagein(&d.streamState, &d.page) for !d.stopRequested() { if ret := vorbis.OggStreamPacketout(&d.streamState, &d.packet); ret < 0 { continue // skip packet } else if ret == 0 { // no packets left on the page, go to the new one return 0, nil } if vorbis.Synthesis(&d.block, &d.packet) == 0 { vorbis.SynthesisBlockin(&d.dspState, &d.block) } samples := vorbis.SynthesisPcmout(&d.dspState, pcm) for ; samples > 0; samples = vorbis.SynthesisPcmout(&d.dspState, pcm) { space := int32(d.samplesPerChannel - len(*frame)) if samples > space { samples = space } for i := 0; i < int(samples); i++ { sample := make([]float32, d.info.Channels) for j := 0; j < int(d.info.Channels); j++ { sample[j] = pcm[0][j][:samples][i] } *frame = append(*frame, sample) } if len(*frame) == d.samplesPerChannel { d.sendFrame(*frame) *frame = make([][]float32, 0, d.samplesPerChannel) } vorbis.SynthesisRead(&d.dspState, samples) } } if d.stopRequested() || vorbis.OggPageEos(&d.page) == 1 { return 0, io.EOF } return 0, nil }
func (d *Decoder) readStreamHeaders(r io.Reader) error { d.readChunk(r) // Read the first page if ret := vorbis.OggSyncPageout(&d.syncState, &d.page); ret != 1 { return errors.New("vorbis: not a valid Ogg bitstream") } // Init the logical bitstream with serial number stored in the page vorbis.OggStreamInit(&d.streamState, vorbis.OggPageSerialno(&d.page)) vorbis.InfoInit(&d.info) vorbis.CommentInit(&d.comment) // Add a complete page to the bitstream if ret := vorbis.OggStreamPagein(&d.streamState, &d.page); ret < 0 { return errors.New("vorbis: the supplied page does not belong this Vorbis stream") } // Get the first packet if ret := vorbis.OggStreamPacketout(&d.streamState, &d.packet); ret != 1 { return errors.New("vorbis: unable to fetch initial Vorbis packet from the first page") } // Finally decode the header packet if ret := vorbis.SynthesisHeaderin(&d.info, &d.comment, &d.packet); ret < 0 { return fmt.Errorf("vorbis: unable to decode the initial Vorbis header: %d", ret) } var headersRead int forPage: for headersRead < 2 { if res := vorbis.OggSyncPageout(&d.syncState, &d.page); res < 0 { // bytes have been skipped, try to sync again continue forPage } else if res == 0 { // go get more data if _, err := d.readChunk(r); err != nil { return errors.New("vorbis: got EOF while reading Vorbis headers") } continue forPage } // page is synced at this point vorbis.OggStreamPagein(&d.streamState, &d.page) for headersRead < 2 { if ret := vorbis.OggStreamPacketout(&d.streamState, &d.packet); ret < 0 { return errors.New("vorbis: data is missing near the secondary Vorbis header") } else if ret == 0 { // no packets left on the page, go get a new one continue forPage } if ret := vorbis.SynthesisHeaderin(&d.info, &d.comment, &d.packet); ret < 0 { return errors.New("vorbis: unable to read the secondary Vorbis header") } headersRead++ } } d.info.Deref() d.comment.Deref() d.comment.UserComments = make([][]byte, d.comment.Comments) d.comment.Deref() return nil }