func (t huffmanTable) Lookup(r *ogg.BitReader) uint32 { i := uint32(0) for i&0x80000000 == 0 { i = t[i*2+r.Read1()] } return i & 0x7FFFFFFF }
func (f *floor1) Decode(r *ogg.BitReader, books []codebook, n uint32) []uint32 { if !r.ReadBool() { return nil } range_ := [4]uint32{256, 128, 86, 64}[f.multiplier-1] y := make([]uint32, 0, len(f.xList)) y = append(y, r.Read32(ilog(int(range_)-1)), r.Read32(ilog(int(range_)-1))) for _, classIndex := range f.partitionClassList { class := f.classes[classIndex] cdim := class.dimension cbits := class.subclass csub := (uint32(1) << cbits) - 1 cval := uint32(0) if cbits > 0 { cval = books[class.masterbook].DecodeScalar(r) } for j := 0; j < int(cdim); j++ { book := class.subclassBooks[cval&csub] cval >>= cbits if book != 0xFF { y = append(y, books[book].DecodeScalar(r)) } else { y = append(y, 0) } } } return y }
func (f *floor0) Decode(r *ogg.BitReader, books []codebook, n uint32) []float32 { amplitude := r.Read32(uint(f.amplitudeBits)) if amplitude > 0 { bookNumber := r.Read8(ilog(len(f.bookList))) coefficients := make([]float32, f.order) i := 0 readCoefficients: for { tempVector := books[f.bookList[bookNumber]].DecodeVector(r) for _, c := range tempVector { coefficients[i] = c i++ if i >= len(coefficients) { break readCoefficients } } } } //TODO return nil }
func (i *identification) ReadFrom(r *ogg.BitReader) error { if r.Read8(8) != headerTypeIdentification { return ogg.ErrCorruptStream } if r.Read64(48) != pattern { return ogg.ErrCorruptStream } if r.Read32(32) != 0 { return ogg.ErrCorruptStream } i.audioChannels = r.Read8(8) i.audioSampleRate = r.Read32(32) i.bitrateMaximum = r.Read32(32) i.bitrateNominal = r.Read32(32) i.bitrateMinimum = r.Read32(32) i.blocksize0 = uint16(1) << r.Read8(4) i.blocksize1 = uint16(1) << r.Read8(4) if !r.ReadBool() { return ogg.ErrCorruptStream } return nil }
func (s *setup) ReadFrom(r *ogg.BitReader) error { if r.Read8(8) != headerTypeSetup { return ogg.ErrCorruptStream } if r.Read64(48) != pattern { return ogg.ErrCorruptStream } // CODEBOOKS s.codebooks = make([]codebook, r.Read16(8)+1) for i := range s.codebooks { err := s.codebooks[i].ReadFrom(r) if err != nil { return err } } // TIME DOMAIN TRANSFORMS transformCount := r.Read8(6) + 1 for i := 0; i < int(transformCount); i++ { if r.Read16(16) != 0 { return ogg.ErrCorruptStream } } // FLOORS s.floors = make([]floor, r.Read8(6)+1) for i := range s.floors { var err error switch r.Read16(16) { case 0: // TODO // floor0 is not supported right now, also I haven't found any files that use it. /*var f floor0 err = f.ReadFrom(r) s.floors[i] = &f*/ case 1: f := new(floor1) err = f.ReadFrom(r) s.floors[i] = f default: err = ogg.ErrCorruptStream } if err != nil { return err } } // RESIDUES s.residues = make([]residue, r.Read8(6)+1) for i := range s.residues { err := s.residues[i].ReadFrom(r) if err != nil { return err } } // MAPPINGS s.mappings = make([]mapping, r.Read8(6)+1) for i := range s.mappings { m := &s.mappings[i] if r.Read16(16) != 0 { return ogg.ErrCorruptStream } if r.ReadBool() { m.submaps = make([]mappingSubmap, r.Read8(4)+1) } else { m.submaps = make([]mappingSubmap, 1) } if r.ReadBool() { m.couplingSteps = r.Read16(8) + 1 m.magnitude = make([]uint8, m.couplingSteps) m.angle = make([]uint8, m.couplingSteps) for i := range m.magnitude { m.magnitude[i] = r.Read8(ilog(s.channels - 1)) m.angle[i] = r.Read8(ilog(s.channels - 1)) } } if r.Read8(2) != 0 { return ogg.ErrCorruptStream } m.mux = make([]uint8, s.channels) if len(m.submaps) > 1 { for i := range m.mux { m.mux[i] = r.Read8(4) } } for i := range m.submaps { r.Read8(8) m.submaps[i].floor = r.Read8(8) m.submaps[i].residue = r.Read8(8) } } // MODES s.modes = make([]mode, r.Read8(6)+1) for i := range s.modes { m := &s.modes[i] m.blockflag = r.Read8(1) if r.Read16(16) != 0 { return ogg.ErrCorruptStream } if r.Read16(16) != 0 { return ogg.ErrCorruptStream } m.mapping = r.Read8(8) } if !r.ReadBool() { return ogg.ErrCorruptStream } return nil }
func (c *codebook) ReadFrom(r *ogg.BitReader) error { if r.Read32(24) != codebookPattern { return ogg.ErrCorruptStream } c.dimensions = r.Read32(16) numEntries := r.Read32(24) c.entries = make(huffmanTable, numEntries*2-2) ordered := r.ReadBool() if !ordered { sparse := r.ReadBool() for i := uint32(0); i < numEntries; i++ { if !sparse || r.ReadBool() { c.entries.Put(i, r.Read8(5)+1) } } } else { currentEntry := uint32(0) currentLength := r.Read8(5) + 1 for currentEntry < numEntries { num := r.Read32(ilog(int(numEntries - currentEntry))) for i := currentEntry; i < currentEntry+num; i++ { c.entries.Put(i, currentLength) } currentEntry += num currentLength++ } } lookupType := r.Read8(4) if lookupType == 0 { return nil } if lookupType > 2 { return ogg.ErrCorruptStream } minimumValue := float32Unpack(r.Read32(32)) deltaValue := float32Unpack(r.Read32(32)) valueBits := r.Read8(4) + 1 sequenceP := r.ReadBool() var multiplicands []uint32 if lookupType == 1 { multiplicands = make([]uint32, lookup1Values(int(numEntries), c.dimensions)) } else { multiplicands = make([]uint32, int(numEntries)*int(c.dimensions)) } for i := range multiplicands { multiplicands[i] = r.Read32(uint(valueBits)) } c.values = make([]float32, numEntries*c.dimensions) for entry := 0; entry < int(numEntries); entry++ { index := entry * int(c.dimensions) if lookupType == 1 { last := float32(0) indexDivisor := 1 for i := 0; i < int(c.dimensions); i++ { multiplicandOffset := (entry / indexDivisor) % len(multiplicands) c.values[index+i] = float32(multiplicands[multiplicandOffset])*deltaValue + minimumValue + last if sequenceP { last = c.values[index+i] } indexDivisor *= len(multiplicands) } } else if lookupType == 2 { last := float32(0) for i := 0; i < int(c.dimensions); i++ { c.values[index+i] = float32(multiplicands[index+i])*deltaValue + minimumValue + last if sequenceP { last = c.values[index+i] } } } } return nil }
func (s *setup) decodePacket(r *ogg.BitReader, prev [][]float32) ([][]float32, [][]float32, error) { if r.ReadBool() { return nil, nil, ogg.ErrCorruptStream } modeNumber := r.Read8(ilog(len(s.modes) - 1)) mode := s.modes[modeNumber] // decode window type blocktype := mode.blockflag longWindow := mode.blockflag == 1 blocksize := s.blocksize[blocktype] spectrumSize := uint32(blocksize / 2) windowPrev, windowNext := false, false window := windowType{blocksize, blocksize, blocksize} if longWindow { windowPrev = r.ReadBool() windowNext = r.ReadBool() if !windowPrev { window.prev = s.blocksize[0] } if !windowNext { window.next = s.blocksize[0] } } mapping := &s.mappings[mode.mapping] floors := make([]floorData, s.channels) residueVectors := make([][]float32, s.channels) for ch := range residueVectors { residueVectors[ch] = s.residueBuffer[ch][:spectrumSize] for i := range residueVectors[ch] { residueVectors[ch][i] = 0 } } s.decodeFloors(r, floors, mapping, spectrumSize) s.decodeResidue(r, residueVectors, mapping, floors, spectrumSize) s.inverseCoupling(mapping, residueVectors) s.applyFloor(floors, residueVectors) // inverse MDCT out := make([][]float32, s.channels) for ch := range out { out[ch] = make([]float32, blocksize) imdct(s.lookup[blocktype], residueVectors[ch], out[ch]) } // apply window and overlap s.applyWindow(&window, out) center := blocksize / 2 offset := s.blocksize[1]/4 - s.blocksize[0]/4 final := make([][]float32, s.channels) next := make([][]float32, s.channels) if longWindow { for ch := range out { start := 0 end := blocksize if !windowPrev { start += offset } if !windowNext { end -= offset } final[ch], next[ch] = out[ch][start:center], out[ch][center:end] if prev != nil { for i := range prev[ch] { final[ch][i] += prev[ch][i] } } } } else /*short window*/ { for ch := range out { if prev != nil && len(prev[ch]) > center { final[ch], next[ch] = prev[ch], out[ch][center:] for i := offset; i < len(final[ch]); i++ { final[ch][i] += out[ch][i-offset] } } else { final[ch], next[ch] = out[ch][:center], out[ch][center:] if prev != nil { for i := range final[ch] { final[ch][i] += prev[ch][i] } } } } } return final, next, nil }
func (x *residue) ReadFrom(r *ogg.BitReader) error { x.residueType = r.Read16(16) if x.residueType > 2 { return ogg.ErrCorruptStream } x.begin = r.Read32(24) x.end = r.Read32(24) x.partitionSize = r.Read32(24) + 1 x.classifications = r.Read8(6) + 1 x.classbook = r.Read8(8) x.cascade = make([]uint8, x.classifications) for i := range x.cascade { highBits := uint8(0) lowBits := r.Read8(3) if r.ReadBool() { highBits = r.Read8(5) } x.cascade[i] = highBits*8 + lowBits } x.books = make([][8]uint8, x.classifications) for i := range x.books { for j := 0; j < 8; j++ { if x.cascade[i]&(1<<uint(j)) != 0 { x.books[i][j] = r.Read8(8) } else { x.books[i][j] = 0xFF //unused } } } return nil }
func (f *floor0) ReadFrom(r *ogg.BitReader) error { f.order = r.Read8(8) f.rate = r.Read16(16) f.barkMapSize = r.Read16(16) f.amplitudeBits = r.Read8(6) f.amplitudeOffset = r.Read8(8) f.bookList = make([]uint8, r.Read8(4)+1) for i := range f.bookList { f.bookList[i] = r.Read8(8) } return nil }
func (f *floor1) ReadFrom(r *ogg.BitReader) error { f.partitionClassList = make([]uint8, r.Read8(5)) var maximumClass uint8 for i := range f.partitionClassList { class := r.Read8(4) f.partitionClassList[i] = class if class > maximumClass { maximumClass = class } } f.classes = make([]floor1Class, maximumClass+1) for i := range f.classes { class := &f.classes[i] class.dimension = r.Read8(3) + 1 class.subclass = r.Read8(2) if class.subclass != 0 { class.masterbook = r.Read8(8) } class.subclassBooks = make([]uint8, 1<<class.subclass) for i := range class.subclassBooks { class.subclassBooks[i] = r.Read8(8) - 1 } } f.multiplier = r.Read8(2) + 1 f.rangebits = r.Read8(4) f.xList = append(f.xList, 0, 1<<f.rangebits) for _, class := range f.partitionClassList { for i := uint8(0); i < f.classes[class].dimension; i++ { f.xList = append(f.xList, r.Read32(uint(f.rangebits))) } } f.sort = make([]uint32, len(f.xList)) for i := range f.sort { f.sort[i] = uint32(i) } sort.Sort(f) f.step2 = make([]bool, len(f.xList)) f.finalY = make([]uint32, len(f.xList)) return nil }