/*
* @(#)AudioFormatAAC.java - parse Audioheaders,
*
* Copyright (c) 2007-2008 by dvb.matt, All Rights Reserved.
*
* This file is part of ProjectX, a free Java based demux utility.
* By the authors, ProjectX is intended for educational purposes only,
* as a non-commercial test project.
*
* The part of audio parsing was derived from the MPEG/Audio
* Software Simulation Group's audio codec and ATSC A/52 in a special modified manner.
*
*
* This program is free software; you can redistribute it 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
*
*/
package net.sourceforge.dvb.projectx.audio;
import net.sourceforge.dvb.projectx.audio.AudioFormat;
import net.sourceforge.dvb.projectx.common.Common;
public class AudioFormatAAC extends AudioFormat {
//unused !!
public AudioFormatAAC()
{
super();
}
/**
*
*/
private int[] frequency_index = {
96000, 88200, 64000, 48000, 44100, 32000,
24000, 22050, 16000, 12000, 11025, 8000, 0, 0, 0, 0
};
/**
*
*/
private int[] bitrate_index = {
32000, 56000, 64000, 96000, 112000, 128000,
192000, 224000, 256000, 320000, 384000,
448000, 512000, 576000, 640000, 768000,
};
/**
*
*/
private String[] acmod = {
"1", "DM", "2/0", "2/0"
};
/**
*
*/
private int[] channels = {
1,2,2,2, 2,3,3,4, 4,5,6,6, 7,8,0,0,
};
/**
* parse aac Header
*/
public int parseHeader(byte[] frame, int pos)
{
boolean latm = false;
int aac_length = 0;
// 0x2B7 LATM
latm = frame[pos] == 0x56 && (0xE0 & frame[pos + 1]) == 0xE0;
if (latm)
{
aac_length = 3 + ((0x1F & frame[pos + 1])<<8 | (0xFF & frame[pos + 2]));
pos += 3;
}
if (frame.length == 4) //pushmpa = 4!
return (latm && (0xFF & frame[pos]) == 0xFF ? aac_length : -1);
//syncword ADTS
if ((0xFF & frame[pos]) != 0xFF && (0xE0 & frame[pos + 1]) != 0xE0)
return -1;
//ADTS fixed
setID(1 & frame[pos + 1]>>>3);
setLayer(3 & frame[pos + 1]>>>1);
setProtectionBit(1 ^ (1 & frame[pos + 1]));
setMode(3 & frame[pos + 2]>>>6); //profile
setSamplingFrequency(frequency_index[0xF & frame[pos + 2]>>>2]);
setPrivateBit(1 & frame[pos + 2]>>>1);
setChannel(7 & frame[pos + 2]<<2 | 3 & frame[pos + 3]>>>6); //see specif.
setCopyright(1 & frame[pos + 3]>>>5);
setOriginal(1 & frame[pos + 3]>>>4); //home
setEmphasis(3 & frame[pos + 3]>>>2);
// setFrameTimeLength(169344000.0 / getSamplingFrequency());
setFrameTimeLength(3840);
setBitrate(1000);
//ADTS variabel
//copyright_identification_bit 1 bslbf pos+3
//copyright_identification_start 1 bslbf pos+3
setSizeBase((0xFF & frame[pos + 4])<<5 | (0x1F & frame[pos + 5]>>3)); //frame_length 13 bslbf
setSize(getSizeBase());
//adts_buffer_fullness 11 bslbf
//number_of_raw_data_blocks_in_frame 2 uimsfb
return getLayer();
}
/**
* parse next aac Header
*/
public int parseNextHeader(byte[] frame, int pos)
{
boolean latm = false;
int aac_length = 0;
latm = frame[pos] == 0x56 && (0xE0 & frame[pos + 1]) == 0xE0;
if (latm)
{
aac_length = 3 + ((0x1F & frame[pos + 1])<<8 | (0xFF & frame[pos + 2]));
pos += 3;
}
if ((0xFF & frame[pos]) != 0xFF && (0xE0 & frame[pos + 1]) != 0xE0)
return -1;
setNextID(1 & frame[pos + 1]>>>3);
setNextLayer(3 & frame[pos + 1]>>>1);
setNextProtectionBit(1 ^ (1 & frame[pos + 1]));
setNextMode(3 & frame[pos + 2]>>>6); //profile
setNextSamplingFrequency(frequency_index[0xF & frame[pos + 2]>>>2]);
setNextPrivateBit(1 & frame[pos + 2]>>>1);
setNextChannel(7 & frame[pos + 2]<<2 | 3 & frame[pos + 3]>>>6); //see specif.
setNextCopyright(1 & frame[pos + 3]>>>5);
setNextOriginal(1 & frame[pos + 3]>>>4); //home
setNextEmphasis(3 & frame[pos + 3]>>>2);
// setNextFrameTimeLength(169344000.0 / getNextSamplingFrequency());
setNextFrameTimeLength(3840);
setNextBitrate(1000);
//ADTS variabel
//copyright_identification_bit 1 bslbf pos+3
//copyright_identification_start 1 bslbf pos+3
setNextSizeBase((0xFF & frame[pos + 4])<<5 | (0x1F & frame[pos + 5]>>3)); //frame_length 13 bslbf
setNextSize(getNextSizeBase());
//adts_buffer_fullness 11 bslbf
//number_of_raw_data_blocks_in_frame 2 uimsfb
return getNextLayer();
}
/**
* verify current & last header
*/
public int compareHeader()
{
if (getLastID() != getID())
return 0x1;
else if (getLastLayer() != getLayer())
return 0x2;
else if (getLastSamplingFrequency() != getSamplingFrequency())
return 0x4;
else if (getLastBitrate() != getBitrate())
return 0x8;
else if (getLastMode() != getMode())
return 0x10;
else if (getLastModeExtension() != getModeExtension())
return 0x20;
else if (getLastSize() != getSize())
return 0x40;
else
return 0;
}
/**
* display last aac header
*/
public String displayHeader()
{
return ("AAC, " + acmod[getLastMode()] + "(" + channels[getLastChannel()] + "), " + getLastSamplingFrequency() + "Hz, " + (getLastBitrate() / 1000.0) + "kbps, " + getLastSize() + "BpF");
}
}