var common = require('./common.js'); var System = common.System; var VbrMode = common.VbrMode; var Float = common.Float; var ShortBlock = common.ShortBlock; var Util = common.Util; var Arrays = common.Arrays; var new_array_n = common.new_array_n; var new_byte = common.new_byte; var new_double = common.new_double; var new_float = common.new_float; var new_float_n = common.new_float_n; var new_int = common.new_int; var new_int_n = common.new_int_n; var assert = common.assert; var Takehiro = require('./Takehiro.js'); var Tables = require('./Tables.js'); var Encoder = require('./Encoder.js'); var LameInternalFlags = require('./LameInternalFlags.js'); BitStream.EQ = function (a, b) { return (Math.abs(a) > Math.abs(b)) ? (Math.abs((a) - (b)) <= (Math .abs(a) * 1e-6)) : (Math.abs((a) - (b)) <= (Math.abs(b) * 1e-6)); }; BitStream.NEQ = function (a, b) { return !BitStream.EQ(a, b); }; function BitStream () { var Lame = require('./Lame.js'); var self = this; var CRC16_POLYNOMIAL = 0x8005; /* * we work with ints, so when doing bit manipulation, we limit ourselves to * MAX_LENGTH-2 just to be on the safe side */ var MAX_LENGTH = 32; //GainAnalysis ga; //MPGLib mpg; //Version ver; //VBRTag vbr; var ga = null; var mpg = null; var ver = null; var vbr = null; //public final void setModules(GainAnalysis ga, MPGLib mpg, Version ver, // VBRTag vbr) { this.setModules = function (_ga, _mpg, _ver, _vbr) { ga = _ga; mpg = _mpg; ver = _ver; vbr = _vbr; }; /** * Bit stream buffer. */ //private byte[] buf; var buf = null; /** * Bit counter of bit stream. */ var totbit = 0; /** * Pointer to top byte in buffer. */ var bufByteIdx = 0; /** * Pointer to top bit of top byte in buffer. */ var bufBitIdx = 0; /** * compute bitsperframe and mean_bits for a layer III frame */ this.getframebits = function (gfp) { var gfc = gfp.internal_flags; var bit_rate; /* get bitrate in kbps [?] */ if (gfc.bitrate_index != 0) bit_rate = Tables.bitrate_table[gfp.version][gfc.bitrate_index]; else bit_rate = gfp.brate; assert(8 <= bit_rate && bit_rate <= 640); /* main encoding routine toggles padding on and off */ /* one Layer3 Slot consists of 8 bits */ var bytes = 0 | (gfp.version + 1) * 72000 * bit_rate / gfp.out_samplerate + gfc.padding; return 8 * bytes; }; function putheader_bits (gfc) { System.arraycopy(gfc.header[gfc.w_ptr].buf, 0, buf, bufByteIdx, gfc.sideinfo_len); bufByteIdx += gfc.sideinfo_len; totbit += gfc.sideinfo_len * 8; gfc.w_ptr = (gfc.w_ptr + 1) & (LameInternalFlags.MAX_HEADER_BUF - 1); } /** * write j bits into the bit stream */ function putbits2 (gfc, val, j) { assert(j < MAX_LENGTH - 2); while (j > 0) { var k; if (bufBitIdx == 0) { bufBitIdx = 8; bufByteIdx++; assert(bufByteIdx < Lame.LAME_MAXMP3BUFFER); assert(gfc.header[gfc.w_ptr].write_timing >= totbit); if (gfc.header[gfc.w_ptr].write_timing == totbit) { putheader_bits(gfc); } buf[bufByteIdx] = 0; } k = Math.min(j, bufBitIdx); j -= k; bufBitIdx -= k; assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */ assert(bufBitIdx < MAX_LENGTH); buf[bufByteIdx] |= ((val >> j) << bufBitIdx); totbit += k; } } /** * write j bits into the bit stream, ignoring frame headers */ function putbits_noheaders (gfc, val, j) { assert(j < MAX_LENGTH - 2); while (j > 0) { var k; if (bufBitIdx == 0) { bufBitIdx = 8; bufByteIdx++; assert(bufByteIdx < Lame.LAME_MAXMP3BUFFER); buf[bufByteIdx] = 0; } k = Math.min(j, bufBitIdx); j -= k; bufBitIdx -= k; assert(j < MAX_LENGTH); /* 32 too large on 32 bit machines */ assert(bufBitIdx < MAX_LENGTH); buf[bufByteIdx] |= ((val >> j) << bufBitIdx); totbit += k; } } /** * Some combinations of bitrate, Fs, and stereo make it impossible to stuff * out a frame using just main_data, due to the limited number of bits to * indicate main_data_length. In these situations, we put stuffing bits into * the ancillary data... */ function drain_into_ancillary (gfp, remainingBits) { var gfc = gfp.internal_flags; var i; assert(remainingBits >= 0); if (remainingBits >= 8) { putbits2(gfc, 0x4c, 8); remainingBits -= 8; } if (remainingBits >= 8) { putbits2(gfc, 0x41, 8); remainingBits -= 8; } if (remainingBits >= 8) { putbits2(gfc, 0x4d, 8); remainingBits -= 8; } if (remainingBits >= 8) { putbits2(gfc, 0x45, 8); remainingBits -= 8; } if (remainingBits >= 32) { var version = ver.getLameShortVersion(); if (remainingBits >= 32) for (i = 0; i < version.length && remainingBits >= 8; ++i) { remainingBits -= 8; putbits2(gfc, version.charAt(i), 8); } } for (; remainingBits >= 1; remainingBits -= 1) { putbits2(gfc, gfc.ancillary_flag, 1); gfc.ancillary_flag ^= (!gfp.disable_reservoir ? 1 : 0); } assert(remainingBits == 0); } /** * write N bits into the header */ function writeheader (gfc, val, j) { var ptr = gfc.header[gfc.h_ptr].ptr; while (j > 0) { var k = Math.min(j, 8 - (ptr & 7)); j -= k; assert(j < MAX_LENGTH); /* >> 32 too large for 32 bit machines */ gfc.header[gfc.h_ptr].buf[ptr >> 3] |= ((val >> j)) << (8 - (ptr & 7) - k); ptr += k; } gfc.header[gfc.h_ptr].ptr = ptr; } function CRC_update (value, crc) { value <<= 8; for (var i = 0; i < 8; i++) { value <<= 1; crc <<= 1; if ((((crc ^ value) & 0x10000) != 0)) crc ^= CRC16_POLYNOMIAL; } return crc; } this.CRC_writeheader = function (gfc, header) { var crc = 0xffff; /* (jo) init crc16 for error_protection */ crc = CRC_update(header[2] & 0xff, crc); crc = CRC_update(header[3] & 0xff, crc); for (var i = 6; i < gfc.sideinfo_len; i++) { crc = CRC_update(header[i] & 0xff, crc); } header[4] = (byte)(crc >> 8); header[5] = (byte)(crc & 255); }; function encodeSideInfo2 (gfp, bitsPerFrame) { var gfc = gfp.internal_flags; var l3_side; var gr, ch; l3_side = gfc.l3_side; gfc.header[gfc.h_ptr].ptr = 0; Arrays.fill(gfc.header[gfc.h_ptr].buf, 0, gfc.sideinfo_len, 0); if (gfp.out_samplerate < 16000) writeheader(gfc, 0xffe, 12); else writeheader(gfc, 0xfff, 12); writeheader(gfc, (gfp.version), 1); writeheader(gfc, 4 - 3, 2); writeheader(gfc, (!gfp.error_protection ? 1 : 0), 1); writeheader(gfc, (gfc.bitrate_index), 4); writeheader(gfc, (gfc.samplerate_index), 2); writeheader(gfc, (gfc.padding), 1); writeheader(gfc, (gfp.extension), 1); writeheader(gfc, (gfp.mode.ordinal()), 2); writeheader(gfc, (gfc.mode_ext), 2); writeheader(gfc, (gfp.copyright), 1); writeheader(gfc, (gfp.original), 1); writeheader(gfc, (gfp.emphasis), 2); if (gfp.error_protection) { writeheader(gfc, 0, 16); /* dummy */ } if (gfp.version == 1) { /* MPEG1 */ assert(l3_side.main_data_begin >= 0); writeheader(gfc, (l3_side.main_data_begin), 9); if (gfc.channels_out == 2) writeheader(gfc, l3_side.private_bits, 3); else writeheader(gfc, l3_side.private_bits, 5); for (ch = 0; ch < gfc.channels_out; ch++) { var band; for (band = 0; band < 4; band++) { writeheader(gfc, l3_side.scfsi[ch][band], 1); } } for (gr = 0; gr < 2; gr++) { for (ch = 0; ch < gfc.channels_out; ch++) { var gi = l3_side.tt[gr][ch]; writeheader(gfc, gi.part2_3_length + gi.part2_length, 12); writeheader(gfc, gi.big_values / 2, 9); writeheader(gfc, gi.global_gain, 8); writeheader(gfc, gi.scalefac_compress, 4); if (gi.block_type != Encoder.NORM_TYPE) { writeheader(gfc, 1, 1); /* window_switching_flag */ writeheader(gfc, gi.block_type, 2); writeheader(gfc, gi.mixed_block_flag, 1); if (gi.table_select[0] == 14) gi.table_select[0] = 16; writeheader(gfc, gi.table_select[0], 5); if (gi.table_select[1] == 14) gi.table_select[1] = 16; writeheader(gfc, gi.table_select[1], 5); writeheader(gfc, gi.subblock_gain[0], 3); writeheader(gfc, gi.subblock_gain[1], 3); writeheader(gfc, gi.subblock_gain[2], 3); } else { writeheader(gfc, 0, 1); /* window_switching_flag */ if (gi.table_select[0] == 14) gi.table_select[0] = 16; writeheader(gfc, gi.table_select[0], 5); if (gi.table_select[1] == 14) gi.table_select[1] = 16; writeheader(gfc, gi.table_select[1], 5); if (gi.table_select[2] == 14) gi.table_select[2] = 16; writeheader(gfc, gi.table_select[2], 5); assert(0 <= gi.region0_count && gi.region0_count < 16); assert(0 <= gi.region1_count && gi.region1_count < 8); writeheader(gfc, gi.region0_count, 4); writeheader(gfc, gi.region1_count, 3); } writeheader(gfc, gi.preflag, 1); writeheader(gfc, gi.scalefac_scale, 1); writeheader(gfc, gi.count1table_select, 1); } } } else { /* MPEG2 */ assert(l3_side.main_data_begin >= 0); writeheader(gfc, (l3_side.main_data_begin), 8); writeheader(gfc, l3_side.private_bits, gfc.channels_out); gr = 0; for (ch = 0; ch < gfc.channels_out; ch++) { var gi = l3_side.tt[gr][ch]; writeheader(gfc, gi.part2_3_length + gi.part2_length, 12); writeheader(gfc, gi.big_values / 2, 9); writeheader(gfc, gi.global_gain, 8); writeheader(gfc, gi.scalefac_compress, 9); if (gi.block_type != Encoder.NORM_TYPE) { writeheader(gfc, 1, 1); /* window_switching_flag */ writeheader(gfc, gi.block_type, 2); writeheader(gfc, gi.mixed_block_flag, 1); if (gi.table_select[0] == 14) gi.table_select[0] = 16; writeheader(gfc, gi.table_select[0], 5); if (gi.table_select[1] == 14) gi.table_select[1] = 16; writeheader(gfc, gi.table_select[1], 5); writeheader(gfc, gi.subblock_gain[0], 3); writeheader(gfc, gi.subblock_gain[1], 3); writeheader(gfc, gi.subblock_gain[2], 3); } else { writeheader(gfc, 0, 1); /* window_switching_flag */ if (gi.table_select[0] == 14) gi.table_select[0] = 16; writeheader(gfc, gi.table_select[0], 5); if (gi.table_select[1] == 14) gi.table_select[1] = 16; writeheader(gfc, gi.table_select[1], 5); if (gi.table_select[2] == 14) gi.table_select[2] = 16; writeheader(gfc, gi.table_select[2], 5); assert(0 <= gi.region0_count && gi.region0_count < 16); assert(0 <= gi.region1_count && gi.region1_count < 8); writeheader(gfc, gi.region0_count, 4); writeheader(gfc, gi.region1_count, 3); } writeheader(gfc, gi.scalefac_scale, 1); writeheader(gfc, gi.count1table_select, 1); } } if (gfp.error_protection) { /* (jo) error_protection: add crc16 information to header */ CRC_writeheader(gfc, gfc.header[gfc.h_ptr].buf); } { var old = gfc.h_ptr; assert(gfc.header[old].ptr == gfc.sideinfo_len * 8); gfc.h_ptr = (old + 1) & (LameInternalFlags.MAX_HEADER_BUF - 1); gfc.header[gfc.h_ptr].write_timing = gfc.header[old].write_timing + bitsPerFrame; if (gfc.h_ptr == gfc.w_ptr) { /* yikes! we are out of header buffer space */ System.err .println("Error: MAX_HEADER_BUF too small in bitstream.c \n"); } } } function huffman_coder_count1 (gfc, gi) { /* Write count1 area */ var h = Tables.ht[gi.count1table_select + 32]; var i, bits = 0; var ix = gi.big_values; var xr = gi.big_values; assert(gi.count1table_select < 2); for (i = (gi.count1 - gi.big_values) / 4; i > 0; --i) { var huffbits = 0; var p = 0, v; v = gi.l3_enc[ix + 0]; if (v != 0) { p += 8; if (gi.xr[xr + 0] < 0) huffbits++; assert(v <= 1); } v = gi.l3_enc[ix + 1]; if (v != 0) { p += 4; huffbits *= 2; if (gi.xr[xr + 1] < 0) huffbits++; assert(v <= 1); } v = gi.l3_enc[ix + 2]; if (v != 0) { p += 2; huffbits *= 2; if (gi.xr[xr + 2] < 0) huffbits++; assert(v <= 1); } v = gi.l3_enc[ix + 3]; if (v != 0) { p++; huffbits *= 2; if (gi.xr[xr + 3] < 0) huffbits++; assert(v <= 1); } ix += 4; xr += 4; putbits2(gfc, huffbits + h.table[p], h.hlen[p]); bits += h.hlen[p]; } return bits; } /** * Implements the pseudocode of page 98 of the IS */ function Huffmancode (gfc, tableindex, start, end, gi) { var h = Tables.ht[tableindex]; var bits = 0; assert(tableindex < 32); if (0 == tableindex) return bits; for (var i = start; i < end; i += 2) { var cbits = 0; var xbits = 0; var linbits = h.xlen; var xlen = h.xlen; var ext = 0; var x1 = gi.l3_enc[i]; var x2 = gi.l3_enc[i + 1]; if (x1 != 0) { if (gi.xr[i] < 0) ext++; cbits--; } if (tableindex > 15) { /* use ESC-words */ if (x1 > 14) { var linbits_x1 = x1 - 15; assert(linbits_x1 <= h.linmax); ext |= linbits_x1 << 1; xbits = linbits; x1 = 15; } if (x2 > 14) { var linbits_x2 = x2 - 15; assert(linbits_x2 <= h.linmax); ext <<= linbits; ext |= linbits_x2; xbits += linbits; x2 = 15; } xlen = 16; } if (x2 != 0) { ext <<= 1; if (gi.xr[i + 1] < 0) ext++; cbits--; } assert((x1 | x2) < 16); x1 = x1 * xlen + x2; xbits -= cbits; cbits += h.hlen[x1]; assert(cbits <= MAX_LENGTH); assert(xbits <= MAX_LENGTH); putbits2(gfc, h.table[x1], cbits); putbits2(gfc, ext, xbits); bits += cbits + xbits; } return bits; } /** * Note the discussion of huffmancodebits() on pages 28 and 29 of the IS, as * well as the definitions of the side information on pages 26 and 27. */ function ShortHuffmancodebits (gfc, gi) { var region1Start = 3 * gfc.scalefac_band.s[3]; if (region1Start > gi.big_values) region1Start = gi.big_values; /* short blocks do not have a region2 */ var bits = Huffmancode(gfc, gi.table_select[0], 0, region1Start, gi); bits += Huffmancode(gfc, gi.table_select[1], region1Start, gi.big_values, gi); return bits; } function LongHuffmancodebits (gfc, gi) { var bigvalues, bits; var region1Start, region2Start; bigvalues = gi.big_values; assert(0 <= bigvalues && bigvalues <= 576); var i = gi.region0_count + 1; assert(0 <= i); assert(i < gfc.scalefac_band.l.length); region1Start = gfc.scalefac_band.l[i]; i += gi.region1_count + 1; assert(0 <= i); assert(i < gfc.scalefac_band.l.length); region2Start = gfc.scalefac_band.l[i]; if (region1Start > bigvalues) region1Start = bigvalues; if (region2Start > bigvalues) region2Start = bigvalues; bits = Huffmancode(gfc, gi.table_select[0], 0, region1Start, gi); bits += Huffmancode(gfc, gi.table_select[1], region1Start, region2Start, gi); bits += Huffmancode(gfc, gi.table_select[2], region2Start, bigvalues, gi); return bits; } function writeMainData (gfp) { var gr, ch, sfb, data_bits, tot_bits = 0; var gfc = gfp.internal_flags; var l3_side = gfc.l3_side; if (gfp.version == 1) { /* MPEG 1 */ for (gr = 0; gr < 2; gr++) { for (ch = 0; ch < gfc.channels_out; ch++) { var gi = l3_side.tt[gr][ch]; var slen1 = Takehiro.slen1_tab[gi.scalefac_compress]; var slen2 = Takehiro.slen2_tab[gi.scalefac_compress]; data_bits = 0; for (sfb = 0; sfb < gi.sfbdivide; sfb++) { if (gi.scalefac[sfb] == -1) continue; /* scfsi is used */ putbits2(gfc, gi.scalefac[sfb], slen1); data_bits += slen1; } for (; sfb < gi.sfbmax; sfb++) { if (gi.scalefac[sfb] == -1) continue; /* scfsi is used */ putbits2(gfc, gi.scalefac[sfb], slen2); data_bits += slen2; } assert(data_bits == gi.part2_length); if (gi.block_type == Encoder.SHORT_TYPE) { data_bits += ShortHuffmancodebits(gfc, gi); } else { data_bits += LongHuffmancodebits(gfc, gi); } data_bits += huffman_coder_count1(gfc, gi); /* does bitcount in quantize.c agree with actual bit count? */ assert(data_bits == gi.part2_3_length + gi.part2_length); tot_bits += data_bits; } /* for ch */ } /* for gr */ } else { /* MPEG 2 */ gr = 0; for (ch = 0; ch < gfc.channels_out; ch++) { var gi = l3_side.tt[gr][ch]; var i, sfb_partition, scale_bits = 0; assert(gi.sfb_partition_table != null); data_bits = 0; sfb = 0; sfb_partition = 0; if (gi.block_type == Encoder.SHORT_TYPE) { for (; sfb_partition < 4; sfb_partition++) { var sfbs = gi.sfb_partition_table[sfb_partition] / 3; var slen = gi.slen[sfb_partition]; for (i = 0; i < sfbs; i++, sfb++) { putbits2(gfc, Math.max(gi.scalefac[sfb * 3 + 0], 0), slen); putbits2(gfc, Math.max(gi.scalefac[sfb * 3 + 1], 0), slen); putbits2(gfc, Math.max(gi.scalefac[sfb * 3 + 2], 0), slen); scale_bits += 3 * slen; } } data_bits += ShortHuffmancodebits(gfc, gi); } else { for (; sfb_partition < 4; sfb_partition++) { var sfbs = gi.sfb_partition_table[sfb_partition]; var slen = gi.slen[sfb_partition]; for (i = 0; i < sfbs; i++, sfb++) { putbits2(gfc, Math.max(gi.scalefac[sfb], 0), slen); scale_bits += slen; } } data_bits += LongHuffmancodebits(gfc, gi); } data_bits += huffman_coder_count1(gfc, gi); /* does bitcount in quantize.c agree with actual bit count? */ assert(data_bits == gi.part2_3_length); assert(scale_bits == gi.part2_length); tot_bits += scale_bits + data_bits; } /* for ch */ } /* for gf */ return tot_bits; } /* main_data */ function TotalBytes () { this.total = 0; } /* * compute the number of bits required to flush all mp3 frames currently in * the buffer. This should be the same as the reservoir size. Only call this * routine between frames - i.e. only after all headers and data have been * added to the buffer by format_bitstream(). * * Also compute total_bits_output = size of mp3 buffer (including frame * headers which may not have yet been send to the mp3 buffer) + number of * bits needed to flush all mp3 frames. * * total_bytes_output is the size of the mp3 output buffer if * lame_encode_flush_nogap() was called right now. */ function compute_flushbits (gfp, total_bytes_output) { var gfc = gfp.internal_flags; var flushbits, remaining_headers; var bitsPerFrame; var last_ptr, first_ptr; first_ptr = gfc.w_ptr; /* first header to add to bitstream */ last_ptr = gfc.h_ptr - 1; /* last header to add to bitstream */ if (last_ptr == -1) last_ptr = LameInternalFlags.MAX_HEADER_BUF - 1; /* add this many bits to bitstream so we can flush all headers */ flushbits = gfc.header[last_ptr].write_timing - totbit; total_bytes_output.total = flushbits; if (flushbits >= 0) { /* if flushbits >= 0, some headers have not yet been written */ /* reduce flushbits by the size of the headers */ remaining_headers = 1 + last_ptr - first_ptr; if (last_ptr < first_ptr) remaining_headers = 1 + last_ptr - first_ptr + LameInternalFlags.MAX_HEADER_BUF; flushbits -= remaining_headers * 8 * gfc.sideinfo_len; } /* * finally, add some bits so that the last frame is complete these bits * are not necessary to decode the last frame, but some decoders will * ignore last frame if these bits are missing */ bitsPerFrame = self.getframebits(gfp); flushbits += bitsPerFrame; total_bytes_output.total += bitsPerFrame; /* round up: */ if ((total_bytes_output.total % 8) != 0) total_bytes_output.total = 1 + (total_bytes_output.total / 8); else total_bytes_output.total = (total_bytes_output.total / 8); total_bytes_output.total += bufByteIdx + 1; if (flushbits < 0) { System.err.println("strange error flushing buffer ... \n"); } return flushbits; } this.flush_bitstream = function (gfp) { var gfc = gfp.internal_flags; var l3_side; var flushbits; var last_ptr = gfc.h_ptr - 1; /* last header to add to bitstream */ if (last_ptr == -1) last_ptr = LameInternalFlags.MAX_HEADER_BUF - 1; l3_side = gfc.l3_side; if ((flushbits = compute_flushbits(gfp, new TotalBytes())) < 0) return; drain_into_ancillary(gfp, flushbits); /* check that the 100% of the last frame has been written to bitstream */ assert(gfc.header[last_ptr].write_timing + this.getframebits(gfp) == totbit); /* * we have padded out all frames with ancillary data, which is the same * as filling the bitreservoir with ancillary data, so : */ gfc.ResvSize = 0; l3_side.main_data_begin = 0; /* save the ReplayGain value */ if (gfc.findReplayGain) { var RadioGain = ga.GetTitleGain(gfc.rgdata); assert(NEQ(RadioGain, GainAnalysis.GAIN_NOT_ENOUGH_SAMPLES)); gfc.RadioGain = Math.floor(RadioGain * 10.0 + 0.5) | 0; /* round to nearest */ } /* find the gain and scale change required for no clipping */ if (gfc.findPeakSample) { gfc.noclipGainChange = Math.ceil(Math .log10(gfc.PeakSample / 32767.0) * 20.0 * 10.0) | 0; /* round up */ if (gfc.noclipGainChange > 0) { /* clipping occurs */ if (EQ(gfp.scale, 1.0) || EQ(gfp.scale, 0.0)) gfc.noclipScale = (Math .floor((32767.0 / gfc.PeakSample) * 100.0) / 100.0); /* round down */ else { /* * the user specified his own scaling factor. We could * suggest the scaling factor of * (32767.0/gfp.PeakSample)*(gfp.scale) but it's usually * very inaccurate. So we'd rather not advice him on the * scaling factor. */ gfc.noclipScale = -1; } } else /* no clipping */ gfc.noclipScale = -1; } }; this.add_dummy_byte = function (gfp, val, n) { var gfc = gfp.internal_flags; var i; while (n-- > 0) { putbits_noheaders(gfc, val, 8); for (i = 0; i < LameInternalFlags.MAX_HEADER_BUF; ++i) gfc.header[i].write_timing += 8; } }; /** * This is called after a frame of audio has been quantized and coded. It * will write the encoded audio to the bitstream. Note that from a layer3 * encoder's perspective the bit stream is primarily a series of main_data() * blocks, with header and side information inserted at the proper locations * to maintain framing. (See Figure A.7 in the IS). */ this.format_bitstream = function (gfp) { var gfc = gfp.internal_flags; var l3_side; l3_side = gfc.l3_side; var bitsPerFrame = this.getframebits(gfp); drain_into_ancillary(gfp, l3_side.resvDrain_pre); encodeSideInfo2(gfp, bitsPerFrame); var bits = 8 * gfc.sideinfo_len; bits += writeMainData(gfp); drain_into_ancillary(gfp, l3_side.resvDrain_post); bits += l3_side.resvDrain_post; l3_side.main_data_begin += (bitsPerFrame - bits) / 8; /* * compare number of bits needed to clear all buffered mp3 frames with * what we think the resvsize is: */ if (compute_flushbits(gfp, new TotalBytes()) != gfc.ResvSize) { System.err.println("Internal buffer inconsistency. flushbits <> ResvSize"); } /* * compare main_data_begin for the next frame with what we think the * resvsize is: */ if ((l3_side.main_data_begin * 8) != gfc.ResvSize) { System.err.printf("bit reservoir error: \n" + "l3_side.main_data_begin: %d \n" + "Resvoir size: %d \n" + "resv drain (post) %d \n" + "resv drain (pre) %d \n" + "header and sideinfo: %d \n" + "data bits: %d \n" + "total bits: %d (remainder: %d) \n" + "bitsperframe: %d \n", 8 * l3_side.main_data_begin, gfc.ResvSize, l3_side.resvDrain_post, l3_side.resvDrain_pre, 8 * gfc.sideinfo_len, bits - l3_side.resvDrain_post - 8 * gfc.sideinfo_len, bits, bits % 8, bitsPerFrame); System.err.println("This is a fatal error. It has several possible causes:"); System.err.println("90%% LAME compiled with buggy version of gcc using advanced optimizations"); System.err.println(" 9%% Your system is overclocked"); System.err.println(" 1%% bug in LAME encoding library"); gfc.ResvSize = l3_side.main_data_begin * 8; } //; assert(totbit % 8 == 0); if (totbit > 1000000000) { /* * to avoid totbit overflow, (at 8h encoding at 128kbs) lets reset * bit counter */ var i; for (i = 0; i < LameInternalFlags.MAX_HEADER_BUF; ++i) gfc.header[i].write_timing -= totbit; totbit = 0; } return 0; }; /** * <PRE> * copy data out of the internal MP3 bit buffer into a user supplied * unsigned char buffer. * * mp3data=0 indicates data in buffer is an id3tags and VBR tags * mp3data=1 data is real mp3 frame data. * </PRE> */ this.copy_buffer = function (gfc, buffer, bufferPos, size, mp3data) { var minimum = bufByteIdx + 1; if (minimum <= 0) return 0; if (size != 0 && minimum > size) { /* buffer is too small */ return -1; } System.arraycopy(buf, 0, buffer, bufferPos, minimum); bufByteIdx = -1; bufBitIdx = 0; if (mp3data != 0) { var crc = new_int(1); crc[0] = gfc.nMusicCRC; vbr.updateMusicCRC(crc, buffer, bufferPos, minimum); gfc.nMusicCRC = crc[0]; /** * sum number of bytes belonging to the mp3 stream this info will be * written into the Xing/LAME header for seeking */ if (minimum > 0) { gfc.VBR_seek_table.nBytesWritten += minimum; } if (gfc.decode_on_the_fly) { /* decode the frame */ var pcm_buf = new_float_n([2, 1152]); var mp3_in = minimum; var samples_out = -1; var i; /* re-synthesis to pcm. Repeat until we get a samples_out=0 */ while (samples_out != 0) { samples_out = mpg.hip_decode1_unclipped(gfc.hip, buffer, bufferPos, mp3_in, pcm_buf[0], pcm_buf[1]); /* * samples_out = 0: need more data to decode samples_out = * -1: error. Lets assume 0 pcm output samples_out = number * of samples output */ /* * set the lenght of the mp3 input buffer to zero, so that * in the next iteration of the loop we will be querying * mpglib about buffered data */ mp3_in = 0; if (samples_out == -1) { /* * error decoding. Not fatal, but might screw up the * ReplayGain tag. What should we do? Ignore for now */ samples_out = 0; } if (samples_out > 0) { /* process the PCM data */ /* * this should not be possible, and indicates we have * overflown the pcm_buf buffer */ assert(samples_out <= 1152); if (gfc.findPeakSample) { for (i = 0; i < samples_out; i++) { if (pcm_buf[0][i] > gfc.PeakSample) gfc.PeakSample = pcm_buf[0][i]; else if (-pcm_buf[0][i] > gfc.PeakSample) gfc.PeakSample = -pcm_buf[0][i]; } if (gfc.channels_out > 1) for (i = 0; i < samples_out; i++) { if (pcm_buf[1][i] > gfc.PeakSample) gfc.PeakSample = pcm_buf[1][i]; else if (-pcm_buf[1][i] > gfc.PeakSample) gfc.PeakSample = -pcm_buf[1][i]; } } if (gfc.findReplayGain) if (ga.AnalyzeSamples(gfc.rgdata, pcm_buf[0], 0, pcm_buf[1], 0, samples_out, gfc.channels_out) == GainAnalysis.GAIN_ANALYSIS_ERROR) return -6; } /* if (samples_out>0) */ } /* while (samples_out!=0) */ } /* if (gfc.decode_on_the_fly) */ } /* if (mp3data) */ return minimum; }; this.init_bit_stream_w = function (gfc) { buf = new_byte(Lame.LAME_MAXMP3BUFFER); gfc.h_ptr = gfc.w_ptr = 0; gfc.header[gfc.h_ptr].write_timing = 0; bufByteIdx = -1; bufBitIdx = 0; totbit = 0; }; // From machine.h } module.exports = BitStream;