public override Object look(DspState vd, InfoMode vm, Object m) { Info vi = vd.vi; LookMapping0 looks = new LookMapping0(); InfoMapping0 info = looks.map = (InfoMapping0)m; looks.mode = vm; looks.floor_look = new Object[info.submaps]; looks.residue_look = new Object[info.submaps]; looks.floor_func = new FuncFloor[info.submaps]; looks.residue_func = new FuncResidue[info.submaps]; for (int i = 0; i < info.submaps; i++) { int timenum = info.timesubmap[i]; int floornum = info.floorsubmap[i]; int resnum = info.residuesubmap[i]; looks.floor_func[i] = vi.floor_funcs[floornum]; looks.floor_look[i] = looks.floor_func[i]. look(vd, vm, vi.floor_param[floornum]); looks.residue_func[i] = vi.residue_funcs[resnum]; looks.residue_look[i] = looks.residue_func[i]. look(vd, vm, vi.residue_param[resnum]); } looks.ch = vi.channels; return(looks); }
override public Object look(DspState vd, InfoMode mi, Object i) { float scale; Info vi=vd.vi; InfoFloor0 info=(InfoFloor0)i; LookFloor0 look=new LookFloor0(); look.m=info.order; look.n=vi.blocksizes[mi.blockflag]/2; look.ln=info.barkmap; look.vi=info; look.lpclook.init(look.ln,look.m); // we choose a scaling constant so that: // floor(bark(rate/2-1)*C)=mapped-1 // floor(bark(rate/2)*C)=mapped scale = look.ln / (float)toBARK((float)(info.rate/2.0)); // the mapping from a linear scale to a smaller bark scale is // straightforward. We do *not* make sure that the linear mapping // does not skip bark-scale bins; the decoder simply skips them and // the encoder may do what it wishes in filling them. They're // necessary in some mapping combinations to keep the scale spacing // accurate look.linearmap=new int[look.n]; for(int j=0; j<look.n; j++) { int val=(int)Math.Floor(toBARK((float)((info.rate/2.0)/look.n*j)) *scale); // bark numbers represent band edges if(val>=look.ln) val=look.ln; // guard against the approximation look.linearmap[j]=val; } return look; }
public override Object look(DspState vd, InfoMode vm, Object vr) { InfoResidue0 info = (InfoResidue0)vr; LookResidue0 look = new LookResidue0(); int acc = 0; int maxstage = 0; look.info = info; look.map = vm.mapping; look.parts = info.partitions; look.fullbooks = vd.fullbooks; look.phrasebook = vd.fullbooks[info.groupbook]; int dim = look.phrasebook.dim; look.partbooks = new int[look.parts][]; for (int j = 0; j < look.parts; j++) { int stages = Util.ilog(info.secondstages[j]); if (stages != 0) { if (stages > maxstage) { maxstage = stages; } look.partbooks[j] = new int[stages]; for (int k = 0; k < stages; k++) { if ((info.secondstages[j] & (1 << k)) != 0) { look.partbooks[j][k] = info.booklist[acc++]; } } } } look.partvals = (int)Math.Round(Math.Pow(look.parts, dim)); look.stages = maxstage; look.decodemap = new int[look.partvals][]; for (int j = 0; j < look.partvals; j++) { int val = j; int mult = look.partvals / look.parts; look.decodemap[j] = new int[dim]; for (int k = 0; k < dim; k++) { int deco = val / mult; val -= deco * mult; mult /= look.parts; look.decodemap[j][k] = deco; } } return(look); }
private VorbisFile() { os=new StreamState(); // take physical pages, weld into a logical // stream of packets vd=new DspState(); // central working state for // the packet->PCM decoder vb=new Block(vd); // local working space for packet->PCM decode }
public Block(DspState vd) { this.vd = vd; // localalloc=0; // localstore=null; if (vd.analysisp != 0) { opb.writeinit(); } }
public Block(DspState vd) { this.vd=vd; // localalloc=0; // localstore=null; if(vd.analysisp!=0) { opb.writeinit(); } }
public VorbisFileInstance(VorbisFile sourceFile) { vorbisFile = sourceFile; oy = new SyncState(); bittrack = 0; samptrack = 0; os = new StreamState(); // take physical pages, weld into a logical // stream of packets vd = new DspState(); // central working state for // the packet->PCM decoder vb = new Block(vd); // local working space for packet->PCM decode raw_seek(0); lastStreamPosition = sourceFile.datasource.Position; }
public override Object look(DspState vd, InfoMode vm, Object m) { Info vi = vd.vi; LookMapping0 looks = new LookMapping0(); InfoMapping0 info = looks.map = (InfoMapping0)m; looks.mode = vm; looks.time_look = new Object[info.submaps]; looks.floor_look = new Object[info.submaps]; looks.residue_look = new Object[info.submaps]; looks.time_func = new FuncTime[info.submaps]; looks.floor_func = new FuncFloor[info.submaps]; looks.residue_func = new FuncResidue[info.submaps]; for (int i = 0; i < info.submaps; i++) { int timenum = info.timesubmap[i]; int floornum = info.floorsubmap[i]; int resnum = info.residuesubmap[i]; looks.time_func[i] = FuncTime.time_P[vi.time_type[timenum]]; looks.time_look[i] = looks.time_func[i].look(vd, vm, vi.time_param[timenum]); looks.floor_func[i] = FuncFloor.floor_P[vi.floor_type[floornum]]; looks.floor_look[i] = looks.floor_func[i]. look(vd, vm, vi.floor_param[floornum]); looks.residue_func[i] = FuncResidue.residue_P[vi.residue_type[resnum]]; looks.residue_look[i] = looks.residue_func[i]. look(vd, vm, vi.residue_param[resnum]); } if (vi.psys != 0 && vd.analysisp != 0) { // ?? } looks.ch = vi.Channels; return(looks); }
override public Object look(DspState vd, InfoMode vm, Object m) { Info vi=vd.vi; LookMapping0 looks=new LookMapping0(); InfoMapping0 info=looks.map=(InfoMapping0)m; looks.mode=vm; looks.time_look=new Object[info.submaps]; looks.floor_look=new Object[info.submaps]; looks.residue_look=new Object[info.submaps]; looks.time_func=new FuncTime[info.submaps]; looks.floor_func=new FuncFloor[info.submaps]; looks.residue_func=new FuncResidue[info.submaps]; for(int i=0;i<info.submaps;i++) { int timenum=info.timesubmap[i]; int floornum=info.floorsubmap[i]; int resnum=info.residuesubmap[i]; looks.time_func[i]=FuncTime.time_P[vi.time_type[timenum]]; looks.time_look[i]=looks.time_func[i].look(vd,vm,vi.time_param[timenum]); looks.floor_func[i]=FuncFloor.floor_P[vi.floor_type[floornum]]; looks.floor_look[i]=looks.floor_func[i]. look(vd,vm,vi.floor_param[floornum]); looks.residue_func[i]=FuncResidue.residue_P[vi.residue_type[resnum]]; looks.residue_look[i]=looks.residue_func[i]. look(vd,vm,vi.residue_param[resnum]); } if(vi.psys!=0 && vd.analysisp!=0) { } looks.ch=vi.channels; return(looks); }
public override object look(DspState vd, InfoMode mi, object i) { Info vi = vd.vi; InfoFloor0 info = (InfoFloor0)i; LookFloor0 look = new LookFloor0(); look.m = info.order; look.n = vi.blocksizes[mi.blockflag] / 2; look.ln = info.barkmap; look.vi = info; look.lpclook.init(look.ln, look.m); // we choose a scaling constant so that: // floor(bark(rate/2-1)*C)=mapped-1 // floor(bark(rate/2)*C)=mapped float scale = look.ln / (float)toBARK((float)(info.rate / 2.0)); // the mapping from a linear scale to a smaller bark scale is // straightforward. We do *not* make sure that the linear mapping // does not skip bark-scale bins; the decoder simply skips them and // the encoder may do what it wishes in filling them. They're // necessary in some mapping combinations to keep the scale spacing // accurate look.linearmap = new int[look.n]; for (int j = 0; j < look.n; j++) { int val = (int)Math.Floor(toBARK((float)((info.rate / 2.0) / look.n * j)) * scale); // bark numbers represent band edges // guard against the approximation if (val >= look.ln) { val = look.ln; } look.linearmap[j] = val; } return(look); }
public override Object look(DspState vd, InfoMode vm, Object vr) { InfoResidue0 info=(InfoResidue0)vr; LookResidue0 look=new LookResidue0(); int acc=0; int dim; int maxstage=0; look.info=info; look.map=vm.mapping; look.parts=info.partitions; look.fullbooks=vd.fullbooks; look.phrasebook=vd.fullbooks[info.groupbook]; dim=look.phrasebook.dim; look.partbooks=new int[look.parts][]; for(int j=0;j<look.parts;j++) { int stages=ilog(info.secondstages[j]); if(stages!=0) { if(stages>maxstage)maxstage=stages; look.partbooks[j]=new int[stages]; for(int k=0; k<stages; k++) { if((info.secondstages[j]&(1<<k))!=0) { look.partbooks[j][k]=info.booklist[acc++]; } } } } look.partvals=(int)Math.Round(Math.Pow(look.parts,dim)); look.stages=maxstage; look.decodemap=new int[look.partvals][]; for(int j=0;j<look.partvals;j++) { int val=j; int mult=look.partvals/look.parts; look.decodemap[j]=new int[dim]; for(int k=0;k<dim;k++) { int deco=val/mult; val-=deco*mult; mult/=look.parts; look.decodemap[j][k]=deco; } } return(look); }
public void init(DspState vd) { this.vd=vd; }
public abstract Object look(DspState vd, InfoMode vm, Object vr);
public override Object look(DspState vd, InfoMode mi, Object i) { return(""); }
public override int inverse(Block vb, Object l) { //System.err.println("Mapping0.inverse"); DspState vd = vb.vd; Info vi = vd.vi; LookMapping0 look = (LookMapping0)l; InfoMapping0 info = look.map; InfoMode mode = look.mode; int n = vb.pcmend = vi.blocksizes[vb.W]; float[] window = vd.wnd[vb.W][vb.lW][vb.nW]; if (pcmbundle == null || pcmbundle.Length < vi.channels) { pcmbundle = new float[vi.channels][]; nonzero = new int[vi.channels]; zerobundle = new int[vi.channels]; floormemo = new Object[vi.channels]; } // recover the spectral envelope; store it in the PCM vector for now for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; int submap = info.chmuxlist[i]; floormemo[i] = look.floor_func[submap].inverse1(vb, look. floor_look[submap], floormemo[i] ); if (floormemo[i] != null) { nonzero[i] = 1; } else { nonzero[i] = 0; } for (int j = 0; j < n / 2; j++) { pcm[j] = 0; } } for (int i = 0; i < info.coupling_steps; i++) { if (nonzero[info.coupling_mag[i]] != 0 || nonzero[info.coupling_ang[i]] != 0) { nonzero[info.coupling_mag[i]] = 1; nonzero[info.coupling_ang[i]] = 1; } } // recover the residue, apply directly to the spectral envelope for (int i = 0; i < info.submaps; i++) { int ch_in_bundle = 0; for (int j = 0; j < vi.channels; j++) { if (info.chmuxlist[j] != i) { continue; } zerobundle[ch_in_bundle] = nonzero[j] != 0 ? 1 : 0; pcmbundle[ch_in_bundle++] = vb.pcm[j]; } look.residue_func[i].inverse(vb, look.residue_look[i], pcmbundle, zerobundle, ch_in_bundle); } InverseCoupling(n, vb, info); // compute and apply spectral envelope for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; int submap = info.chmuxlist[i]; look.floor_func[submap].inverse2(vb, look.floor_look[submap], floormemo[i], pcm); } // transform the PCM data; takes PCM vector, vb; modifies PCM vector // only MDCT right now.... for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; ((Mdct)vd.transform[vb.W]).backward(pcm, pcm); } // window the data for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; if (nonzero[i] != 0) { for (int j = 0; j < n; j++) { pcm[j] *= window[j]; } } else { for (int j = 0; j < n; j++) { pcm[j] = 0.0f; } } } return(0); }
override public Object look(DspState vd, InfoMode mi, Object i) { int _n=0; int[] sortpointer=new int[VIF_POSIT+2]; // Info vi=vd.vi; InfoFloor1 info=(InfoFloor1)i; LookFloor1 look=new LookFloor1(); look.vi=info; look.n=info.postlist[1]; /* we drop each position value in-between already decoded values, and use linear interpolation to predict each new value past the edges. The positions are read in the order of the position list... we precompute the bounding positions in the lookup. Of course, the neighbors can change (if a position is declined), but this is an initial mapping */ for(int j=0;j<info.partitions;j++) { _n+=info.class_dim[info.partitionclass[j]]; } _n+=2; look.posts=_n; /* also store a sorted position index */ for(int j=0;j<_n;j++) { sortpointer[j]=j; } // qsort(sortpointer,n,sizeof(int),icomp); // !! int foo; for(int j=0; j<_n-1; j++) { for(int k=j; k<_n; k++) { if(info.postlist[sortpointer[j]]>info.postlist[sortpointer[k]]) { foo=sortpointer[k]; sortpointer[k]=sortpointer[j]; sortpointer[j]=foo; } } } /* points from sort order back to range number */ for(int j=0;j<_n;j++) { look.forward_index[j]=sortpointer[j]; } /* points from range order to sorted position */ for(int j=0;j<_n;j++) { look.reverse_index[look.forward_index[j]]=j; } /* we actually need the post values too */ for(int j=0;j<_n;j++) { look.sorted_index[j]=info.postlist[look.forward_index[j]]; } /* quantize values to multiplier spec */ switch(info.mult) { case 1: /* 1024 -> 256 */ look.quant_q=256; break; case 2: /* 1024 -> 128 */ look.quant_q=128; break; case 3: /* 1024 -> 86 */ look.quant_q=86; break; case 4: /* 1024 -> 64 */ look.quant_q=64; break; default: look.quant_q=-1; break; } /* discover our neighbors for decode where we don't use fit flags (that would push the neighbors outward) */ for(int j=0;j<_n-2;j++) { int lo=0; int hi=1; int lx=0; int hx=look.n; int currentx=info.postlist[j+2]; for(int k=0;k<j+2;k++) { int x=info.postlist[k]; if(x>lx && x<currentx) { lo=k; lx=x; } if(x<hx && x>currentx) { hi=k; hx=x; } } look.loneighbor[j]=lo; look.hineighbor[j]=hi; } return look; }
/// <summary> /// Decodes a stream of Ogg Vorbis data into wav file format. /// </summary> /// <returns> /// A MemoryStream with the entire decoded stream. /// </returns> /// <param name='input'> /// Ogg Vorbis data to be decoded /// </param> /// <param name='output'> /// <para>Stream to write wav data.</para> /// <para>If writeWavHeader is true then this stream must be seekable.</para> /// </param> /// <param name='writeWavHeader'> /// Write wav header in the beginning of the returned stream. /// </param> public static void DecodeStream(Stream input, Stream output, bool writeWavHeader) { int convsize = 4096 * 2; byte[] convbuffer = new byte[convsize]; // take 8k out of the data segment, not the stack long start = output.Position; DebugWriter s_err = new DebugWriter(); if (writeWavHeader && !output.CanSeek) throw new ArgumentException("To write wav header, the output stream must be seekable.", "output"); if (writeWavHeader) output.Seek(HEADER_SIZE, SeekOrigin.Current); // reserve place for WAV header SyncState oy = new SyncState(); // sync and verify incoming physical bitstream StreamState os = new StreamState(); // take physical pages, weld into a logical stream of packets Page og = new Page(); // one Ogg bitstream page. Vorbis packets are inside Packet op = new Packet(); // one raw packet of data for decode Info vi = new Info(); // struct that stores all the static vorbis bitstream settings Comment vc = new Comment(); // struct that stores all the bitstream user comments DspState vd = new DspState(); // central working state for the packet->PCM decoder Block vb = new Block(vd); // local working space for packet->PCM decode int bytes = 0; // Decode setup oy.init(); // Now we can read pages // we repeat if the bitstream is chained while (true) { int eos = 0; // grab some data at the head of the stream. We want the first page // (which is guaranteed to be small and only contain the Vorbis // stream initial header) We need the first page to get the stream // serialno. // submit a 4k block to libvorbis' Ogg layer int index = oy.buffer(4096); bytes = input.Read(oy.data, index, 4096); oy.wrote(bytes); // Get the first page. if (oy.pageout(og) != 1) { // have we simply run out of data? If so, we're done. if (bytes < 4096) break; // error case. Must not be Vorbis data s_err.WriteLine("Input does not appear to be an Ogg bitstream."); } // Get the serial number and set up the rest of decode. // serialno first; use it to set up a logical stream os.init(og.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data // I handle the initial header first instead of just having the code // read all three Vorbis headers at once because reading the initial // header is an easy way to identify a Vorbis bitstream and it's // useful to see that functionality seperated out. vi.init(); vc.init(); if (os.pagein(og) < 0) { // error; stream version mismatch perhaps s_err.WriteLine("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { // no page? must not be vorbis s_err.WriteLine("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { // error case; not a vorbis header s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data."); } // At this point, we're sure we're Vorbis. We've set up the logical // (Ogg) bitstream decoder. Get the comment and codebook headers and // set up the Vorbis decoder // The next two packets in order are the comment and codebook headers. // They're likely large and may span multiple pages. Thus we reead // and submit data until we get our two pacakets, watching that no // pages are missing. If a page is missing, error out; losing a // header page is the only place where missing data is fatal. */ int i = 0; while (i < 2) { while (i < 2) { int result = oy.pageout(og); if (result == 0) break; // Need more data // Don't complain about missing or corrupt data yet. We'll // catch it at the packet output phase if (result == 1) { os.pagein(og); // we can ignore any errors here // as they'll also become apparent // at packetout while (i < 2) { result = os.packetout(op); if (result == 0) break; if (result == -1) { // Uh oh; data at some point was corrupted or missing! // We can't tolerate that in a header. Die. s_err.WriteLine("Corrupt secondary header. Exiting."); } vi.synthesis_headerin(vc, op); i++; } } } // no harm in not checking before adding more index = oy.buffer(4096); bytes = input.Read(oy.data, index, 4096); if (bytes == 0 && i < 2) { s_err.WriteLine("End of file before finding all Vorbis headers!"); } oy.wrote(bytes); } // Throw the comments plus a few lines about the bitstream we're // decoding { byte[][] ptr = vc.user_comments; for (int j = 0; j < vc.user_comments.Length; j++) { if (ptr [j] == null) break; s_err.WriteLine(vc.getComment(j)); } s_err.WriteLine("\nBitstream is " + vi.channels + " channel, " + vi.rate + "Hz"); s_err.WriteLine("Encoded by: " + vc.getVendor() + "\n"); } convsize = 4096 / vi.channels; // OK, got and parsed all three headers. Initialize the Vorbis // packet->PCM decoder. vd.synthesis_init(vi); // central decode state vb.init(vd); // local state for most of the decode // so multiple block decodes can // proceed in parallel. We could init // multiple vorbis_block structures // for vd here float[][][] _pcm = new float[1][][]; int[] _index = new int[vi.channels]; // The rest is just a straight decode loop until end of stream while (eos == 0) { while (eos == 0) { int result = oy.pageout(og); if (result == 0) break; // need more data if (result == -1) { // missing or corrupt data at this page position s_err.WriteLine("Corrupt or missing data in bitstream; continuing..."); } else { os.pagein(og); // can safely ignore errors at // this point while (true) { result = os.packetout(op); if (result == 0) break; // need more data if (result == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above } else { // we have a packet. Decode it int samples; if (vb.synthesis(op) == 0) { // test for success! vd.synthesis_blockin(vb); } // **pcm is a multichannel float vector. In stereo, for // example, pcm[0] is left, and pcm[1] is right. samples is // the size of each channel. Convert the float values // (-1.<=range<=1.) to whatever PCM format and write it out while ((samples = vd.synthesis_pcmout(_pcm, _index)) > 0) { float[][] pcm = _pcm [0]; bool clipflag = false; int bout = (samples < convsize ? samples : convsize); // convert floats to 16 bit signed ints (host order) and // interleave for (i = 0; i < vi.channels; i++) { int ptr = i * 2; //int ptr=i; int mono = _index [i]; for (int j = 0; j < bout; j++) { int val = (int)(pcm [i] [mono + j] * 32767.0); // short val=(short)(pcm[i][mono+j]*32767.); // int val=(int)Math.round(pcm[i][mono+j]*32767.); // might as well guard against clipping if (val > 32767) { val = 32767; clipflag = true; } if (val < -32768) { val = -32768; clipflag = true; } if (val < 0) val = val | 0x8000; convbuffer [ptr] = (byte)(val); convbuffer [ptr + 1] = (byte)((uint)val >> 8); ptr += 2 * (vi.channels); } } if (clipflag) { //s_err.WriteLine("Clipping in frame "+vd.sequence); } output.Write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); // tell libvorbis how // many samples we // actually consumed } } } if (og.eos() != 0) eos = 1; } } if (eos == 0) { index = oy.buffer(4096); bytes = input.Read(oy.data, index, 4096); oy.wrote(bytes); if (bytes == 0) eos = 1; } } // clean up this logical bitstream; before exit we see if we're // followed by another [chained] os.clear(); // ogg_page and ogg_packet structs always point to storage in // libvorbis. They're never freed or manipulated directly vb.clear(); vd.clear(); vi.clear(); // must be called last } // OK, clean up the framer oy.clear(); s_err.WriteLine("Done."); if (writeWavHeader) { long end = output.Position; int length = (int)(end - (start + HEADER_SIZE)); output.Seek(start, SeekOrigin.Begin); WriteHeader(output, length, vi.rate, (ushort)16, (ushort)vi.channels); output.Seek(end, SeekOrigin.Begin); } }
override public int inverse(Block vb, Object l) { lock (this) { //System.err.println("Mapping0.inverse"); DspState vd = vb.vd; Info vi = vd.vi; LookMapping0 look = (LookMapping0)l; InfoMapping0 info = look.map; InfoMode mode = look.mode; int n = vb.pcmend = vi.blocksizes[vb.W]; float[] window = vd.wnd[vb.W][vb.lW][vb.nW][mode.windowtype]; // float[][] pcmbundle=new float[vi.channels][]; // int[] nonzero=new int[vi.channels]; if (pcmbundle == null || pcmbundle.Length < vi.channels) { pcmbundle = new float[vi.channels][]; nonzero = new int[vi.channels]; zerobundle = new int[vi.channels]; floormemo = new Object[vi.channels]; } // time domain information decode (note that applying the // information would have to happen later; we'll probably add a // function entry to the harness for that later // NOT IMPLEMENTED // recover the spectral envelope; store it in the PCM vector for now for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; int submap = info.chmuxlist[i]; floormemo[i] = look.floor_func[submap].inverse1(vb, look. floor_look[submap], floormemo[i] ); if (floormemo[i] != null) { nonzero[i] = 1; } else { nonzero[i] = 0; } for (int j = 0; j < n / 2; j++) { pcm[j] = 0; } //_analysis_output("ifloor",seq+i,pcm,n/2,0,1); } for (int i = 0; i < info.coupling_steps; i++) { if (nonzero[info.coupling_mag[i]] != 0 || nonzero[info.coupling_ang[i]] != 0) { nonzero[info.coupling_mag[i]] = 1; nonzero[info.coupling_ang[i]] = 1; } } // recover the residue, apply directly to the spectral envelope for (int i = 0; i < info.submaps; i++) { int ch_in_bundle = 0; for (int j = 0; j < vi.channels; j++) { if (info.chmuxlist[j] == i) { if (nonzero[j] != 0) { zerobundle[ch_in_bundle] = 1; } else { zerobundle[ch_in_bundle] = 0; } pcmbundle[ch_in_bundle++] = vb.pcm[j]; } } look.residue_func[i].inverse(vb, look.residue_look[i], pcmbundle, zerobundle, ch_in_bundle); } for (int i = info.coupling_steps - 1; i >= 0; i--) { float[] pcmM = vb.pcm[info.coupling_mag[i]]; float[] pcmA = vb.pcm[info.coupling_ang[i]]; for (int j = 0; j < n / 2; j++) { float mag = pcmM[j]; float ang = pcmA[j]; if (mag > 0) { if (ang > 0) { pcmM[j] = mag; pcmA[j] = mag - ang; } else { pcmA[j] = mag; pcmM[j] = mag + ang; } } else { if (ang > 0) { pcmM[j] = mag; pcmA[j] = mag + ang; } else { pcmA[j] = mag; pcmM[j] = mag - ang; } } } } // /* compute and apply spectral envelope */ for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; int submap = info.chmuxlist[i]; look.floor_func[submap].inverse2(vb, look.floor_look[submap], floormemo[i], pcm); } // transform the PCM data; takes PCM vector, vb; modifies PCM vector // only MDCT right now.... for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; //_analysis_output("out",seq+i,pcm,n/2,0,0); ((Mdct)vd.transform[vb.W][0]).backward(pcm, pcm); } // now apply the decoded pre-window time information // NOT IMPLEMENTED // window the data for (int i = 0; i < vi.channels; i++) { float[] pcm = vb.pcm[i]; if (nonzero[i] != 0) { for (int j = 0; j < n; j++) { pcm[j] *= window[j]; } } else { for (int j = 0; j < n; j++) { pcm[j] = 0.0f; } } //_analysis_output("final",seq++,pcm,n,0,0); } // now apply the decoded post-window time information // NOT IMPLEMENTED // all done! return(0); } }
static MemoryStream DecodeStream(Stream input, bool skipWavHeader, out Info vi) { int convsize = 4096 * 2; byte[] convbuffer = new byte[convsize]; // take 8k out of the data segment, not the stack TextWriter s_err = new DebugWriter(); var output = new MemoryStream(); if (!skipWavHeader) { output.Seek(HEADER_SIZE, SeekOrigin.Begin); // reserve place for WAV header } SyncState oy = new SyncState(); // sync and verify incoming physical bitstream StreamState os = new StreamState(); // take physical pages, weld into a logical stream of packets Page og = new Page(); // one Ogg bitstream page. Vorbis packets are inside Packet op = new Packet(); // one raw packet of data for decode vi = new Info(); // struct that stores all the static vorbis bitstream settings Comment vc = new Comment(); // struct that stores all the bitstream user comments DspState vd = new DspState(); // central working state for the packet->PCM decoder Block vb = new Block(vd); // local working space for packet->PCM decode byte[] buffer; int bytes = 0; // Decode setup oy.init(); // Now we can read pages while (true) { // we repeat if the bitstream is chained int eos = 0; // grab some data at the head of the stream. We want the first page // (which is guaranteed to be small and only contain the Vorbis // stream initial header) We need the first page to get the stream // serialno. // submit a 4k block to libvorbis' Ogg layer int index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); // Get the first page. if (oy.pageout(og) != 1) { // have we simply run out of data? If so, we're done. if (bytes < 4096) { break; } // error case. Must not be Vorbis data s_err.WriteLine("Input does not appear to be an Ogg bitstream."); } // Get the serial number and set up the rest of decode. // serialno first; use it to set up a logical stream os.init(og.serialno()); // extract the initial header from the first page and verify that the // Ogg bitstream is in fact Vorbis data // I handle the initial header first instead of just having the code // read all three Vorbis headers at once because reading the initial // header is an easy way to identify a Vorbis bitstream and it's // useful to see that functionality seperated out. vi.init(); vc.init(); if (os.pagein(og) < 0) { // error; stream version mismatch perhaps s_err.WriteLine("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { // no page? must not be vorbis s_err.WriteLine("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { // error case; not a vorbis header s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data."); } // At this point, we're sure we're Vorbis. We've set up the logical // (Ogg) bitstream decoder. Get the comment and codebook headers and // set up the Vorbis decoder // The next two packets in order are the comment and codebook headers. // They're likely large and may span multiple pages. Thus we reead // and submit data until we get our two pacakets, watching that no // pages are missing. If a page is missing, error out; losing a // header page is the only place where missing data is fatal. */ int i = 0; while (i < 2) { while (i < 2) { int result = oy.pageout(og); if (result == 0) { break; // Need more data } // Don't complain about missing or corrupt data yet. We'll // catch it at the packet output phase if (result == 1) { os.pagein(og); // we can ignore any errors here // as they'll also become apparent // at packetout while (i < 2) { result = os.packetout(op); if (result == 0) { break; } if (result == -1) { // Uh oh; data at some point was corrupted or missing! // We can't tolerate that in a header. Die. s_err.WriteLine("Corrupt secondary header. Exiting."); } vi.synthesis_headerin(vc, op); i++; } } } // no harm in not checking before adding more index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } if (bytes == 0 && i < 2) { s_err.WriteLine("End of file before finding all Vorbis headers!"); } oy.wrote(bytes); } // Throw the comments plus a few lines about the bitstream we're // decoding { byte[][] ptr = vc.user_comments; for (int j = 0; j < vc.user_comments.Length; j++) { if (ptr[j] == null) { break; } s_err.WriteLine(vc.getComment(j)); } s_err.WriteLine("\nBitstream is " + vi.channels + " channel, " + vi.rate + "Hz"); s_err.WriteLine("Encoded by: " + vc.getVendor() + "\n"); } convsize = 4096 / vi.channels; // OK, got and parsed all three headers. Initialize the Vorbis // packet->PCM decoder. vd.synthesis_init(vi); // central decode state vb.init(vd); // local state for most of the decode // so multiple block decodes can // proceed in parallel. We could init // multiple vorbis_block structures // for vd here float[][][] _pcm = new float[1][][]; int[] _index = new int[vi.channels]; // The rest is just a straight decode loop until end of stream while (eos == 0) { while (eos == 0) { int result = oy.pageout(og); if (result == 0) { break; // need more data } if (result == -1) { // missing or corrupt data at this page position s_err.WriteLine("Corrupt or missing data in bitstream; continuing..."); } else { os.pagein(og); // can safely ignore errors at // this point while (true) { result = os.packetout(op); if (result == 0) { break; // need more data } if (result == -1) { // missing or corrupt data at this page position // no reason to complain; already complained above } else { // we have a packet. Decode it int samples; if (vb.synthesis(op) == 0) { // test for success! vd.synthesis_blockin(vb); } // **pcm is a multichannel float vector. In stereo, for // example, pcm[0] is left, and pcm[1] is right. samples is // the size of each channel. Convert the float values // (-1.<=range<=1.) to whatever PCM format and write it out while ((samples = vd.synthesis_pcmout(_pcm, _index)) > 0) { float[][] pcm = _pcm[0]; bool clipflag = false; int bout = (samples < convsize ? samples : convsize); // convert floats to 16 bit signed ints (host order) and // interleave for (i = 0; i < vi.channels; i++) { int ptr = i * 2; //int ptr=i; int mono = _index[i]; for (int j = 0; j < bout; j++) { int val = (int)(pcm[i][mono + j] * 32767.0); // short val=(short)(pcm[i][mono+j]*32767.); // int val=(int)Math.round(pcm[i][mono+j]*32767.); // might as well guard against clipping if (val > 32767) { val = 32767; clipflag = true; } if (val < -32768) { val = -32768; clipflag = true; } if (val < 0) { val = val | 0x8000; } convbuffer[ptr] = (byte)(val); convbuffer[ptr + 1] = (byte)((uint)val >> 8); ptr += 2 * (vi.channels); } } if (clipflag) { //s_err.WriteLine("Clipping in frame "+vd.sequence); } output.Write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); // tell libvorbis how // many samples we // actually consumed } } } if (og.eos() != 0) { eos = 1; } } } if (eos == 0) { index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); if (bytes == 0) { eos = 1; } } } // clean up this logical bitstream; before exit we see if we're // followed by another [chained] os.clear(); // ogg_page and ogg_packet structs always point to storage in // libvorbis. They're never freed or manipulated directly vb.clear(); vd.clear(); vi.clear(); // must be called last } // OK, clean up the framer oy.clear(); s_err.WriteLine("Done."); output.Seek(0, SeekOrigin.Begin); if (!skipWavHeader) { WriteHeader(output, (int)(output.Length - HEADER_SIZE), vi.rate, (ushort)16, (ushort)vi.channels); output.Seek(0, SeekOrigin.Begin); } return(output); }
public override Object look(DspState vd, InfoMode mi, Object i) { return ""; }
override public Object look(DspState vd, InfoMode mi, Object i) { int _n = 0; int[] sortpointer = new int[VIF_POSIT + 2]; // Info vi=vd.vi; InfoFloor1 info = (InfoFloor1)i; LookFloor1 look = new LookFloor1(); look.vi = info; look.n = info.postlist[1]; /* we drop each position value in-between already decoded values, * and use linear interpolation to predict each new value past the * edges. The positions are read in the order of the position * list... we precompute the bounding positions in the lookup. Of * course, the neighbors can change (if a position is declined), but * this is an initial mapping */ for (int j = 0; j < info.partitions; j++) { _n += info.class_dim[info.partitionclass[j]]; } _n += 2; look.posts = _n; /* also store a sorted position index */ for (int j = 0; j < _n; j++) { sortpointer[j] = j; } // qsort(sortpointer,n,sizeof(int),icomp); // !! int foo; for (int j = 0; j < _n - 1; j++) { for (int k = j; k < _n; k++) { if (info.postlist[sortpointer[j]] > info.postlist[sortpointer[k]]) { foo = sortpointer[k]; sortpointer[k] = sortpointer[j]; sortpointer[j] = foo; } } } /* points from sort order back to range number */ for (int j = 0; j < _n; j++) { look.forward_index[j] = sortpointer[j]; } /* points from range order to sorted position */ for (int j = 0; j < _n; j++) { look.reverse_index[look.forward_index[j]] = j; } /* we actually need the post values too */ for (int j = 0; j < _n; j++) { look.sorted_index[j] = info.postlist[look.forward_index[j]]; } /* quantize values to multiplier spec */ switch (info.mult) { case 1: /* 1024 -> 256 */ look.quant_q = 256; break; case 2: /* 1024 -> 128 */ look.quant_q = 128; break; case 3: /* 1024 -> 86 */ look.quant_q = 86; break; case 4: /* 1024 -> 64 */ look.quant_q = 64; break; default: look.quant_q = -1; break; } /* discover our neighbors for decode where we don't use fit flags * (that would push the neighbors outward) */ for (int j = 0; j < _n - 2; j++) { int lo = 0; int hi = 1; int lx = 0; int hx = look.n; int currentx = info.postlist[j + 2]; for (int k = 0; k < j + 2; k++) { int x = info.postlist[k]; if (x > lx && x < currentx) { lo = k; lx = x; } if (x < hx && x > currentx) { hi = k; hx = x; } } look.loneighbor[j] = lo; look.hineighbor[j] = hi; } return(look); }
Stream DecodeStream( Stream input, bool skipWavHeader ) { int convsize = 4096 * 2; byte [] convbuffer = new byte [ convsize ]; Stream output = new MemoryStream (); if ( !skipWavHeader ) output.Seek ( HEADER_SIZE, SeekOrigin.Begin ); SyncState oy = new SyncState (); StreamState os = new StreamState (); Page og = new Page (); Packet op = new Packet (); Info vi = new Info (); Comment vc = new Comment (); DspState vd = new DspState (); Block vb = new Block ( vd ); byte [] buffer; int bytes = 0; oy.init (); while ( true ) { int eos = 0; int index = oy.buffer ( 4096 ); buffer = oy.data; bytes = input.Read ( buffer, index, 4096 ); oy.wrote ( bytes ); if ( oy.pageout ( og ) != 1 ) { if ( bytes < 4096 ) break; throw new Exception ( "Input does not appear to be an Ogg bitstream." ); } os.init ( og.serialno () ); vi.init (); vc.init (); if ( os.pagein ( og ) < 0 ) { throw new Exception ( "Error reading first page of Ogg bitstream data." ); } if ( os.packetout ( op ) != 1 ) { throw new Exception ( "Error reading initial header packet." ); } if ( vi.synthesis_headerin ( vc, op ) < 0 ) { throw new Exception ( "This Ogg bitstream does not contain Vorbis audio data." ); } int i = 0; while ( i < 2 ) { while ( i < 2 ) { int result = oy.pageout ( og ); if ( result == 0 ) break; if ( result == 1 ) { os.pagein ( og ); while ( i < 2 ) { result = os.packetout ( op ); if ( result == 0 ) break; if ( result == -1 ) { throw new Exception ( "Corrupt secondary header. Exiting." ); } vi.synthesis_headerin ( vc, op ); i++; } } } index = oy.buffer ( 4096 ); buffer = oy.data; bytes = input.Read ( buffer, index, 4096 ); if ( bytes == 0 && i < 2 ) { throw new Exception ( "End of file before finding all Vorbis headers!" ); } oy.wrote ( bytes ); } { byte [] [] ptr = vc.user_comments; for ( int j = 0; j < vc.user_comments.Length; j++ ) { if ( ptr [ j ] == null ) break; } } convsize = 4096 / vi.channels; vd.synthesis_init ( vi ); vb.init ( vd ); float [] [] [] _pcm = new float [ 1 ] [][]; int [] _index = new int [ vi.channels ]; while ( eos == 0 ) { while ( eos == 0 ) { int result = oy.pageout ( og ); if ( result == 0 ) break; if ( result == -1 ) throw new Exception ( "Corrupt or missing data in bitstream; continuing..." ); else { os.pagein ( og ); while ( true ) { result = os.packetout ( op ); if ( result == 0 ) break; if ( result == -1 ) { } else { int samples; if ( vb.synthesis ( op ) == 0 ) { vd.synthesis_blockin ( vb ); } while ( ( samples = vd.synthesis_pcmout ( _pcm, _index ) ) > 0 ) { float [] [] pcm = _pcm [ 0 ]; bool clipflag = false; int bout = ( samples < convsize ? samples : convsize ); for ( i = 0; i < vi.channels; i++ ) { int ptr = i * 2; int mono = _index [ i ]; for ( int j = 0; j < bout; j++ ) { int val = ( int ) ( pcm [ i ] [ mono + j ] * 32767.0 ); if ( val > 32767 ) { val = 32767; clipflag = true; } if ( val < -32768 ) { val = -32768; clipflag = true; } if ( val < 0 ) val = val | 0x8000; convbuffer [ ptr ] = ( byte ) ( val ); convbuffer [ ptr + 1 ] = ( byte ) ( ( uint ) val >> 8 ); ptr += 2 * ( vi.channels ); } } if ( clipflag ) { } output.Write ( convbuffer, 0, 2 * vi.channels * bout ); vd.synthesis_read ( bout ); } } } if ( og.eos () != 0 ) eos = 1; } } if ( eos == 0 ) { index = oy.buffer ( 4096 ); buffer = oy.data; bytes = input.Read ( buffer, index, 4096 ); oy.wrote ( bytes ); if ( bytes == 0 ) eos = 1; } } os.clear (); vb.clear (); vd.clear (); vi.clear (); } oy.clear (); output.Seek ( 0, SeekOrigin.Begin ); if ( !skipWavHeader ) { WriteHeader ( output, ( int ) ( output.Length - HEADER_SIZE ), vi.rate, ( ushort ) 16, ( ushort ) vi.channels ); output.Seek ( 0, SeekOrigin.Begin ); } return output; }
public void init(DspState vd) { this.vd = vd; }
public abstract Object look(DspState vd, InfoMode mi, Object i);
public abstract Object look(DspState vd, InfoMode vm, Object i);
public AudioSample OggToWav(Stream ogg, float volume, float pitch) { AudioSample sample = new AudioSample(); TextWriter s_err = new StringWriter(); Stream input = null; MemoryStream output = null; input = ogg; output = new MemoryStream(); SyncState oy = new SyncState(); StreamState os = new StreamState(); Page og = new Page(); Packet op = new Packet(); Info vi = new Info(); Comment vc = new Comment(); DspState vd = new DspState(); Block vb = new Block(vd); byte[] buffer; int bytes = 0; oy.init(); while (true) { int eos = 0; int index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); if (oy.pageout(og) != 1) { if (bytes < 4096) break; s_err.WriteLine("Input does not appear to be an Ogg bitstream."); } os.init(og.serialno()); vi.init(); vc.init(); if (os.pagein(og) < 0) { s_err.WriteLine("Error reading first page of Ogg bitstream data."); } if (os.packetout(op) != 1) { s_err.WriteLine("Error reading initial header packet."); } if (vi.synthesis_headerin(vc, op) < 0) { s_err.WriteLine("This Ogg bitstream does not contain Vorbis audio data."); } int i = 0; while (i < 2) { while (i < 2) { int result = oy.pageout(og); if (result == 0) break; if (result == 1) { os.pagein(og); while (i < 2) { result = os.packetout(op); if (result == 0) break; vi.synthesis_headerin(vc, op); i++; } } } index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); } sample.Channels = vi.channels; sample.Rate = (int)((float)vi.rate * pitch); convsize = 4096 / vi.channels; vd.synthesis_init(vi); vb.init(vd); float[][][] _pcm = new float[1][][]; int[] _index = new int[vi.channels]; while (eos == 0) { while (eos == 0) { int result = oy.pageout(og); if (result == 0) break; if (result != -1) { os.pagein(og); while (true) { result = os.packetout(op); if (result == 0) break; if (result != -1) { int samples; if (vb.synthesis(op) == 0) { vd.synthesis_blockin(vb); } while ((samples = vd.synthesis_pcmout(_pcm, _index)) > 0) { float[][] pcm = _pcm[0]; int bout = (samples < convsize ? samples : convsize); for (i = 0; i < vi.channels; i++) { int ptr = i * 2; int mono = _index[i]; for (int j = 0; j < bout; j++) { int val = (int)(pcm[i][mono + j] * 32767.0); if (val > 32767) { val = 32767; } if (val < -32768) { val = -32768; } val = (int)((float)val * volume); if (val < 0) val = val | 0x8000; convbuffer[ptr] = (byte)(val); convbuffer[ptr + 1] = (byte)((uint)val >> 8); ptr += 2 * (vi.channels); } } output.Write(convbuffer, 0, 2 * vi.channels * bout); vd.synthesis_read(bout); } } } if (og.eos() != 0) eos = 1; } } if (eos == 0) { index = oy.buffer(4096); buffer = oy.data; try { bytes = input.Read(buffer, index, 4096); } catch (Exception e) { s_err.WriteLine(e); } oy.wrote(bytes); if (bytes == 0) eos = 1; } } os.clear(); vb.clear(); vd.clear(); vi.clear(); break; } oy.clear(); input.Close(); sample.Pcm = output.ToArray(); return sample; }