public byte[] WriteToBitStream(int bitsPerFrame, ref FrameParams fr_ps, int[][][] l3_enc, ref SideInfo l3_side, int[][][] scalefact_l, int[][][][] scalefact_s, double[][][] xr, byte[] ancillary, int ancillary_bits) { OutputBit = 8; int mode_gr = 2; for (int gr = 0; gr < mode_gr; gr++) { for (int ch = 0; ch < fr_ps.Chn; ch++) { for (int i = 0; i < 576; i++) { if ((xr[ch][gr][i] < 0) && (l3_enc[ch][gr][i] > 0)) { l3_enc[ch][gr][i] *= -1; } } } } EncodeSideInfo(ref l3_side, ref fr_ps); EncodeMainData(l3_enc, ref l3_side, ref fr_ps, scalefact_l, scalefact_s); WriteAncillaryData(ancillary, ancillary_bits); if (l3_side.ResvDrain != 0) { DrainIntoAncillaryData(l3_side.ResvDrain); } SFrameData = new FrameData(bitsPerFrame, mode_gr, fr_ps.Chn, headerPH, frameSIPH, channelSIPH, spectrumSIPH, scaleFactorsPH, codedDataPH, userSpectrumPH, userFrameDataPH); sFrameResults = new FrameResults(); WriteFrame(ref SFrameData, ref sFrameResults); l3_side.MainDataBegin = sFrameResults.NextBackPtr; return(EncodedOutput); }
public void ResvFrameBegin(ref FrameParams fr_ps, ref SideInfo l3_side, int mean_bits, int frameLength) { Layer info; int fullFrameBits, mode_gr; int expectedResvSize, resvLimit; info = fr_ps.Header; mode_gr = 2; resvLimit = 4088; expectedResvSize = l3_side.MainDataBegin * 8; fullFrameBits = mean_bits * mode_gr; if (frameLength > 7680) { ResvMax = 0; } else { ResvMax = 7680 - frameLength; } if (ResvMax > resvLimit) { ResvMax = resvLimit; } }
public int ResvMaxBits(ref FrameParams fr_ps, ref SideInfo l3_side, ref double pe, int mean_bits) { int more_bits, max_bits, add_bits, over_bits; mean_bits /= fr_ps.Chn; max_bits = mean_bits; if (max_bits > 4095) { max_bits = 4095; } if (ResvMax == 0) { return(max_bits); } more_bits = (int)(pe * 3.1 - mean_bits); add_bits = 0; if (more_bits > 100) { int frac = (ResvSize * 6) / 10; if (frac < more_bits) { add_bits = frac; } else { add_bits = more_bits; } } over_bits = ResvSize - ((ResvMax * 8) / 10) - add_bits; if (over_bits > 0) { add_bits += over_bits; } max_bits += add_bits; if (max_bits > 4095) { max_bits = 4095; } return(max_bits); }
public void ResvFrameEnd(ref FrameParams fr_ps, ref SideInfo l3_side, int mean_bits) { int mode_gr, gr, ch, chn, ancillary_pad, stuffingBits; int over_bits; chn = fr_ps.Chn; mode_gr = 2; ancillary_pad = 0; if ((chn == 2) && ((mean_bits & 1) != 0)) { ResvSize += 1; } over_bits = ResvSize - ResvMax; if (over_bits < 0) { over_bits = 0; } ResvSize -= over_bits; stuffingBits = over_bits + ancillary_pad; if ((over_bits = ResvSize % 8) != 0) { stuffingBits += over_bits; ResvSize -= over_bits; } if (stuffingBits != 0) { if (l3_side.TT[0, 0].Part23Length + stuffingBits < 4095) { l3_side.TT[0, 0].Part23Length += stuffingBits; } else { for (gr = 0; gr < mode_gr; gr++) { for (ch = 0; ch < chn; ch++) { int extraBits, bitsThisGr; if (stuffingBits == 0) { break; } extraBits = 4095 - l3_side.TT[ch, gr].Part23Length; if (extraBits < stuffingBits) { bitsThisGr = extraBits; } else { bitsThisGr = stuffingBits; } l3_side.TT[0, 0].Part23Length += bitsThisGr; stuffingBits -= bitsThisGr; } } l3_side.ResvDrain = stuffingBits; } } }
public void ResvAdjust(ref FrameParams fr_ps, ref GrInfo gi, ref SideInfo l3_side, int mean_bits) { ResvSize += (mean_bits / fr_ps.Chn) - gi.Part23Length; }
static private int Part2Length(int[][][] scalefact_l, int[][][][] scalefact_s, ref FrameParams fr_ps, int gr, int ch, ref SideInfo si) { int slen1, slen2, bits; bits = 0; slen1 = Tables.Slen1Tab[si.TT[ch, gr].ScalefacCompress]; slen2 = Tables.Slen2Tab[si.TT[ch, gr].ScalefacCompress]; if ((si.TT[ch, gr].WindowSwitchingFlag == 1) && (si.TT[ch, gr].BlockType == 2)) { if (si.TT[ch, gr].MixedBlockFlag != 0) { bits += (8 * slen1) + (9 * slen1) + (18 * slen2); } else { bits += (18 * slen1) + (18 * slen2); } } else { if ((gr == 0) || (si.Scfsi[ch, 0] == 0)) { bits += (6 * slen1); } if ((gr == 0) || (si.Scfsi[ch, 1] == 0)) { bits += (5 * slen1); } if ((gr == 0) || (si.Scfsi[ch, 2] == 0)) { bits += (5 * slen2); } if ((gr == 0) || (si.Scfsi[ch, 3] == 0)) { bits += (5 * slen2); } } return(bits); }
private int OuterLoop(double[] abs_xr, int max_bits, double[,,] xmin_l, double[,,,] xmin_s, int[] abs_ix, ref FrameParams fr_ps, int[][][] scalefact_l, int[][][][] scalefact_s, int gr, int ch, ref SideInfo l3_side) { double[,] xfsf = new double[4, 21]; int[] scalesave_l = new int[21]; int[,] scalesave_s = new int[12, 3]; int bits, huff_bits, save_preflag, save_compress; int sfb, b, over, iteration = 0; do { iteration++; l3_side.TT[ch, gr].Part2Length = Part2Length(scalefact_l, scalefact_s, ref fr_ps, gr, ch, ref l3_side); huff_bits = max_bits - l3_side.TT[ch, gr].Part2Length; if (iteration == 1) { BinSearchStepSize(max_bits, l3_side.TT[ch, gr].QuantizerStepSize, abs_ix, abs_xr, ref l3_side.TT[ch, gr]); /* speeds things up a bit */ } bits = InnerLoop(abs_xr, abs_ix, huff_bits, ref l3_side.TT[ch, gr]); CalcNoise(abs_xr, abs_ix, ref l3_side.TT[ch, gr], xfsf); for (sfb = 0; sfb < 21; sfb++) { scalesave_l[sfb] = scalefact_l[ch][gr][sfb]; } for (sfb = 0; sfb < 12; sfb++) { for (b = 0; b < 3; b++) { scalesave_s[sfb, b] = scalefact_s[ch][gr][sfb][b]; } } save_preflag = l3_side.TT[ch, gr].Preflag; save_compress = l3_side.TT[ch, gr].ScalefacCompress; Preemphasis(abs_xr, xfsf, xmin_l, xmin_s, gr, ch, ref l3_side); over = AmpScalefacBands(abs_xr, xfsf, xmin_l, xmin_s, ref l3_side, scalefact_l, scalefact_s, gr, ch, iteration); if (LoopBreak(scalefact_l, scalefact_s, ref l3_side.TT[ch, gr], gr, ch)) { break; } if (ScaleBitcount(scalefact_l, scalefact_s, ref l3_side.TT[ch, gr], gr, ch) != 0) { break; } }while (over > 0); l3_side.TT[ch, gr].Preflag = save_preflag; l3_side.TT[ch, gr].ScalefacCompress = save_compress; for (sfb = 0; sfb < 21; sfb++) { scalefact_l[ch][gr][sfb] = scalesave_l[sfb]; } for (sfb = 0; sfb < 12; sfb++) { for (b = 0; b < 3; b++) { scalefact_s[ch][gr][sfb][b] = scalesave_s[sfb, b]; } } l3_side.TT[ch, gr].Part2Length = Part2Length(scalefact_l, scalefact_s, ref fr_ps, gr, ch, ref l3_side); l3_side.TT[ch, gr].Part23Length = l3_side.TT[ch, gr].Part2Length + bits; return(l3_side.TT[ch, gr].Part23Length); }
public void Loop(double[,] pe, double[][][] xr_org, double[,,,] ratio_s, double[,,] ratio_l, ref SideInfo l3_side, int[][][] l3_enc, int mean_bits, int chn, double[][][] xr_dec, int[][][] scalefact_l, int[][][][] scalefact_s, ref FrameParams fr_ps, int ancillary_pad, int bitsPerFrame) { int max_bits; int ch, gr, i, sfb, b, scfsi_band; int mode_gr; int start, end; double sum1, sum2, temp, x; double log2; double[,,] xmin_l = new double[2, 2, 21]; double[,,,] xmin_s = new double[2, 2, 12, 3]; double[] abs_xr = new double[576]; double[] energy_l = new double[22]; double[,] en_tot = new double[2, 2]; double[,,] en = new double[2, 2, 21]; double[,,] xm = new double[2, 2, 21]; int[,] xrAllZero = new int[2, 2]; int en_tot_krit = 10; int en_dif_krit = 100; int en_scfsi_band_krit = 10; int xm_scfsi_band_krit = 10; log2 = Math.Log(2.0); l3_side.ResvDrain = 0; if (fInit_iteration_loop == 0) { l3_side.MainDataBegin = 0; fInit_iteration_loop = 1; } mode_gr = 2; scalefac_band_long = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][0]; scalefac_band_short = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][1]; reserv.ResvFrameBegin(ref fr_ps, ref l3_side, mean_bits, bitsPerFrame); for (gr = 0; gr < mode_gr; gr++) { for (ch = 0; ch < chn; ch++) { for (i = 0; i < 576; i++) { abs_xr[i] = Math.Abs(xr_org[ch][gr][i]); } if (l3_side.TT[ch, gr].WindowSwitchingFlag != 0 && l3_side.TT[ch, gr].BlockType == 2) { if (l3_side.TT[ch, gr].MixedBlockFlag != 0) { l3_side.TT[ch, gr].SfbLmax = 8; l3_side.TT[ch, gr].SfbSmax = 3; } else { l3_side.TT[ch, gr].SfbLmax = 0; l3_side.TT[ch, gr].SfbSmax = 0; } } else { l3_side.TT[ch, gr].SfbLmax = 21; l3_side.TT[ch, gr].SfbSmax = 12; } sum1 = 0; sum2 = 0; for (sfb = 0; sfb < 22; sfb++) { start = scalefac_band_long[sfb]; end = scalefac_band_long[sfb + 1]; temp = 0; for (i = start; i < end; i++) { if ((x = abs_xr[i]) != 0) { temp += x * x; sum1 += Math.Log(x); } } sum2 += energy_l[sfb] = temp; if (sfb < l3_side.TT[ch, gr].SfbLmax) { xmin_l[ch, gr, sfb] = ratio_l[ch, gr, sfb] * temp / (end - start); } } for (sfb = l3_side.TT[ch, gr].SfbSmax; sfb < 12; sfb++) { start = scalefac_band_short[sfb]; end = scalefac_band_short[sfb + 1]; for (b = 0; b < 3; b++) { temp = 0.0; for (i = start; i < end; i++) { temp += abs_xr[i * 3 + b] * abs_xr[i * 3 + b]; } xmin_s[ch, gr, sfb, b] = ratio_s[ch, gr, sfb, b] * temp / (end - start); } } xrAllZero[ch, gr] = 1; if (l3_side.TT[ch, gr].WindowSwitchingFlag == 0 || (l3_side.TT[ch, gr].BlockType != 2)) { for (sfb = 0; sfb < 21; sfb++) { if (xmin_l[ch, gr, sfb] == 0) { xm[ch, gr, sfb] = 0; } else { xm[ch, gr, sfb] = Math.Log(xmin_l[ch, gr, sfb]) / log2; } } if (gr == 1) { for (scfsi_band = 0; scfsi_band < 4; scfsi_band++) { l3_side.Scfsi[ch, scfsi_band] = 0; } if (xrAllZero[ch, 0] == 0 || xrAllZero[ch, 1] == 0) { if (Math.Abs(en_tot[ch, 0] - en_tot[ch, 1]) < en_tot_krit) { temp = 0.0; for (sfb = 0; sfb < 21; sfb++) { temp += Math.Abs(en[ch, 0, sfb] - en[ch, 1, sfb]); } if (temp < en_dif_krit) { for (scfsi_band = 0; scfsi_band < 4; scfsi_band++) { sum1 = 0; sum2 = 0; start = scfsi_band_long[scfsi_band]; end = scfsi_band_long[scfsi_band + 1]; for (sfb = start; sfb < end; sfb++) { sum1 += Math.Abs(en[ch, 0, sfb] - en[ch, 1, sfb]); sum2 += Math.Abs(xm[ch, 0, sfb] - xm[ch, 1, sfb]); } if (sum1 < en_scfsi_band_krit && sum2 < xm_scfsi_band_krit) { l3_side.Scfsi[ch, scfsi_band] = 1; } } } } } } } max_bits = reserv.ResvMaxBits(ref fr_ps, ref l3_side, ref pe[ch, gr], mean_bits); for (sfb = 0; sfb < 21; sfb++) { scalefact_l[ch][gr][sfb] = 0; } for (sfb = 0; sfb < 12; sfb++) { for (b = 0; b < 3; b++) { scalefact_s[ch][gr][sfb][b] = 0; } } for (scfsi_band = 0; scfsi_band < 4; scfsi_band++) { l3_side.TT[ch, gr].Slen[scfsi_band] = 0; } l3_side.TT[ch, gr].SfbPartitionTable = nr_of_sfb_block; l3_side.TT[ch, gr].Part23Length = 0; l3_side.TT[ch, gr].BigValues = 0; l3_side.TT[ch, gr].Count1 = 0; l3_side.TT[ch, gr].ScalefacCompress = 0; l3_side.TT[ch, gr].TableSelect[0] = 0; l3_side.TT[ch, gr].TableSelect[1] = 0; l3_side.TT[ch, gr].TableSelect[2] = 0; l3_side.TT[ch, gr].SubblockGain[0] = 0; l3_side.TT[ch, gr].SubblockGain[1] = 0; l3_side.TT[ch, gr].SubblockGain[2] = 0; l3_side.TT[ch, gr].Region0Count = 0; l3_side.TT[ch, gr].Region1Count = 0; l3_side.TT[ch, gr].Part2Length = 0; l3_side.TT[ch, gr].Preflag = 0; l3_side.TT[ch, gr].ScalefacScale = 0; l3_side.TT[ch, gr].QuantizerStepSize = 0; l3_side.TT[ch, gr].Count1tableSelect = 0; int system_const = 8; int minlimit = -100; if (sum2 != 0) { temp = Nint(system_const * (sum1 / 288 - Math.Log(sum2 / 576))); if (temp < minlimit) { temp = minlimit; } temp -= 70; l3_side.TT[ch, gr].QuantizerStepSize = temp; l3_side.TT[ch, gr].Part23Length = OuterLoop(abs_xr, max_bits, xmin_l, xmin_s, l3_enc[ch][gr], ref fr_ps, scalefact_l, scalefact_s, gr, ch, ref l3_side); } reserv.ResvAdjust(ref fr_ps, ref l3_side.TT[ch, gr], ref l3_side, mean_bits); l3_side.TT[ch, gr].GlobalGain = Nint(l3_side.TT[ch, gr].QuantizerStepSize + 210.0); } } reserv.ResvFrameEnd(ref fr_ps, ref l3_side, mean_bits); }
private void EncodeSideInfo(ref SideInfo l3_side, ref FrameParams fr_ps) { int bits_sent, mode_gr = 2; headerPH.Position = 0; headerPH.Add(4095, 12); headerPH.Add(1, 1); headerPH.Add(1, 2); headerPH.Add(fr_ps.Header.ErrorProtection, 1); headerPH.Add(fr_ps.Header.BitrateIndex, 4); headerPH.Add(fr_ps.Header.SamplingFrequency, 2); headerPH.Add(fr_ps.Header.Padding, 1); headerPH.Add(fr_ps.Header.Extension, 1); headerPH.Add(fr_ps.Header.Mode, 2); headerPH.Add(fr_ps.Header.ModeExt, 2); headerPH.Add(fr_ps.Header.Copyright, 1); headerPH.Add(fr_ps.Header.Original, 1); headerPH.Add(fr_ps.Header.Emphasis, 2); bits_sent = 32; frameSIPH.Position = 0; for (int ch = 0; ch < fr_ps.Chn; ch++) { channelSIPH[ch].Position = 0; } for (int gr = 0; gr < 2; gr++) { for (int ch = 0; ch < fr_ps.Chn; ch++) { spectrumSIPH[ch, gr].Position = 0; } } if (fr_ps.Header.ErrorProtection == 0) { headerPH.Add(0, 16); bits_sent += 16; } frameSIPH.Add(l3_side.MainDataBegin, 9); if (fr_ps.Chn == 2) { frameSIPH.Add(l3_side.PrivateBits, 3); } else { frameSIPH.Add(l3_side.PrivateBits, 5); } for (int ch = 0; ch < fr_ps.Chn; ch++) { for (int scfsi_band = 0; scfsi_band < 4; scfsi_band++) { channelSIPH[ch].Add(l3_side.Scfsi[ch, scfsi_band], 1); } } for (int gr = 0; gr < mode_gr; gr++) { for (int ch = 0; ch < fr_ps.Chn; ch++) { spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].Part23Length, 12); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].BigValues, 9); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].GlobalGain, 8); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].ScalefacCompress, 4); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].WindowSwitchingFlag, 1); if (l3_side.TT[ch, gr].WindowSwitchingFlag != 0) { spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].BlockType, 2); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].MixedBlockFlag, 1); for (int region = 0; region < 2; region++) { spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].TableSelect[region], 5); } for (int window = 0; window < 3; window++) { spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].SubblockGain[window], 3); } } else { for (int region = 0; region < 3; region++) { spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].TableSelect[region], 5); } spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].Region0Count, 4); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].Region1Count, 3); } spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].Preflag, 1); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].ScalefacScale, 1); spectrumSIPH[ch, gr].Add(l3_side.TT[ch, gr].Count1tableSelect, 1); } } if (fr_ps.Chn == 2) { bits_sent += 256; } else { bits_sent += 136; } }
private void HuffmanCodeBits(int ch, int gr, int[] ix, ref GrInfo gi, ref FrameParams fr_ps) { int region1Start; int region2Start; int bigvalues, count1End; int v, w, x, y, bits, stuffingBits; HuffCodeTab ht; int bvbits, c1bits, cbits = 0, xbits = 0, code = 0, ext = 0, tablezeros = 0, r0 = 0, r1 = 0, r2 = 0, rt, pr; int bitsWritten = 0; bigvalues = gi.BigValues * 2; if (bigvalues != 0) { if (gi.MixedBlockFlag == 0 && gi.WindowSwitchingFlag != 0 && gi.BlockType == 2) { int sfb, window, line, start, end; region1Start = 12; region2Start = 576; for (sfb = 0; sfb < 13; sfb++) { int tableindex = 100; start = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][1][sfb]; //scalefac[sfb]; end = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][1][sfb + 1]; if (start < region1Start) { tableindex = gi.TableSelect[0]; } else { tableindex = gi.TableSelect[1]; } for (window = 0; window < 3; window++) { for (line = start; line < end; line += 2) { x = ix[line * 3 + window]; y = ix[(line + 1) * 3 + window]; bits = HuffmanCode(tableindex, x, y, ref code, ref ext, ref cbits, ref xbits); codedDataPH[ch, gr].Add(code, cbits); codedDataPH[ch, gr].Add(ext, xbits); bitsWritten += bits; } } } } else if (gi.MixedBlockFlag != 0 && gi.BlockType == 2) { int sfb, window, line, start, end, tableindex; tableindex = gi.TableSelect[0]; if (tableindex != 0) { for (int i = 0; i < 36; i += 2) { x = ix[i]; y = ix[i + 1]; bits = HuffmanCode(tableindex, x, y, ref code, ref ext, ref cbits, ref xbits); codedDataPH[ch, gr].Add(code, cbits); codedDataPH[ch, gr].Add(ext, xbits); bitsWritten += bits; } } tableindex = gi.TableSelect[1]; for (sfb = 3; sfb < 13; sfb++) { start = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][1][sfb]; end = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][1][sfb + 1]; for (window = 0; window < 3; window++) { for (line = start; line < end; line += 2) { x = ix[line * 3 + window]; y = ix[(line + 1) * 3 + window]; bits = HuffmanCode(tableindex, x, y, ref code, ref ext, ref cbits, ref xbits); codedDataPH[ch, gr].Add(code, cbits); codedDataPH[ch, gr].Add(ext, xbits); bitsWritten += bits; } } } } else { int scalefac_index = 100; if (gi.MixedBlockFlag != 0) { region1Start = 36; region2Start = 576; } else { scalefac_index = gi.Region0Count + 1; region1Start = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][0][scalefac_index]; scalefac_index += gi.Region1Count + 1; region2Start = Tables.SfBandIndex[fr_ps.Header.SamplingFrequency][0][scalefac_index]; } for (int i = 0; i < bigvalues; i += 2) { int tableindex = 100; if (i < region1Start) { tableindex = gi.TableSelect[0]; pr = 0; } else if (i < region2Start) { tableindex = gi.TableSelect[1]; pr = 1; } else { tableindex = gi.TableSelect[2]; pr = 2; } ht = huf.HT[tableindex]; x = ix[i]; y = ix[i + 1]; if (tableindex != 0) { bits = HuffmanCode(tableindex, x, y, ref code, ref ext, ref cbits, ref xbits); codedDataPH[ch, gr].Add(code, cbits); codedDataPH[ch, gr].Add(ext, xbits); rt = bits; bitsWritten += rt; switch (pr) { case 0: r0 += rt; break; case 1: r1 += rt; break; case 2: r2 += rt; break; } } else { tablezeros += 1; switch (pr) { case 0: r0 = 0; break; case 1: r1 = 0; break; case 2: r2 = 0; break; } } } } } bvbits = bitsWritten; ht = huf.HT[gi.Count1tableSelect + 32]; count1End = bigvalues + (gi.Count1 * 4); for (int i = bigvalues; i < count1End; i += 4) { v = ix[i]; w = ix[i + 1]; x = ix[i + 2]; y = ix[i + 3]; bitsWritten += HuffmanCoderCount1(ch, gr, ht, v, w, x, y); } c1bits = bitsWritten - bvbits; stuffingBits = gi.Part23Length - gi.Part2Length - bitsWritten; if (stuffingBits != 0) { int stuffingWords = stuffingBits / 32; int remainingBits = stuffingBits % 32; for (; stuffingWords > 0; stuffingWords--) { codedDataPH[ch, gr].Add(-1, 32); } if (remainingBits != 0) { codedDataPH[ch, gr].Add(-1, remainingBits); } bitsWritten += stuffingBits; } }
private void EncodeMainData(int[][][] l3_enc, ref SideInfo l3_side, ref FrameParams fr_ps, int[][][] scalefact_l, int[][][][] scalefact_s) { int slen1, slen2, mode_gr = 2; for (int gr = 0; gr < mode_gr; gr++) { for (int ch = 0; ch < fr_ps.Chn; ch++) { scaleFactorsPH[ch, gr].Position = 0; } } for (int gr = 0; gr < mode_gr; gr++) { for (int ch = 0; ch < fr_ps.Chn; ch++) { codedDataPH[ch, gr].Position = 0; } } for (int gr = 0; gr < mode_gr; gr++) { for (int ch = 0; ch < fr_ps.Chn; ch++) { slen1 = Tables.Slen1Tab[l3_side.TT[ch, gr].ScalefacCompress]; slen2 = Tables.Slen2Tab[l3_side.TT[ch, gr].ScalefacCompress]; if ((l3_side.TT[ch, gr].WindowSwitchingFlag == 1) && (l3_side.TT[ch, gr].BlockType == 2)) { if (l3_side.TT[ch, gr].MixedBlockFlag != 0) { for (int sfb = 0; sfb < 8; sfb++) { scaleFactorsPH[ch, gr].Add(scalefact_l[ch][gr][sfb], slen1); } for (int sfb = 3; sfb < 6; sfb++) { for (int window = 0; window < 3; window++) { scaleFactorsPH[ch, gr].Add(scalefact_s[ch][gr][sfb][window], slen1); } } for (int sfb = 6; sfb < 12; sfb++) { for (int window = 0; window < 3; window++) { scaleFactorsPH[ch, gr].Add(scalefact_s[ch][gr][sfb][window], slen2); } } } else { for (int sfb = 0; sfb < 6; sfb++) { for (int window = 0; window < 3; window++) { scaleFactorsPH[ch, gr].Add(scalefact_s[gr][ch][sfb][window], slen1); } } for (int sfb = 6; sfb < 12; sfb++) { for (int window = 0; window < 3; window++) { scaleFactorsPH[ch, gr].Add(scalefact_s[ch][gr][sfb][window], slen2); } } } } else { if ((gr == 0) || (l3_side.Scfsi[ch, 0] == 0)) { for (int sfb = 0; sfb < 6; sfb++) { scaleFactorsPH[ch, gr].Add(scalefact_l[ch][gr][sfb], slen1); } } if ((gr == 0) || (l3_side.Scfsi[ch, 1] == 0)) { for (int sfb = 6; sfb < 11; sfb++) { scaleFactorsPH[ch, gr].Add(scalefact_l[ch][gr][sfb], slen1); } } if ((gr == 0) || (l3_side.Scfsi[ch, 2] == 0)) { for (int sfb = 11; sfb < 16; sfb++) { scaleFactorsPH[ch, gr].Add(scalefact_l[ch][gr][sfb], slen2); } } if ((gr == 0) || (l3_side.Scfsi[ch, 3] == 0)) { for (int sfb = 16; sfb < 21; sfb++) { scaleFactorsPH[ch, gr].Add(scalefact_l[ch][gr][sfb], slen2); } } } HuffmanCodeBits(ch, gr, l3_enc[ch][gr], ref l3_side.TT[ch, gr], ref fr_ps); } } }
public static string Encode(string path, int bitrate, string title, string artist, string album, string year, string comment, byte zero, byte num, byte genre, System.ComponentModel.BackgroundWorker backgroundWorker) { int[,] savebuf = new int[2, 1344]; int[,] buf = new int[2, 1152]; int[,,] grbuf = new int[2, 2, 576]; double[][][][] xr; double[][][] xr1; int[][][] l3_enc = new int[2][][]; for (int i1 = 0; i1 < 2; i1++) { l3_enc[i1] = new int[2][]; for (int i2 = 0; i2 < 2; i2++) { l3_enc[i1][i2] = new int[576]; } } double[][][] xr_dec = new double[2][][]; for (int i1 = 0; i1 < 2; i1++) { xr_dec[i1] = new double[2][]; for (int i2 = 0; i2 < 2; i2++) { xr_dec[i1][i2] = new double[576]; } } int[][][] scalefact_l = new int[2][][]; for (int i1 = 0; i1 < 2; i1++) { scalefact_l[i1] = new int[2][]; for (int i2 = 0; i2 < 2; i2++) { scalefact_l[i1][i2] = new int[21]; } } int[][][][] scalefact_s = new int[2][][][]; for (int i1 = 0; i1 < 2; i1++) { scalefact_s[i1] = new int[2][][]; for (int i2 = 0; i2 < 2; i2++) { scalefact_s[i1][i2] = new int[12][]; for (int i3 = 0; i3 < 12; i3++) { scalefact_s[i1][i2][i3] = new int[3]; } } } SideInfo l3_side = new SideInfo(); FrameParams fr_ps = new FrameParams(); BitAndNoizeAlloc bna = new BitAndNoizeAlloc(); FormatBitStream fbs = new FormatBitStream(); int counter = 0; int ancillary_pad = 0; int bitsPerFrame = 0; int meanBits = 0; double[,,] ratio_d = new double[2, 2, 21]; double[,,,] ratio_ds = new double[2, 2, 12, 3]; double[,] pe = new double[2, 2]; int[,] sw_fl = new int[2, 2], bl_fl = new int[2, 2], wintp = new int[2, 2]; byte[] Song = File.ReadAllBytes(path); //чтение файла с PCM и запись в массив байтов int chn = BitConverter.ToInt16(Song, 22); //кол-во каналов int smplr = BitConverter.ToInt32(Song, 24); //частота семплирования int bps = BitConverter.ToInt16(Song, 34) / 8; //размер одного семпла int size = BitConverter.ToInt32(Song, 40); //размер области с данными int[,] s = new int[chn, (Song.Length - 44) / (chn * bps)]; double[][][][] sb_gr = new double[2][][][]; if (bps != 2 && bps != 4 && bps != 3) { throw new Exception("Неподдерживаемое разрешение"); } for (int i1 = 0; i1 < 2; i1++) { sb_gr[i1] = new double[3][][]; for (int i2 = 0; i2 < 3; i2++) { sb_gr[i1][i2] = new double[18][]; for (int i3 = 0; i3 < 18; i3++) { sb_gr[i1][i2][i3] = new double[32]; } } } Layer info = new Layer(); MDCT subber = new MDCT(); switch (smplr) { case 48000: info.SamplingFrequency = 1; break; case 44100: info.SamplingFrequency = 0; break; case 32000: info.SamplingFrequency = 2; break; default: throw new Exception("Неподдерживаемая частота семплирования"); } switch (chn) { case 0: info.Mode = 0; info.ModeExt = 0; break; case 2: info.Mode = 2; info.ModeExt = 0; break; case 1: info.Mode = 3; info.ModeExt = 0; break; default: throw new Exception("Неправильный формат данных"); } int j = 0; while (j < 15) { if (bitratex[1][j] == bitrate) { break; } j++; } info.BitrateIndex = j; info.Version = 1; info.Emphasis = 0; info.Extension = 0; info.Copyright = 0; info.Original = 1; info.ErrorProtection = 1; fr_ps.Header = info; fr_ps.Chn = chn; fr_ps.TabNum = -1; fr_ps.Alloc = null; fr_ps.ActualMode = info.Mode; fr_ps.Sblimit = 32; fr_ps.Jsbound = 32; double avg_slots_per_frame = (1152 / s_freq[1][info.SamplingFrequency]) * (bitratex[1][info.BitrateIndex] / 8.0); int whole_SpF = (int)avg_slots_per_frame; double frac_SpF = avg_slots_per_frame - whole_SpF; double slot_lag = -frac_SpF; int extra_slot; if (frac_SpF == 0) { fr_ps.Header.Padding = 0; } if (frac_SpF != 0) { if (slot_lag > (frac_SpF - 1.0)) { slot_lag -= frac_SpF; extra_slot = 0; fr_ps.Header.Padding = 0; } else { extra_slot = 1; fr_ps.Header.Padding = 1; slot_lag += (1 - frac_SpF); } } int sideinfo_len = 32; if (chn == 1) { sideinfo_len += 136; } else { sideinfo_len += 256; } if (fr_ps.Header.ErrorProtection == 0) { sideinfo_len += 16; } bitsPerFrame = 8 * whole_SpF + (fr_ps.Header.Padding * 8); meanBits = (bitsPerFrame - sideinfo_len) / 2; PsyAcoustic Obj = new PsyAcoustic(smplr); // инициализация психоакустической модели for (int i = 44; i < Song.Length - 44;) //массив со значениями PCM { for (int ch = 0; ch < chn; ch++, i += bps) { switch (bps) { case 2: s[ch, (i - 44) / (bps * chn)] = BitConverter.ToInt16(Song, i); break; case 3: s[ch, (i - 44) / (bps * chn)] = ToInt24(Song[i], Song[i + 1], Song[i + 2]); break; case 4: s[ch, (i - 44) / (bps * chn)] = BitConverter.ToInt32(Song, i); break; default: throw new ArgumentException(); } } } string outpath = Path.GetDirectoryName(path) + @"\" + Path.GetFileNameWithoutExtension(path) + ".mp3"; BinaryWriter bw = new BinaryWriter(File.Open(outpath, FileMode.Create)); counter = 0; double end = Math.Floor((double)(s.GetLength(1)) / 1152); for (int k = 0; k < end; k++) { xr = new double[2][][][]; for (int i1 = 0; i1 < 2; i1++) { xr[i1] = new double[3][][]; for (int i2 = 0; i2 < 3; i2++) { xr[i1][i2] = new double[32][]; for (int i3 = 0; i3 < 32; i3++) { xr[i1][i2][i3] = new double[18]; } } } grbuf = Granulation(s, ref counter, buf, chn); Sub = new double[2][][]; for (int gr = 0; gr < 2; gr++) { for (int ch = 0; ch < chn; ch++) { Obj.Analize(ch, gr, grbuf, ref savebuf, ref ratio_d, ref ratio_ds, ref pe, ref wintp[ch, gr], ref sw_fl[ch, gr], ref bl_fl[ch, gr]); //применение психоакустической модели l3_side.TT[ch, gr].WindowSwitchingFlag = sw_fl[ch, gr]; l3_side.TT[ch, gr].BlockType = wintp[ch, gr]; l3_side.TT[ch, gr].MixedBlockFlag = bl_fl[ch, gr]; } } for (int ch = 0; ch < chn; ch++) { PolyPhase.Subbanding(ch, out Sub[ch], buf); // разделение на 32 подполосы } for (int ch = 0; ch < chn; ch++) { for (int gr = 0, i0 = 0; gr < 2; gr++) { for (int s1 = 0; s1 < 18; s1++, i0++) { for (int band = 0; band < 32; band++) { sb_gr[ch][gr + 1][s1][band] = Sub[ch][i0][band]; } } } } subber.Subbanding(sb_gr, xr, chn, wintp, bl_fl); xr1 = new double[2][][]; for (int ch = 0; ch < chn; ch++) { xr1[ch] = new double[2][]; for (int gr = 0; gr < 2; gr++) { xr1[ch][gr] = new double[576]; for (int i1 = 0, i3 = 0; i1 < 32; i1++) { for (int i2 = 0; i2 < 18; i2++) { xr1[ch][gr][i3++] = xr[ch][gr][i1][i2]; } } } } bna.Loop(pe, xr1, ratio_ds, ratio_d, ref l3_side, l3_enc, meanBits, chn, xr_dec, scalefact_l, scalefact_s, ref fr_ps, ancillary_pad, bitsPerFrame); byte[] Arr = fbs.WriteToBitStream(bitsPerFrame, ref fr_ps, l3_enc, ref l3_side, scalefact_l, scalefact_s, xr1, null, 0); for (int i = 0; i < fbs.GetLength(); i++) { bw.Write(Arr[i]); } if (backgroundWorker.CancellationPending) { bw.Close(); return(outpath); } if (backgroundWorker.WorkerReportsProgress) { double pr = (k * 100) / end; backgroundWorker.ReportProgress((int)Math.Round(pr)); } } byte[] Tag = new byte[128]; byte[] temp = new byte[30]; Array.Copy(ASCIIEncoding.ASCII.GetBytes("TAG"), 0, Tag, 0, 3); Array.Copy(ASCIIEncoding.ASCII.GetBytes(title), 0, temp, 0, title.Length); Array.Copy(temp, 0, Tag, 3, 30); temp = new byte[30]; Array.Copy(ASCIIEncoding.ASCII.GetBytes(artist), 0, temp, 0, artist.Length); Array.Copy(temp, 0, Tag, 33, 30); temp = new byte[30]; Array.Copy(ASCIIEncoding.ASCII.GetBytes(album), 0, temp, 0, album.Length); Array.Copy(temp, 0, Tag, 63, 30); temp = new byte[30]; Array.Copy(ASCIIEncoding.ASCII.GetBytes(year), 0, temp, 0, year.Length); Array.Copy(temp, 0, Tag, 93, 30); temp = new byte[28]; Array.Copy(ASCIIEncoding.ASCII.GetBytes(comment), 0, temp, 0, comment.Length); Array.Copy(temp, 0, Tag, 97, 28); Tag[125] = zero; Tag[126] = num; Tag[127] = genre; bw.Write(Tag); bw.Close(); return(outpath); }