mirror of
https://github.com/WinampDesktop/winamp.git
synced 2024-11-28 07:40:47 +01:00
171 lines
4.0 KiB
C++
171 lines
4.0 KiB
C++
#include "MPEGHeader.h"
|
|
#include <math.h>
|
|
|
|
// [mpeg_version][layer][index]
|
|
static const int bitrates[4][4][15] =
|
|
{
|
|
{
|
|
// MPEG-2.5
|
|
{ 0,},
|
|
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000}, // Layer 3
|
|
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000}, // Layer 2
|
|
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000}, // Layer 1
|
|
},
|
|
|
|
{
|
|
// invalid
|
|
{ 0, },
|
|
{ 0, },
|
|
{ 0, },
|
|
{ 0, },
|
|
},
|
|
|
|
{
|
|
// MPEG-2
|
|
{ 0,},
|
|
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000}, // Layer 3
|
|
{ 0, 8000, 16000, 24000, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000}, // Layer 2
|
|
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 144000, 160000, 176000, 192000, 224000, 256000}, // Layer 1
|
|
},
|
|
|
|
{
|
|
// MPEG-1
|
|
{ 0,},
|
|
{ 0, 32000, 40000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000}, // Layer 3
|
|
{ 0, 32000, 48000, 56000, 64000, 80000, 96000, 112000, 128000, 160000, 192000, 224000, 256000, 320000, 384000}, // Layer 2
|
|
{ 0, 32000, 64000, 96000, 128000, 160000, 192000, 224000, 256000, 288000, 320000, 352000, 384000, 416000, 448000}, // Layer 1
|
|
},
|
|
};
|
|
|
|
// [mpeg_version][index]
|
|
static const int sample_rates[4][4] =
|
|
{
|
|
{11025, 12000, 8000, 0}, // MPEG-2.5
|
|
{0, },
|
|
{22050, 24000, 16000, 0}, // MPEG-2
|
|
{44100, 48000, 32000, 0}, // MPEG-1
|
|
};
|
|
|
|
// [mpeg_version][layer]
|
|
static const int samples_per_frame[4][4] =
|
|
{
|
|
// Layer 3, Layer 2, Layer 1
|
|
{ 0, 576, 1152, 384}, // MPEG2.5
|
|
{ 0, },
|
|
{ 0, 576, 1152, 384}, // MPEG2
|
|
{ 0, 1152, 1152, 384}, // MPEG1
|
|
};
|
|
|
|
// [layer]
|
|
static const int bits_per_slot[4] = { 0, 8, 8, 32 };
|
|
|
|
void MPEGHeader::ReadBuffer(const uint8_t *buffer)
|
|
{
|
|
sync = ((uint16_t)buffer[0] << 3) | (buffer[1] >> 5);
|
|
mpeg_version = (buffer[1] >> 3) & 3;
|
|
layer = (buffer[1] >> 1) & 3;
|
|
protection = (buffer[1]) & 1;
|
|
bitrate_index = (buffer[2] >> 4) & 0xF;
|
|
sample_rate_index = (buffer[2] >> 2) & 3;
|
|
padding_bit = (buffer[2] >> 1) & 1;
|
|
private_bit = buffer[2] & 1;
|
|
channel_mode = (buffer[3] >> 6) & 3;
|
|
mode_extension = (buffer[3] >> 4) & 3;
|
|
copyright = (buffer[3] >> 3) & 1;
|
|
original = (buffer[3] >> 2) & 1;
|
|
emphasis = (buffer[3]) & 3;
|
|
}
|
|
|
|
bool MPEGHeader::IsSync() const
|
|
{
|
|
return sync == 0x07FF
|
|
&& layer != LayerError
|
|
&& mpeg_version != MPEG_Error
|
|
&& bitrate_index != 15
|
|
&& bitrate_index != 0
|
|
&& sample_rate_index != 3
|
|
&& !(mpeg_version == MPEG2 && layer != Layer3)
|
|
&& !(mpeg_version == MPEG2_5 && layer != Layer3);
|
|
}
|
|
|
|
int MPEGHeader::GetBitrate() const
|
|
{
|
|
return bitrates[mpeg_version][layer][bitrate_index];
|
|
}
|
|
|
|
int MPEGHeader::HeaderSize() const
|
|
{
|
|
if (protection == CRC)
|
|
return 4 + 2; // 32bits frame header, 16bits CRC
|
|
else
|
|
return 4; // 32bits frame ehader
|
|
}
|
|
|
|
int MPEGHeader::GetSampleRate() const
|
|
{
|
|
return sample_rates[mpeg_version][sample_rate_index];
|
|
}
|
|
|
|
bool MPEGHeader::IsCopyright() const
|
|
{
|
|
return copyright == 1;
|
|
}
|
|
bool MPEGHeader::IsCRC() const
|
|
{
|
|
return protection == CRC;
|
|
}
|
|
|
|
bool MPEGHeader::IsOriginal() const
|
|
{
|
|
return original == 1;
|
|
}
|
|
|
|
int MPEGHeader::GetSamplesPerFrame() const
|
|
{
|
|
return samples_per_frame[mpeg_version][layer];
|
|
}
|
|
|
|
int MPEGHeader::FrameSize() const
|
|
{
|
|
int nBitsPerSlot;
|
|
int nAvgSlotsPerFrame;
|
|
|
|
nBitsPerSlot = bits_per_slot[layer];
|
|
|
|
nAvgSlotsPerFrame = (GetSamplesPerFrame() * (bitrates[mpeg_version][layer][bitrate_index] / nBitsPerSlot)) / sample_rates[mpeg_version][sample_rate_index];
|
|
|
|
return (nAvgSlotsPerFrame + padding_bit) * nBitsPerSlot / 8;
|
|
}
|
|
|
|
int MPEGHeader::GetLayer() const
|
|
{
|
|
switch(layer)
|
|
{
|
|
case Layer1:
|
|
return 1;
|
|
case Layer2:
|
|
return 2;
|
|
case Layer3:
|
|
return 3;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
int MPEGHeader::GetNumChannels() const
|
|
{
|
|
switch(channel_mode)
|
|
{
|
|
case Stereo:
|
|
return 2;
|
|
case JointStereo:
|
|
return 2;
|
|
case DualChannel:
|
|
return 2;
|
|
case Mono:
|
|
return 1;
|
|
default:
|
|
return 0;
|
|
}
|
|
}
|