📄 mpac.java
字号:
/*
* @(#)MPAC.java - mono<->stereo converter M1L2,48khz losless
*
* Copyright (c) 2002-2005 by dvb.matt, All rights reserved.
*
* This file is part of X, a free Java based demux utility.
* X is intended for educational purposes only, as a non-commercial test project.
* It may not be used otherwise. Most parts are only experimental.
*
* The part of audio parsing was derived from the MPEG/Audio
* Software Simulation Group's audio codec in a special modified manner.
*
*
* This program is free software; you can redistribute it free of charge
* and/or modify it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
/*
* rewritten Oct 2003 by dvb.matt
*/
package net.sourceforge.dvb.projectx.audio;
import net.sourceforge.dvb.projectx.common.X;
import net.sourceforge.dvb.projectx.common.Resource;
public class MPAC
{
//mpeg-1 27 subbands
private final short alloc27[][] = {
{ 0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17 },
{ 0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17 },
{ 0,1,3,5,6,7,8,9,10,11,12,13,14,15,16,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,3,4,5,6,17 },
{ 0,1,2,17 },
{ 0,1,2,17 },
{ 0,1,2,17 },
{ 0,1,2,17 }
};
private final short bal27mp1[] = { 4,4,4,4,4,4,4,4,4,4,4,3,3,3,3,3,3,3,3,3,3,3,3,2,2,2,2 };
private final short getbits[] = { 0,5,7,3,10,4,5,6,7,8,9,10,11,12,13,14,15,16 };
private final short grouping[] = { 0,3,5,0,9,0,0,0,0,0,0,0,0,0,0,0,0,0 };
private final int MPA_48M1L2[] = { 0,768,1152,1344,1536,1920,2304,2688,3072,3840,4608,5376,6144,7680,9216,16384 };
private final int STEREO = 0;
private final int JSTEREO = 1;
private final int DUAL = 2;
private final int SINGLE = 3;
private int maxBitSize = 0;
private short Bal[] = new short[0];
private short Allocation[][];
private int Sizes[];
private int BRindex[] = new int[3];
private int Restart = 0;
private int error_flag = 0;
private Audio Audio;
//init
public MPAC()
{
Audio = new Audio();
Sizes = MPA_48M1L2;
java.util.Arrays.sort(Sizes);
maxBitSize = Sizes[14];
Bal = bal27mp1;
Allocation = alloc27;
}
/******************************************
* modify mpegaudio frame 48khz 56..384kbps M1L2; *
******************************************/
public byte[][] modifyframe(byte[] AudioFrame, long[] options)
{
byte newAudioFrames[][] = new byte[2][AudioFrame.length];
for (int a=0; a < 3; a++) //0-s, 1-l, 2-r
BRindex[a]=(int)(0xF & options[17]>>>(4 + (a<<2)));
Restart = 0;
error_flag = 0;
int transcode = (int)options[10];
//secure, but most was already done by X.java
if (Audio.MPA_parseHeader(AudioFrame,0)!=1 || Audio.ID!=1 || Audio.Layer!=2 || Audio.Sampling_frequency!=48000 ||
Audio.Bitrate<56000 || (Audio.Mode==SINGLE && Audio.Bitrate>192000) || (Audio.Mode!=SINGLE && Audio.Bitrate<112000))
{
System.arraycopy(AudioFrame,0,newAudioFrames[0],0,AudioFrame.length);
System.arraycopy(AudioFrame,0,newAudioFrames[1],0,AudioFrame.length); // copy frame
X.Msg(Resource.getString("audio.msg.convert.disabled", "" + (options[17]>>>18)));
options[17] |= 0x1000CL;
return newAudioFrames;
}
Audio.MPA_deleteCRC(AudioFrame);
switch(transcode)
{
case 1: //single channel to dual(A)
case 2: //single channel to stereo
case 3: //single channel to jstereo
if (Audio.Channel == 1)
newAudioFrames = createByteArrays(makeTwoChannel(createBitArray(AudioFrame), transcode, 0));
else
newAudioFrames = adaptSourceFrame(AudioFrame, newAudioFrames, transcode); //check to pass BR
break;
case 4: //dual-stereo-jointstereo to 2 x mono
if (Audio.Channel == 2)
newAudioFrames = createByteArrays(splitTwoChannel(createBitArray(AudioFrame),transcode));
else
newAudioFrames = adaptSourceFrame(AudioFrame, newAudioFrames, transcode); //check to pass BR
}
options[17] &= ~0xFFFCL;
for (int a=0; a < 3; a++) //0-s, 1-l, 2-r
options[17] |= BRindex[a]<<(4 + (a<<2));
options[17] |= Restart<<2;
if (error_flag > 0)
X.Msg(Resource.getString("audio.msg.convert.error", "" + error_flag, "" + (options[17]>>>18)));
return newAudioFrames;
}
private void setError(int error)
{
error_flag |= error;
}
//check to pass BR
private byte[][] adaptSourceFrame(byte AudioFrame[], byte input[][], int transcode)
{
System.arraycopy(AudioFrame, 0, input[0], 0, AudioFrame.length);
System.arraycopy(AudioFrame, 0, input[1], 0, AudioFrame.length); // copy frame
int size[] = new int[2];
size[1] = size[0] = (0xF0 & AudioFrame[2])>>>4;
if (transcode < 4)
{
if (size[0] == BRindex[0]) //same size
return input;
else if (size[0] > BRindex[0])
{ //restart with new size
if (BRindex[0] != 0)
Restart |= 3;
BRindex[0] = size[0];
return input;
}
}
else
{
if (size[0] == BRindex[1] && size[1] == BRindex[2]) //same size
return input;
else
{ //restart with new size
if (size[0] > BRindex[1])
{ //fill to size L
if (BRindex[1] != 0)
Restart |= 1;
BRindex[1] = size[0];
}
if (size[1] > BRindex[2])
{ //fill to size R
if (BRindex[2] != 0)
Restart |= 2;
BRindex[2] = size[1];
}
if (Restart > 0)
return input;
}
}
byte output[][]=new byte[2][0];
for (int ch=0; ch<2; ch++)
{
output[ch] = new byte[Sizes[BRindex[ch + (transcode>>>2)]]>>>3];
System.arraycopy(input[ch], 0, output[ch], 0, input[ch].length);
output[ch][2] &= (byte)~0xF0;
output[ch][2] |= (byte)BRindex[ch + (transcode>>>2)]<<4;
if (transcode < 4)
break;
else if (BRindex[ch+1] > 10)
output[ch] = createByteArray(makeTwoChannel(createBitArray(output[ch]), 3, ch + 1));
}
return output;
}
//bytearray to bitarray
private boolean[] createBitArray(byte input[])
{
boolean output[] = new boolean[maxBitSize]; //max=1152bytes=9216bits
for (int a=0; a < input.length; a++)
for (int b=0; b < 8; b++)
if ( ((0x80>>>b) & input[a]) != 0 )
output[b + (a<<3)] = true;
return output;
}
//1ch_bitarray to 1ch_bytearray, frame in bitform must already be compliant, but will be shortened in this method to the indexed BR
private byte[] createByteArray(boolean input[])
{
int size = getSizeFromIndex(input)>>>3;
byte output[] = new byte[size];
for (int a=0; a < size; a++)
for (int b=0; b < 8; b++)
output[a] |= input[b + (a<<3)] ? 0x80>>>b : 0;
return output;
}
//1ch_bitarray to 2ch_bytearray, frame in bitform must already be compliant, but will be shortened in this method to the indexed BR
private byte[][] createByteArrays(boolean input[])
{
int size = getSizeFromIndex(input)>>>3;
byte output[][] = { new byte[size], new byte[0] };
for (int a=0; a < size; a++)
for (int b=0; b < 8; b++)
output[0][a] |= input[b + (a<<3)] ? 0x80>>>b : 0;
return output;
}
//2ch_bitarray to 2ch_bytearray, frame in bitform must already be compliant, but will be shortened in this method to the indexed BR
private byte[][] createByteArrays(boolean input[][])
{
int size[] = new int[2];
for (int ch=0; ch < 2; ch++)
size[ch] = getSizeFromIndex(input[ch])>>>3;
byte output[][] = { new byte[size[0]], new byte[size[1]] };
for (int ch=0; ch < 2; ch++)
for (int a=0; a < size[ch]; a++)
for (int b=0; b < 8; b++)
output[ch][a] |= input[ch][b + (a<<3)] ? 0x80>>>b : 0;
return output;
}
//read out BR_index in bitlength
private int getSizeFromIndex(boolean input[])
{
int size = 0;
for (int a=0; a<4; a++)
size |= input[a + 16] ? 8>>>a : 0;
size = Sizes[size];
return size;
}
//set Bitrate index
private void setBitRateIndex(boolean input[], int size, int channel)
{
if ( (size = java.util.Arrays.binarySearch(Sizes, size)) < 0);
size = Math.abs(size) - 1;
if (channel == 0 && size < 7)
size = 7;
if (channel > 0 && size < 3)
size = 3;
size = updateCBRIndex(size, channel);
for (int a=0; a < 4; a++)
input[a + 16] = (size & 8>>a) != 0 ? true : false;
}
//update Bitrate index for CBR
private int updateCBRIndex(int size, int channel)
{
if (BRindex[channel] == 0) // if 0 set first BR
BRindex[channel] = size;
else if (BRindex[channel] >= size)
size = BRindex[channel];
else
{
Restart |= (3 - channel);
BRindex[channel] = size;
}
return size;
}
//set channelmode
private void setChannelMode(boolean input[], int mode)
{
mode <<= 2;
for (int a=0; a < 4; a++)
input[a + 24] = (mode & 8>>a) != 0 ? true : false;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -