|
|
|
/*
|
|
|
|
stores information after we found a header.
|
|
|
|
Copyright (C) 2000 Martin Vogt
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU Library General Public License as published by
|
|
|
|
the Free Software Foundation.
|
|
|
|
|
|
|
|
For more information look at the file COPYRIGHT in this package
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include "mpegAudioHeader.h"
|
|
|
|
|
|
|
|
#define DEBUG_HEADER(x)
|
|
|
|
//#define DEBUG_HEADER(x) x
|
|
|
|
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
static const int frequencies[3][3]= {
|
|
|
|
{44100,48000,32000}, // MPEG 1
|
|
|
|
{22050,24000,16000}, // MPEG 2
|
|
|
|
{11025,12000,8000} // MPEG 2.5
|
|
|
|
};
|
|
|
|
|
|
|
|
static int translate[3][2][16] = { { { 2,0,0,2,2,2,3,3,3,3,3,3,3,3,3,2 } ,
|
|
|
|
{ 2,0,0,0,0,0,0,2,2,2,3,3,3,3,3,2 } } ,
|
|
|
|
{ { 2,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2 } ,
|
|
|
|
{ 2,0,0,0,0,0,0,2,2,2,2,2,2,2,2,2 } } ,
|
|
|
|
{ { 2,1,1,2,2,2,3,3,3,3,3,3,3,3,3,2 } ,
|
|
|
|
{ 2,1,1,1,1,1,1,2,2,2,3,3,3,3,3,2 } } };
|
|
|
|
|
|
|
|
|
|
|
|
static int sblims[5] = { 8 , 12 , 27, 30 , 30 };
|
|
|
|
|
|
|
|
|
|
|
|
static const int bitrate[2][3][15]= {
|
|
|
|
// MPEG 1
|
|
|
|
{{0,32,64,96,128,160,192,224,256,288,320,352,384,416,448},
|
|
|
|
{0,32,48,56,64,80,96,112,128,160,192,224,256,320,384},
|
|
|
|
{0,32,40,48,56,64,80,96,112,128,160,192,224,256,320}},
|
|
|
|
|
|
|
|
// MPEG 2
|
|
|
|
{{0,32,48,56,64,80,96,112,128,144,160,176,192,224,256},
|
|
|
|
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160},
|
|
|
|
{0,8,16,24,32,40,48,56,64,80,96,112,128,144,160}}
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
MpegAudioHeader::MpegAudioHeader() {
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
MpegAudioHeader::~MpegAudioHeader() {
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MpegAudioHeader::getChannelbitrate() {
|
|
|
|
cout << "getChannelbitrate not implemented"<<endl;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int MpegAudioHeader::parseHeader(unsigned char* buf){
|
|
|
|
|
|
|
|
int c;
|
|
|
|
int mpeg25=false;
|
|
|
|
|
|
|
|
|
|
|
|
// Analyzing
|
|
|
|
header[0]=buf[0];
|
|
|
|
header[1]=buf[1];
|
|
|
|
header[2]=buf[2];
|
|
|
|
header[3]=buf[3];
|
|
|
|
|
|
|
|
c=buf[1];
|
|
|
|
lmpeg25=false;
|
|
|
|
if ( (c&0xf0) == 0xe0) {
|
|
|
|
lmpeg25=true;
|
|
|
|
}
|
|
|
|
|
|
|
|
c&=0xf;
|
|
|
|
protection=c&1;
|
|
|
|
layer=4-((c>>1)&3);
|
|
|
|
// we catch the layer==4 error later, for now go on with parsing
|
|
|
|
version=(int)(((c>>3)&1)^1);
|
|
|
|
if ((version==0) && lmpeg25) {
|
|
|
|
DEBUG_HEADER(cout << "wrong lsf/mpeg25 combination"<<endl;)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
c=buf[2];
|
|
|
|
|
|
|
|
c=((c))>>1;
|
|
|
|
padding=(c&1);
|
|
|
|
c>>=1;
|
|
|
|
frequency=(int)(c&3);
|
|
|
|
c>>=2;
|
|
|
|
bitrateindex=(int)c;
|
|
|
|
if(bitrateindex>=15) {
|
|
|
|
DEBUG_HEADER(cout << "bitrateindex error"<<endl;)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
c=buf[3];
|
|
|
|
|
|
|
|
c=((unsigned int)(c))>>4;
|
|
|
|
extendedmode=c&3;
|
|
|
|
mode=(int)(c>>2);
|
|
|
|
|
|
|
|
|
|
|
|
// Making information
|
|
|
|
inputstereo= (mode==_MODE_SINGLE)?0:1;
|
|
|
|
|
|
|
|
//
|
|
|
|
// frequency can be 0,1 or 2 but the mask above allows 3 as well
|
|
|
|
// check now.
|
|
|
|
if (frequency > 2) {
|
|
|
|
DEBUG_HEADER(cout << "frequency value out of range"<<endl;)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// does not belong here should be in the layer specific parts. [START]
|
|
|
|
//
|
|
|
|
|
|
|
|
switch(layer) {
|
|
|
|
case 3:
|
|
|
|
subbandnumber=0;
|
|
|
|
stereobound=0;
|
|
|
|
tableindex=0;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
tableindex = translate[frequency][inputstereo][bitrateindex];
|
|
|
|
subbandnumber = sblims[tableindex];
|
|
|
|
stereobound = subbandnumber;
|
|
|
|
/*
|
|
|
|
Now merge the tableindex, for the bitalloclengthtable
|
|
|
|
*/
|
|
|
|
tableindex=tableindex>>1;
|
|
|
|
if(mode==_MODE_SINGLE)stereobound=0;
|
|
|
|
if(mode==_MODE_JOINT)stereobound=(extendedmode+1)<<2;
|
|
|
|
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
subbandnumber=MAXSUBBAND;
|
|
|
|
stereobound=subbandnumber;
|
|
|
|
tableindex=0;
|
|
|
|
if(mode==_MODE_SINGLE)stereobound=0;
|
|
|
|
if(mode==_MODE_JOINT)stereobound=(extendedmode+1)<<2;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
DEBUG_HEADER(cout <<"unknown layer"<<endl;)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// does not belong here should be in the layer specific parts. [END]
|
|
|
|
//
|
|
|
|
frequencyHz=frequencies[version+lmpeg25][frequency];
|
|
|
|
// framesize & slots
|
|
|
|
if(layer==1) {
|
|
|
|
if (frequencyHz <= 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
framesize=(12000*bitrate[version][0][bitrateindex])/frequencyHz;
|
|
|
|
|
|
|
|
if(frequency==_FREQUENCY_44100 && padding)framesize++;
|
|
|
|
framesize<<=2;
|
|
|
|
} else {
|
|
|
|
int freq=frequencyHz<<version;
|
|
|
|
if (freq <= 0) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
framesize=(144000*bitrate[version][layer-1][bitrateindex])/freq;
|
|
|
|
|
|
|
|
if(padding)framesize++;
|
|
|
|
if(layer==3) {
|
|
|
|
if(version)
|
|
|
|
layer3slots=framesize-((mode==_MODE_SINGLE)?9:17)
|
|
|
|
-(protection?0:2)
|
|
|
|
-4;
|
|
|
|
else
|
|
|
|
layer3slots=framesize-((mode==_MODE_SINGLE)?17:32)
|
|
|
|
-(protection?0:2)
|
|
|
|
-4;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (framesize <= 0) {
|
|
|
|
DEBUG_HEADER(cout << "framesize negative"<<endl;)
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int MpegAudioHeader::getpcmperframe() {
|
|
|
|
int s;
|
|
|
|
|
|
|
|
s=32;
|
|
|
|
if(layer==3) {
|
|
|
|
s*=18;
|
|
|
|
if(version==0)s*=2;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
s*=SCALEBLOCK;
|
|
|
|
if(layer==2)s*=3;
|
|
|
|
}
|
|
|
|
|
|
|
|
return s;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MpegAudioHeader::copyTo(MpegAudioHeader* dest) {
|
|
|
|
dest->protection=protection;
|
|
|
|
dest->layer=layer;
|
|
|
|
dest->version=version;
|
|
|
|
dest->padding=padding;
|
|
|
|
dest->frequency=frequency;
|
|
|
|
dest->frequencyHz=frequencyHz;
|
|
|
|
dest->bitrateindex=bitrateindex;
|
|
|
|
dest->extendedmode=extendedmode;
|
|
|
|
dest->mode=mode;
|
|
|
|
dest->inputstereo=inputstereo;
|
|
|
|
dest->channelbitrate=channelbitrate;
|
|
|
|
dest->tableindex=tableindex;
|
|
|
|
dest->subbandnumber=subbandnumber;
|
|
|
|
dest->stereobound=stereobound;
|
|
|
|
dest->framesize=framesize;
|
|
|
|
dest->layer3slots=layer3slots;
|
|
|
|
dest->lmpeg25=lmpeg25;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void MpegAudioHeader::print(const char* name) {
|
|
|
|
cout << "MpegAudioHeader [START]:"<<name<<endl;
|
|
|
|
printf("header:%1x%1x%1x%1x\n",header[0],header[1],header[2],header[3]);
|
|
|
|
cout << "getProtection:"<<getProtection()<<endl;
|
|
|
|
cout << "getLayer:"<<getLayer()<<endl;
|
|
|
|
cout << "getVersion:"<<getVersion()<<endl;
|
|
|
|
cout << "getPadding:"<<getPadding()<<endl;
|
|
|
|
cout << "getFrequency:"<<getFrequency()<<endl;
|
|
|
|
cout << "getFrequencyHz:"<<getFrequencyHz()<<endl;
|
|
|
|
cout << "getBitrateindex:"<<getBitrateindex()<<endl;
|
|
|
|
cout << "getExtendedmode:"<<getExtendedmode()<<endl;
|
|
|
|
cout << "getMode():"<<getMode()<<endl;
|
|
|
|
cout << "getInputstereo:"<<getInputstereo()<<endl;
|
|
|
|
cout << "getChannelbitrate:"<<getChannelbitrate()<<endl;
|
|
|
|
cout << "getTableindex:"<<getTableindex()<<endl;
|
|
|
|
cout << "getSubbandnumber:"<<getSubbandnumber()<<endl;
|
|
|
|
cout << "getStereobound:"<<getStereobound()<<endl;
|
|
|
|
cout << "getFramesize:"<<getFramesize()<<endl;
|
|
|
|
cout << "getLayer3slots:"<<getLayer3slots()<<endl;
|
|
|
|
cout << "getpcmperframe:"<<getpcmperframe()<<endl;
|
|
|
|
cout << "MpegAudioHeader [END]:"<<name<<endl;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|