internal virtual MPGLib.buf addbuf(MPGLib.mpstr_tag mp, byte[] de, int bufPos, int size) { var nbuf = new MPGLib.buf { pnt = new byte[size], size = size, next = null, prev = mp.head, pos = 0 }; Array.Copy(de, bufPos, nbuf.pnt, 0, size); if (null == mp.tail) { mp.tail = nbuf; } else { mp.head.next = nbuf; } mp.head = nbuf; mp.bsize += size; return(nbuf); }
internal virtual void copy_mp(MPGLib.mpstr_tag mp, int size, byte[] ptr, int ptrPos) { var len = 0; while (len < size && mp.tail != null) { int nlen; var blen = mp.tail.size - mp.tail.pos; if (size - len <= blen) { nlen = size - len; } else { nlen = blen; } Array.Copy(mp.tail.pnt, mp.tail.pos, ptr, ptrPos + len, nlen); len += nlen; mp.tail.pos += nlen; mp.bsize -= nlen; if (mp.tail.pos == mp.tail.size) { remove_buf(mp); } } }
internal virtual MPGLib.mpstr_tag InitMP3() { var mp = new MPGLib.mpstr_tag(); mp.framesize = 0; mp.num_frames = 0; mp.enc_delay = -1; mp.enc_padding = -1; mp.vbr_header = false; mp.header_parsed = false; mp.side_parsed = false; mp.data_parsed = false; mp.free_format = false; mp.old_free_format = false; mp.ssize = 0; mp.dsize = 0; mp.fsizeold = -1; mp.bsize = 0; mp.head = mp.tail = null; mp.fr.single = -1; mp.bsnum = 0; mp.wordpointer = mp.bsspace[mp.bsnum]; mp.wordpointerPos = 512; mp.bitindex = 0; mp.synth_bo = 1; mp.sync_bitstream = 1; tab.make_decode_tables(32767); layer3.init_layer3(MPG123.SBLIMIT); layer2.init_layer2(); return(mp); }
internal virtual int read_buf_byte(MPGLib.mpstr_tag mp) { int b; int pos; pos = mp.tail.pos; while (pos >= mp.tail.size) { remove_buf(mp); if (null == mp.tail) { throw new Exception("hip: Fatal error! tried to read past mp buffer"); } pos = mp.tail.pos; } b = mp.tail.pnt[pos] & 0xff; mp.bsize--; mp.tail.pos++; mp.total++; return(b); }
internal int getbits(MPGLib.mpstr_tag mp, int number_of_bits) { long rval; if (number_of_bits <= 0 || null == mp.wordpointer) { return(0); } { rval = mp.wordpointer[mp.wordpointerPos + 0] & 0xff; rval <<= 8; rval |= mp.wordpointer[mp.wordpointerPos + 1] & 0xff; rval <<= 8; rval |= mp.wordpointer[mp.wordpointerPos + 2] & 0xff; rval <<= mp.bitindex; rval &= 0xffffffL; mp.bitindex += number_of_bits; rval >>= 24 - number_of_bits; mp.wordpointerPos += mp.bitindex >> 3; mp.bitindex &= 7; } return((int)rval); }
internal virtual int audiodata_precedesframes(MPGLib.mpstr_tag mp) { if (mp.fr.lay == 3) { return(layer3.layer3_audiodata_precedesframes(mp)); } return (0); // For Layer 1 & 2 the audio data starts at the frame that describes it, so no audio data precedes. }
public virtual int synth_1to1_mono_ptr <X>( MPGLib.mpstr_tag mp, float[] @in, int inPos, X[] @out, MPGLib.ProcessedBytes p, Decode.Factory <X> tFactory) { return(outerInstance.decode.synth_1to1_mono(mp, @in, inPos, @out, p, tFactory)); }
public virtual int synth_1to1_ptr( MPGLib.mpstr_tag mp, float[] @in, int inPos, int i, T[] @out, MPGLib.ProcessedBytes p, Decode.Factory <T> tFactory) { return(outerInstance.decode.synth_1to1_unclipped(mp, @in, inPos, i, @out, p, tFactory)); }
internal virtual void ExitMP3(MPGLib.mpstr_tag mp) { MPGLib.buf b, bn; b = mp.tail; while (b != null) { b.pnt = null; bn = b.next; b = bn; } }
internal ISynthAnonymousInnerClass( Interface outerInstance, MPGLib.mpstr_tag mp, byte[] @in, T[] @out, Decode.Factory <T> tFactory) { this.outerInstance = outerInstance; this.mp = mp; this.@in = @in; this.@out = @out; this.tFactory = tFactory; }
internal virtual void read_head(MPGLib.mpstr_tag mp) { long head = read_buf_byte(mp); head <<= 8; head |= read_buf_byte(mp); head <<= 8; head |= read_buf_byte(mp); head <<= 8; head |= read_buf_byte(mp); mp.header = head; }
internal virtual void remove_buf(MPGLib.mpstr_tag mp) { var buf = mp.tail; mp.tail = buf.next; if (mp.tail != null) { mp.tail.prev = null; } else { mp.tail = mp.head = null; } buf.pnt = null; buf = null; }
internal virtual int do_layer1 <T>( MPGLib.mpstr_tag mp, T[] pcm_sample, MPGLib.ProcessedBytes pcm_point, Decode.Factory <T> tFactory) { var clip = 0; var balloc = new int[2 * MPG123.SBLIMIT]; var scale_index = new int[2 * MPG123.SBLIMIT]; var fraction = Arrays.ReturnRectangularArray <float>(2, MPG123.SBLIMIT); var fr = mp.fr; int i, stereo = fr.stereo; var single = fr.single; fr.jsbound = fr.mode == MPG123.MPG_MD_JOINT_STEREO ? (fr.mode_ext << 2) + 4 : 32; if (stereo == 1 || single == 3) { single = 0; } I_step_one(mp, balloc, scale_index, fr); for (i = 0; i < MPG123.SCALE_BLOCK; i++) { I_step_two(mp, fraction, balloc, scale_index, fr); if (single >= 0) { clip += decode.synth_1to1_mono(mp, fraction[single], 0, pcm_sample, pcm_point, tFactory); } else { var p1 = new MPGLib.ProcessedBytes(); p1.pb = pcm_point.pb; clip += decode.synth_1to1(mp, fraction[0], 0, 0, pcm_sample, p1, tFactory); clip += decode.synth_1to1(mp, fraction[1], 0, 1, pcm_sample, pcm_point, tFactory); } } return(clip); }
internal int getbits_fast(MPGLib.mpstr_tag mp, int number_of_bits) { long rval; { rval = mp.wordpointer[mp.wordpointerPos + 0] & 0xff; rval <<= 8; rval |= mp.wordpointer[mp.wordpointerPos + 1] & 0xff; rval <<= mp.bitindex; rval &= 0xffffL; mp.bitindex += number_of_bits; rval >>= 16 - number_of_bits; mp.wordpointerPos += mp.bitindex >> 3; mp.bitindex &= 7; } return((int)rval); }
internal int set_pointer(MPGLib.mpstr_tag mp, int backstep) { if (mp.fsizeold < 0 && backstep > 0) { return(MPGLib.MP3_ERR); } var bsbufold = mp.bsspace[1 - mp.bsnum]; var bsbufoldPos = 512; mp.wordpointerPos -= backstep; if (backstep != 0) { Array.Copy(bsbufold, bsbufoldPos + mp.fsizeold - backstep, mp.wordpointer, mp.wordpointerPos, backstep); } mp.bitindex = 0; return(MPGLib.MP3_OK); }
internal virtual int decodeMP3 <T>( MPGLib.mpstr_tag mp, byte[] @in, int bufferPos, int isize, T[] @out, int osize, MPGLib.ProcessedBytes done, Decode.Factory <T> tFactory) { if (osize < 2304) { Console.WriteLine("hip: Insufficient memory for decoding buffer %d\n", osize); return(MPGLib.MP3_ERR); } /* passing pointers to the functions which clip the samples */ ISynth synth = new ISynthAnonymousInnerClass <T>(this, mp, @in, @out, tFactory); return(decodeMP3_clipchoice(mp, @in, bufferPos, isize, @out, done, synth, tFactory)); }
internal virtual int decodeMP3 <T>( MPGLib.mpstr_tag mp, byte[] @in, int bufferPos, int isize, T[] @out, int osize, MPGLib.ProcessedBytes done, Decode.Factory <T> tFactory, bool seek) { if (osize < 2304) { return(MPGLib.MP3_ERR); } /* passing pointers to the functions which clip the samples */ ISynth <T> synth = new ISynthAnonymousInnerClass <T>(this, mp, @in, @out, tFactory); return(decodeMP3_clipchoice(mp, @in, bufferPos, isize, @out, done, synth, tFactory, seek)); }
internal virtual int decodeMP3_unclipped <T>( MPGLib.mpstr_tag mp, byte[] @in, int bufferPos, int isize, T[] @out, int osize, MPGLib.ProcessedBytes done, Decode.Factory <T> tFactory) { /* we forbid input with more than 1152 samples per channel for output in unclipped mode */ if (osize < 1152 * 2) { Console.WriteLine("hip: out space too small for unclipped mode\n"); return(MPGLib.MP3_ERR); } ISynth synth = new ISynthAnonymousInnerClass2 <T>(this, mp, @in, @out, tFactory); /* passing pointers to the functions which don't clip the samples */ return(decodeMP3_clipchoice(mp, @in, bufferPos, isize, @out, done, synth, tFactory)); }
private void I_step_one(MPGLib.mpstr_tag mp, int[] balloc, int[] scale_index, Frame fr) { var ba = 0; var sca = 0; Debug.Assert(fr.stereo == 1 || fr.stereo == 2); if (fr.stereo == 2) { int i; var jsbound = fr.jsbound; for (i = 0; i < jsbound; i++) { balloc[ba++] = common.getbits(mp, 4); balloc[ba++] = common.getbits(mp, 4); } for (i = jsbound; i < MPG123.SBLIMIT; i++) { balloc[ba++] = common.getbits(mp, 4); } ba = 0; for (i = 0; i < jsbound; i++) { if (balloc[ba]++ != 0) { scale_index[sca++] = common.getbits(mp, 6); } if (balloc[ba++] != 0) { scale_index[sca++] = common.getbits(mp, 6); } } for (i = jsbound; i < MPG123.SBLIMIT; i++) { if (balloc[ba++] != 0) { scale_index[sca++] = common.getbits(mp, 6); scale_index[sca++] = common.getbits(mp, 6); } } } else { int i; for (i = 0; i < MPG123.SBLIMIT; i++) { balloc[ba++] = common.getbits(mp, 4); } ba = 0; for (i = 0; i < MPG123.SBLIMIT; i++) { if (balloc[ba++] != 0) { scale_index[sca++] = common.getbits(mp, 6); } } } }
private void I_step_two(MPGLib.mpstr_tag mp, float[][] fraction, int[] balloc, int[] scale_index, Frame fr) { int i, n; var smpb = new int[2 * MPG123.SBLIMIT]; // values: 0-65535 int sample; var ba = 0; var sca = 0; Debug.Assert(fr.stereo == 1 || fr.stereo == 2); if (fr.stereo == 2) { var jsbound = fr.jsbound; var f0 = 0; var f1 = 0; ba = 0; for (sample = 0, i = 0; i < jsbound; i++) { n = balloc[ba++]; if (n != 0) { smpb[sample++] = common.getbits(mp, n + 1); } n = balloc[ba++]; if (n != 0) { smpb[sample++] = common.getbits(mp, n + 1); } } for (i = jsbound; i < MPG123.SBLIMIT; i++) { n = balloc[ba++]; if (n != 0) { smpb[sample++] = common.getbits(mp, n + 1); } } ba = 0; for (sample = 0, i = 0; i < jsbound; i++) { n = balloc[ba++]; if (n != 0) { fraction[0][f0++] = ((-1 << n) + smpb[sample++] + 1) * common.muls[n + 1][scale_index[sca++]]; } else { fraction[0][f0++] = 0.0f; } n = balloc[ba++]; if (n != 0) { fraction[1][f1++] = ((-1 << n) + smpb[sample++] + 1) * common.muls[n + 1][scale_index[sca++]]; } else { fraction[1][f1++] = 0.0f; } } for (i = jsbound; i < MPG123.SBLIMIT; i++) { n = balloc[ba++]; if (n != 0) { var samp = (float)((-1 << n) + smpb[sample++] + 1); fraction[0][f0++] = samp * common.muls[n + 1][scale_index[sca++]]; fraction[1][f1++] = samp * common.muls[n + 1][scale_index[sca++]]; } else { fraction[0][f0++] = fraction[1][f1++] = 0.0f; } } for (i = fr.down_sample_sblimit; i < 32; i++) { fraction[0][i] = fraction[1][i] = 0.0f; } } else { var f0 = 0; ba = 0; for (sample = 0, i = 0; i < MPG123.SBLIMIT; i++) { n = balloc[ba++]; if (n != 0) { smpb[sample++] = common.getbits(mp, n + 1); } } ba = 0; for (sample = 0, i = 0; i < MPG123.SBLIMIT; i++) { n = balloc[ba++]; if (n != 0) { fraction[0][f0++] = ((-1 << n) + smpb[sample++] + 1) * common.muls[n + 1][scale_index[sca++]]; } else { fraction[0][f0++] = 0.0f; } } for (i = fr.down_sample_sblimit; i < 32; i++) { fraction[0][i] = 0.0f; } } }
internal virtual int decodeMP3_clipchoice <T>( MPGLib.mpstr_tag mp, byte[] @in, int inPos, int isize, T[] @out, MPGLib.ProcessedBytes done, ISynth synth, Decode.Factory <T> tFactory) { int i, iret, bits, bytes; if (@in != null && isize != 0 && addbuf(mp, @in, inPos, isize) == null) { return(MPGLib.MP3_ERR); } /* First decode header */ if (!mp.header_parsed) { if (mp.fsizeold == -1 || mp.sync_bitstream != 0) { int vbrbytes; mp.sync_bitstream = 0; /* This is the very first call. sync with anything */ /* bytes= number of bytes before header */ bytes = sync_buffer(mp, false); /* now look for Xing VBR header */ if (mp.bsize >= bytes + XING_HEADER_SIZE) { vbrbytes = check_vbr_header(mp, bytes); } else { return(MPGLib.MP3_NEED_MORE); } if (mp.vbr_header) { /* do we have enough data to parse entire Xing header? */ if (bytes + vbrbytes > mp.bsize) { return(MPGLib.MP3_NEED_MORE); } /* read in Xing header. Buffer data in case it * is used by a non zero main_data_begin for the next * frame, but otherwise dont decode Xing header */ // #ifdef HIP_DEBUG // fprintf(stderr, "hip: found xing header, skipping %i bytes\n", vbrbytes + bytes); // #endif for (i = 0; i < vbrbytes + bytes; ++i) { read_buf_byte(mp); } /* now we need to find another syncword */ /* just return and make user send in more data */ return(MPGLib.MP3_NEED_MORE); } } else { /* match channels, samplerate, etc, when syncing */ bytes = sync_buffer(mp, true); } /* buffer now synchronized */ if (bytes < 0) { return(MPGLib.MP3_NEED_MORE); } if (bytes > 0) { /* there were some extra bytes in front of header. * bitstream problem, but we are now resynced * should try to buffer previous data in case new * frame has nonzero main_data_begin, but we need * to make sure we do not overflow buffer */ int size; Console.WriteLine("hip: bitstream problem, resyncing skipping %d bytes...\n", bytes); mp.old_free_format = false; /* FIXME: correct ??? */ mp.sync_bitstream = 1; /* skip some bytes, buffer the rest */ size = mp.wordpointerPos - 512; if (size > MPG123.MAXFRAMESIZE) { /* wordpointer buffer is trashed. probably cant recover, but try anyway */ Console.WriteLine( "hip: wordpointer trashed. size=%i (%i) bytes=%i \n", size, MPG123.MAXFRAMESIZE, bytes); size = 0; mp.wordpointer = mp.bsspace[mp.bsnum]; mp.wordpointerPos = 512; } /* buffer contains 'size' data right now * we want to add 'bytes' worth of data, but do not * exceed MAXFRAMESIZE, so we through away 'i' bytes */ i = size + bytes - MPG123.MAXFRAMESIZE; for (; i > 0; --i) { --bytes; read_buf_byte(mp); } copy_mp(mp, bytes, mp.wordpointer, mp.wordpointerPos); mp.fsizeold += bytes; } read_head(mp); common.decode_header(mp.fr, mp.header); mp.header_parsed = true; mp.framesize = mp.fr.framesize; mp.free_format = mp.framesize == 0; if (mp.fr.lsf != 0) { mp.ssize = mp.fr.stereo == 1 ? 9 : 17; } else { mp.ssize = mp.fr.stereo == 1 ? 17 : 32; } if (mp.fr.error_protection) { mp.ssize += 2; } mp.bsnum = 1 - mp.bsnum; // toggle buffer mp.wordpointer = mp.bsspace[mp.bsnum]; mp.wordpointerPos = 512; mp.bitindex = 0; /* for very first header, never parse rest of data */ if (mp.fsizeold == -1) { return(MPGLib.MP3_NEED_MORE); } } // end of header parsing block /* now decode side information */ if (!mp.side_parsed) { /* Layer 3 only */ if (mp.fr.lay == 3) { if (mp.bsize < mp.ssize) { return(MPGLib.MP3_NEED_MORE); } copy_mp(mp, mp.ssize, mp.wordpointer, mp.wordpointerPos); if (mp.fr.error_protection) { common.getbits(mp, 16); } bits = layer3.do_layer3_sideinfo(mp); /* bits = actual number of bits needed to parse this frame */ /* can be negative, if all bits needed are in the reservoir */ if (bits < 0) { bits = 0; } /* read just as many bytes as necessary before decoding */ mp.dsize = (bits + 7) / 8; // #ifdef HIP_DEBUG // fprintf(stderr, // "hip: %d bits needed to parse layer III frame, number of bytes to read before decoding dsize = %d\n", // bits, mp.dsize); // #endif /* this will force mpglib to read entire frame before decoding */ /* mp.dsize= mp.framesize - mp.ssize; */ } else { /* Layers 1 and 2 */ /* check if there is enough input data */ if (mp.fr.framesize > mp.bsize) { return(MPGLib.MP3_NEED_MORE); } /* takes care that the right amount of data is copied into wordpointer */ mp.dsize = mp.fr.framesize; mp.ssize = 0; } mp.side_parsed = true; } /* now decode main data */ iret = MPGLib.MP3_NEED_MORE; if (!mp.data_parsed) { if (mp.dsize > mp.bsize) { return(MPGLib.MP3_NEED_MORE); } copy_mp(mp, mp.dsize, mp.wordpointer, mp.wordpointerPos); done.pb = 0; /*do_layer3(&mp.fr,(unsigned char *) out,done); */ switch (mp.fr.lay) { case 1: if (mp.fr.error_protection) { common.getbits(mp, 16); } layer1.do_layer1(mp, @out, done, tFactory); break; case 2: if (mp.fr.error_protection) { common.getbits(mp, 16); } layer2.do_layer2(mp, @out, done, synth, tFactory); break; case 3: layer3.do_layer3(mp, @out, done, synth, tFactory); break; default: Console.WriteLine("hip: invalid layer %d\n", mp.fr.lay); break; } mp.wordpointer = mp.bsspace[mp.bsnum]; mp.wordpointerPos = 512 + mp.ssize + mp.dsize; mp.data_parsed = true; iret = MPGLib.MP3_OK; } /* remaining bits are ancillary data, or reservoir for next frame * If free format, scan stream looking for next frame to determine * mp.framesize */ if (mp.free_format) { if (mp.old_free_format) { /* free format. bitrate must not vary */ mp.framesize = mp.fsizeold_nopadding + mp.fr.padding; } else { bytes = sync_buffer(mp, true); if (bytes < 0) { return(iret); } mp.framesize = bytes + mp.ssize + mp.dsize; mp.fsizeold_nopadding = mp.framesize - mp.fr.padding; /* * fprintf(stderr,"hip: freeformat bitstream: estimated bitrate=%ikbs \n", * 8*(4+mp.framesize)*freqs[mp.fr.sampling_frequency]/ * (1000*576*(2-mp.fr.lsf))); */ } } /* buffer the ancillary data and reservoir for next frame */ bytes = mp.framesize - (mp.ssize + mp.dsize); if (bytes > mp.bsize) { return(iret); } if (bytes > 0) { int size; copy_mp(mp, bytes, mp.wordpointer, mp.wordpointerPos); mp.wordpointerPos += bytes; size = mp.wordpointerPos - 512; if (size > MPG123.MAXFRAMESIZE) { Console.WriteLine("hip: fatal error. MAXFRAMESIZE not large enough.\n"); } } /* the above frame is completely parsed. start looking for next frame */ mp.fsizeold = mp.framesize; mp.old_free_format = mp.free_format; mp.framesize = 0; mp.header_parsed = false; mp.side_parsed = false; mp.data_parsed = false; return(iret); }
/* * traverse mp data structure without changing it * (just like sync_buffer) * pull out Xing bytes * call vbr header check code from LAME * if we find a header, parse it and also compute the VBR header size * if no header, do nothing. * * bytes = number of bytes before MPEG header. skip this many bytes * before starting to read * return value: number of bytes in VBR header, including syncword */ internal virtual int check_vbr_header(MPGLib.mpstr_tag mp, int bytes) { int i, pos; var buf = mp.tail; var xing = new byte[XING_HEADER_SIZE]; pos = buf.pos; /* skip to valid header */ for (i = 0; i < bytes; ++i) { while (pos >= buf.size) { buf = buf.next; if (null == buf) { return(-1); // fatal error } pos = buf.pos; } ++pos; } /* now read header */ for (i = 0; i < XING_HEADER_SIZE; ++i) { while (pos >= buf.size) { buf = buf.next; if (null == buf) { return(-1); // fatal error } pos = buf.pos; } xing[i] = buf.pnt[pos]; ++pos; } /* check first bytes for Xing header */ var pTagData = vbr.getVbrTag(xing); mp.vbr_header = pTagData != null; if (mp.vbr_header) { mp.num_frames = pTagData.frames; mp.enc_delay = pTagData.encDelay; mp.enc_padding = pTagData.encPadding; /* fprintf(stderr,"hip: delays: %i %i \n",mp.enc_delay,mp.enc_padding); */ /* fprintf(stderr,"hip: Xing VBR header dectected. MP3 file has %i frames\n", pTagData.frames); */ if (pTagData.headersize < 1) { return(1); } return(pTagData.headersize); } return(0); }
internal virtual int sync_buffer(MPGLib.mpstr_tag mp, bool free_match) { /* traverse mp structure without modifying pointers, looking * for a frame valid header. * if free_format, valid header must also have the same * samplerate. * return number of bytes in mp, before the header * return -1 if header is not found */ var b = new[] { 0, 0, 0, 0 }; int i, pos; bool h; var buf = mp.tail; if (null == buf) { return(-1); } pos = buf.pos; for (i = 0; i < mp.bsize; i++) { /* get 4 bytes */ b[0] = b[1]; b[1] = b[2]; b[2] = b[3]; while (pos >= buf.size) { buf = buf.next; pos = buf.pos; } b[3] = buf.pnt[pos] & 0xff; ++pos; if (i >= 3) { var fr = mp.fr; long head; head = b[0]; head <<= 8; head |= b[1]; head <<= 8; head |= b[2]; head <<= 8; head |= b[3]; h = common.head_check(head, fr.lay); if (h && free_match) { /* just to be even more thorough, match the sample rate */ int mode, stereo, sampling_frequency, lsf; bool mpeg25; if ((head & (1 << 20)) != 0) { lsf = (head & (1 << 19)) != 0 ? 0x0 : 0x1; mpeg25 = false; } else { lsf = 1; mpeg25 = true; } mode = (int)((head >> 6) & 0x3); stereo = mode == MPG123.MPG_MD_MONO ? 1 : 2; if (mpeg25) { sampling_frequency = (int)(6 + ((head >> 10) & 0x3)); } else { sampling_frequency = (int)(((head >> 10) & 0x3) + lsf * 3); } h = stereo == fr.stereo && lsf == fr.lsf && mpeg25 == fr.mpeg25 && sampling_frequency == fr.sampling_frequency; } if (h) { return(i - 3); } } } return(-1); }