95
Assets/NLayer/Decoder/LayerIIDecoder.cs
Normal file
95
Assets/NLayer/Decoder/LayerIIDecoder.cs
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* NLayer - A C# MPEG1/2/2.5 audio decoder
|
||||
*
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace NLayer.Decoder
|
||||
{
|
||||
// there's not much we have to do here... table selection, granule count, scalefactor selection
|
||||
class LayerIIDecoder : LayerIIDecoderBase
|
||||
{
|
||||
static internal bool GetCRC(MpegFrame frame, ref uint crc)
|
||||
{
|
||||
return LayerIIDecoderBase.GetCRC(frame, SelectTable(frame), _allocLookupTable, true, ref crc);
|
||||
}
|
||||
|
||||
// figure out which rate table to use... basically, high-rate full, high-rate limited, low-rate limited, low-rate minimal, and LSF.
|
||||
static int[] SelectTable(IMpegFrame frame)
|
||||
{
|
||||
var bitRatePerChannel = (frame.BitRate / (frame.ChannelMode == MpegChannelMode.Mono ? 1 : 2)) / 1000;
|
||||
|
||||
if (frame.Version == MpegVersion.Version1)
|
||||
{
|
||||
if ((bitRatePerChannel >= 56 && bitRatePerChannel <= 80) || (frame.SampleRate == 48000 && bitRatePerChannel >= 56))
|
||||
{
|
||||
return _rateLookupTable[0]; // high-rate, 27 subbands
|
||||
}
|
||||
else if (frame.SampleRate != 48000 && bitRatePerChannel >= 96)
|
||||
{
|
||||
return _rateLookupTable[1]; // high-rate, 30 subbands
|
||||
}
|
||||
else if (frame.SampleRate != 32000 && bitRatePerChannel <= 48)
|
||||
{
|
||||
return _rateLookupTable[2]; // low-rate, 8 subbands
|
||||
}
|
||||
else
|
||||
{
|
||||
return _rateLookupTable[3]; // low-rate, 12 subbands
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return _rateLookupTable[4]; // lsf, 30 subbands
|
||||
}
|
||||
}
|
||||
|
||||
// this table tells us which allocation lookup list to use for each subband
|
||||
// note that each row has the same number of elements as there are subbands for that type...
|
||||
static readonly int[][] _rateLookupTable = {
|
||||
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
||||
new int[] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0 }, // high-rate, 27 subbands
|
||||
new int[] { 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 }, // high-rate, 30 subbands
|
||||
new int[] { 4, 4, 5, 5, 5, 5, 5, 5 }, // low-rate, 7 subbands
|
||||
new int[] { 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 }, // low-rate, 12 subbands
|
||||
new int[] { 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }, // lsf, 30 subbands
|
||||
};
|
||||
|
||||
// this tells the decode logic: a) how many bits per allocation, and b) how many bits per sample for the give allocation value
|
||||
// if negative, read -x bits and handle as a group
|
||||
static readonly int[][] _allocLookupTable = {
|
||||
// bits 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
||||
new int[] { 2, 0, -5, -7, 16 }, // 0 (II)
|
||||
new int[] { 3, 0, -5, -7, 3,-10, 4, 5, 16 }, // 1 (II)
|
||||
new int[] { 4, 0, -5, -7, 3,-10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 16 }, // 2 (II)
|
||||
new int[] { 4, 0, -5, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 }, // 3 (II)
|
||||
new int[] { 4, 0, -5, -7,-10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }, // 4 (II, 4, 4 bits per alloc)
|
||||
new int[] { 3, 0, -5, -7,-10, 4, 5, 6, 9 }, // 5 (II, 4, 3 bits per alloc)
|
||||
new int[] { 4, 0, -5, -7, 3,-10, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 }, // 6 (II)
|
||||
new int[] { 2, 0, -5, -7, 3 }, // 7 (II, 4, 2 bits per alloc)
|
||||
};
|
||||
|
||||
internal LayerIIDecoder() : base(_allocLookupTable, 3) { }
|
||||
|
||||
protected override int[] GetRateTable(IMpegFrame frame)
|
||||
{
|
||||
return SelectTable(frame);
|
||||
}
|
||||
|
||||
protected override void ReadScaleFactorSelection(IMpegFrame frame, int[][] scfsi, int channels)
|
||||
{
|
||||
// we'll never have more than 30 active subbands
|
||||
for (int sb = 0; sb < 30; sb++)
|
||||
{
|
||||
for (int ch = 0; ch < channels; ch++)
|
||||
{
|
||||
if (scfsi[ch][sb] == 2)
|
||||
{
|
||||
scfsi[ch][sb] = frame.ReadBits(2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user