mirror of
https://github.com/ClassiCube/ClassiCube.git
synced 2025-09-17 03:25:14 -04:00
WIP vorbis frame decoding
This commit is contained in:
parent
c481aa32f6
commit
7e9b6a8dd9
@ -121,7 +121,12 @@ Real32 float32_unpack(struct VorbisState* state) {
|
||||
*#########################################################################################################################*/
|
||||
#define CODEBOOK_SYNC 0x564342
|
||||
struct Codebook {
|
||||
UInt32 Dimensions, Entries;
|
||||
UInt32 Dimensions, Entries, NumCodewords;
|
||||
UInt32* Codewords;
|
||||
UInt8* CodewordLens;
|
||||
Real32 MinValue, DeltaValue;
|
||||
UInt32 SequenceP, LookupType, LookupValues;
|
||||
UInt16* Multiplicands;
|
||||
};
|
||||
|
||||
UInt32 Codebook_Pow(UInt32 base, UInt32 exp) {
|
||||
@ -149,22 +154,66 @@ UInt32 lookup1_values(UInt32 entries, UInt32 dimensions) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Codebook_CalcCodewords(struct Codebook* codebook, UInt8* codewordLens, Int16 usedEntries) {
|
||||
codebook->NumCodewords = usedEntries;
|
||||
codebook->Codewords = Platform_MemAlloc(usedEntries, sizeof(UInt32), "codewords");
|
||||
codebook->CodewordLens = Platform_MemAlloc(usedEntries, sizeof(UInt8), "raw codeword lens");
|
||||
|
||||
Int32 i, j;
|
||||
UInt32 lastCodeword = UInt32_MaxValue;
|
||||
UInt32 lastLen = 32; UInt8 len;
|
||||
|
||||
for (i = 0, j = 0; i < codebook->Entries; i++) {
|
||||
len = codewordLens[i];
|
||||
if (len == UInt8_MaxValue) continue;
|
||||
codebook->CodewordLens[j] = len;
|
||||
|
||||
/* work out where to start depth of next codeword */
|
||||
UInt32 depth = min(lastLen, len);
|
||||
UInt32 mask = ~(UInt32_MaxValue >> depth); /* e.g. depth of 4, 0xF0 00 00 00 */
|
||||
|
||||
/* for example, assume Tree is like this:
|
||||
#
|
||||
0/ \
|
||||
#
|
||||
0/ \1
|
||||
# #
|
||||
$3 0/
|
||||
|
||||
*/
|
||||
|
||||
/* NOPE, THIS ASSUMPTION IS WRONG */
|
||||
UInt32 nextCodeword = (lastCodeword & mask) + (1UL << (32 - depth));
|
||||
codebook->Codewords[j] = nextCodeword;
|
||||
|
||||
lastCodeword = nextCodeword;
|
||||
lastLen = len;
|
||||
}
|
||||
}
|
||||
|
||||
ReturnCode Codebook_DecodeSetup(struct VorbisState* state, struct Codebook* codebook) {
|
||||
UInt32 sync = Vorbis_ReadBits(state, 24);
|
||||
if (sync != CODEBOOK_SYNC) return VORBIS_ERR_CODEBOOK_SYNC;
|
||||
codebook->Dimensions = Vorbis_ReadBits(state, 16);
|
||||
codebook->Entries = Vorbis_ReadBits(state, 24);
|
||||
|
||||
Int32 i, ordered = Vorbis_ReadBits(state, 1);
|
||||
UInt8* codewordLens = Platform_MemAlloc(codebook->Entries, sizeof(UInt8), "raw codeword lens");
|
||||
Int32 i, ordered = Vorbis_ReadBits(state, 1), usedEntries = 0;
|
||||
|
||||
if (!ordered) {
|
||||
Int32 sparse = Vorbis_ReadBits(state, 1);
|
||||
for (i = 0; i < codebook->Entries; i++) {
|
||||
if (sparse) {
|
||||
Int32 flag = Vorbis_ReadBits(state, 1);
|
||||
if (!flag) continue; /* TODO: unused entry */
|
||||
if (!flag) {
|
||||
codewordLens[i] = UInt8_MaxValue;
|
||||
continue; /* unused entry */
|
||||
}
|
||||
}
|
||||
|
||||
Int32 len = Vorbis_ReadBits(state, 5); len++;
|
||||
codewordLens[i] = len;
|
||||
usedEntries++;
|
||||
}
|
||||
} else {
|
||||
Int32 entry;
|
||||
@ -174,51 +223,97 @@ ReturnCode Codebook_DecodeSetup(struct VorbisState* state, struct Codebook* code
|
||||
Int32 runLen = Vorbis_ReadBits(state, runBits);
|
||||
|
||||
for (i = entry; i < entry + runLen; i++) {
|
||||
Int32 len = curLength;
|
||||
codewordLens[i] = curLength;
|
||||
}
|
||||
|
||||
entry += runLen;
|
||||
curLength++;
|
||||
if (entry > codebook->Entries) return VORBIS_ERR_CODEBOOK_ENTRY;
|
||||
}
|
||||
usedEntries = codebook->Entries;
|
||||
}
|
||||
|
||||
Int32 lookupType = Vorbis_ReadBits(state, 4);
|
||||
if (lookupType == 0) return 0;
|
||||
if (lookupType > 2) return VORBIS_ERR_CODEBOOK_LOOKUP;
|
||||
Codebook_CalcCodewords(codebook, codewordLens, usedEntries);
|
||||
Platform_MemFree(&codewordLens);
|
||||
|
||||
Real32 minValue = float32_unpack(state);
|
||||
Real32 deltaValue = float32_unpack(state);
|
||||
codebook->LookupType = Vorbis_ReadBits(state, 4);
|
||||
if (codebook->LookupType == 0) return 0;
|
||||
if (codebook->LookupType > 2) return VORBIS_ERR_CODEBOOK_LOOKUP;
|
||||
|
||||
codebook->MinValue = float32_unpack(state);
|
||||
codebook->DeltaValue = float32_unpack(state);
|
||||
Int32 valueBits = Vorbis_ReadBits(state, 4); valueBits++;
|
||||
Int32 sequenceP = Vorbis_ReadBits(state, 1);
|
||||
codebook->SequenceP = Vorbis_ReadBits(state, 1);
|
||||
|
||||
UInt32 lookupValues;
|
||||
if (lookupType == 1) {
|
||||
if (codebook->LookupType == 1) {
|
||||
lookupValues = lookup1_values(codebook->Entries, codebook->Dimensions);
|
||||
} else {
|
||||
lookupValues = codebook->Entries * codebook->Dimensions;
|
||||
}
|
||||
codebook->LookupValues = lookupValues;
|
||||
|
||||
codebook->Multiplicands = Platform_MemAlloc(lookupValues, sizeof(UInt16), "multiplicands");
|
||||
for (i = 0; i < lookupValues; i++) {
|
||||
Vorbis_ReadBits(state, valueBits);
|
||||
codebook->Multiplicands[i] = Vorbis_ReadBits(state, valueBits);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Real32* Codebook_DecodeVQ_Type1(struct Codebook* codebook, UInt32 lookupOffset) {
|
||||
Real32 last = 0.0f;
|
||||
UInt32 indexDivisor = 1, i;
|
||||
Real32* values;
|
||||
|
||||
for (i = 0; i < codebook->Dimensions; i++) {
|
||||
UInt32 offset = (lookupOffset / indexDivisor) % codebook->LookupValues;
|
||||
values[i] = codebook->Multiplicands[offset] * codebook->DeltaValue + codebook->MinValue + last;
|
||||
if (codebook->SequenceP) last = values[i];
|
||||
indexDivisor *= codebook->LookupValues;
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
Real32* Codebook_DecodeVQ_Type2(struct Codebook* codebook, UInt32 lookupOffset) {
|
||||
Real32 last = 0.0f;
|
||||
UInt32 i, offset = lookupOffset * codebook->Dimensions;
|
||||
Real32* values;
|
||||
|
||||
for (i = 0; i < codebook->Dimensions; i++, offset++) {
|
||||
values[i] = codebook->Multiplicands[offset] * codebook->DeltaValue + codebook->MinValue + last;
|
||||
if (codebook->SequenceP) last = values[i];
|
||||
}
|
||||
return values;
|
||||
}
|
||||
|
||||
UInt32 Codebook_DecodeScalar(struct Codebook* codebook) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
Real32* Codebook_DecodeVectors(struct Codebook* codebook) {
|
||||
UInt32 lookupOffset = Codebook_DecodeScalar(codebook);
|
||||
switch (codebook->LookupType) {
|
||||
case 1: return Codebook_DecodeVQ_Type1(codebook, lookupOffset);
|
||||
case 2: return Codebook_DecodeVQ_Type2(codebook, lookupOffset);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Vorbis floors-------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#define FLOOR_MAX_PARTITIONS 32
|
||||
#define FLOOR_MAX_CLASSES 16
|
||||
#define FLOOR_MAX_VALUES (FLOOR_MAX_PARTITIONS * 8)
|
||||
struct Floor {
|
||||
UInt8 Partitions, Multiplier, RangeBits;
|
||||
UInt8 Partitions, Multiplier; Int32 Range, Values;
|
||||
UInt8 PartitionClasses[FLOOR_MAX_PARTITIONS];
|
||||
UInt8 ClassDimensions[FLOOR_MAX_CLASSES];
|
||||
UInt8 ClassSubClasses[FLOOR_MAX_CLASSES];
|
||||
UInt8 ClassMasterbooks[FLOOR_MAX_CLASSES];
|
||||
Int16 SubclassBooks[FLOOR_MAX_CLASSES][8];
|
||||
Int16 XList[FLOOR_MAX_PARTITIONS * 8];
|
||||
Int16 XList[FLOOR_MAX_VALUES];
|
||||
Int32 YList[FLOOR_MAX_VALUES];
|
||||
};
|
||||
|
||||
ReturnCode Floor_DecodeSetup(struct VorbisState* state, struct Floor* floor) {
|
||||
@ -242,25 +337,157 @@ ReturnCode Floor_DecodeSetup(struct VorbisState* state, struct Floor* floor) {
|
||||
}
|
||||
|
||||
floor->Multiplier = Vorbis_ReadBits(state, 2); floor->Multiplier++;
|
||||
floor->RangeBits = Vorbis_ReadBits(state, 4);
|
||||
floor->XList[0] = 0;
|
||||
floor->XList[1] = 1 << floor->RangeBits;
|
||||
static Int16 ranges[4] = { 256, 128, 84, 64 };
|
||||
floor->Range = ranges[floor->Multiplier - 1];
|
||||
|
||||
UInt32 rangeBits = Vorbis_ReadBits(state, 4);
|
||||
floor->XList[0] = 0;
|
||||
floor->XList[1] = 1 << rangeBits;
|
||||
|
||||
for (i = 0, idx = 2; i < floor->Partitions; i++) {
|
||||
Int32 classNum = floor->PartitionClasses[i];
|
||||
for (j = 0; j < floor->ClassDimensions[classNum]; j++) {
|
||||
floor->XList[idx++] = Vorbis_ReadBits(state, floor->RangeBits);
|
||||
floor->XList[idx++] = Vorbis_ReadBits(state, rangeBits);
|
||||
}
|
||||
}
|
||||
floor->Values = idx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Floor_DecodeFrame(struct VorbisState* state, struct Floor* floor) {
|
||||
Int32 nonZero = Vorbis_ReadBits(state, 1);
|
||||
if (!nonZero) return false;
|
||||
|
||||
Int32 i, j, idx, rangeBits = iLog(floor->Range - 1);
|
||||
floor->YList[0] = Vorbis_ReadBits(state, rangeBits);
|
||||
floor->YList[1] = Vorbis_ReadBits(state, rangeBits);
|
||||
|
||||
for (i = 0, idx = 2; i < floor->Partitions; i++) {
|
||||
UInt8 class = floor->PartitionClasses[i];
|
||||
UInt8 cdim = floor->ClassDimensions[class];
|
||||
UInt8 cbits = floor->ClassSubClasses[class];
|
||||
|
||||
UInt32 csub = (1 << cbits) - 1;
|
||||
UInt32 cval = 0;
|
||||
if (cbits) {
|
||||
UInt8 bookNum = floor->ClassMasterbooks[class];
|
||||
cval = Codebook_DecodeScalar(&state->Codebooks[bookNum]);
|
||||
}
|
||||
|
||||
for (j = 0; j < cdim; j++) {
|
||||
Int16 bookNum = floor->SubclassBooks[class][cval & csub];
|
||||
cval <<= cbits;
|
||||
if (bookNum >= 0) {
|
||||
floor->YList[idx + j] = Codebook_DecodeScalar(&state->Codebooks[bookNum]);
|
||||
} else {
|
||||
floor->YList[idx + j] = 0;
|
||||
}
|
||||
}
|
||||
idx += cdim;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Int32 render_point(Int32 x0, Int32 y0, Int32 x1, Int32 y1, Int32 X) {
|
||||
Int32 dy = y1 - y0, adx = x1 - x0;
|
||||
Int32 ady = Math_AbsI(dy);
|
||||
Int32 err = ady * (X - x0);
|
||||
Int32 off = err / adx;
|
||||
|
||||
if (dy < 0) {
|
||||
return y0 - off;
|
||||
} else {
|
||||
return y0 + off;
|
||||
}
|
||||
}
|
||||
|
||||
void render_line(Int32 x0, Int32 y0, Int32 x1, Int32 y1, Int32* v) {
|
||||
Int32 dy = y1 - y0, adx = x1 - x0;
|
||||
Int32 ady = Math_AbsI(dy);
|
||||
Int32 base = dy / adx, sy;
|
||||
Int32 x = x0, y = y0, err = 0;
|
||||
|
||||
if (dy < 0) {
|
||||
sy = base - 1;
|
||||
} else {
|
||||
sy = base + 1;
|
||||
}
|
||||
|
||||
ady = ady - Math_AbsI(base) * adx;
|
||||
v[x] = y;
|
||||
|
||||
for (x = x0 + 1; x < x1; x++) {
|
||||
err = err + ady;
|
||||
if (err >= adx) {
|
||||
err = err - adx;
|
||||
y = y + sy;
|
||||
} else {
|
||||
y = y + base;
|
||||
}
|
||||
v[x] = y;
|
||||
}
|
||||
}
|
||||
|
||||
void Floor_Synthesis(struct VorbisState* state, struct Floor* floor) {
|
||||
/* amplitude value synthesis */
|
||||
Int32 YFinal[FLOOR_MAX_VALUES];
|
||||
bool Step2[FLOOR_MAX_VALUES];
|
||||
|
||||
Step2[0] = true;
|
||||
Step2[1] = true;
|
||||
YFinal[0] = floor->YList[0];
|
||||
YFinal[1] = floor->YList[1];
|
||||
|
||||
Int32 i;
|
||||
for (i = 2; i < floor->Values; i++) {
|
||||
Int32 lo_offset = low_neighbor(floor->XList, i);
|
||||
Int32 hi_offset = high_neighbor(floor->XList, i);
|
||||
|
||||
Int32 predicted = render_point(floor->XList[lo_offset], YFinal[lo_offset],
|
||||
floor->XList[hi_offset], YFinal[hi_offset], floor->XList[i]);
|
||||
|
||||
Int32 val = floor->YList[i];
|
||||
Int32 highroom = floor->Range - predicted;
|
||||
Int32 lowroom = predicted, room;
|
||||
|
||||
if (highroom < lowroom) {
|
||||
room = highroom * 2;
|
||||
} else {
|
||||
room = lowroom * 2;
|
||||
}
|
||||
|
||||
if (val) {
|
||||
Step2[lo_offset] = true;
|
||||
Step2[hi_offset] = true;
|
||||
Step2[i] = true;
|
||||
|
||||
if (val >= room) {
|
||||
if (highroom > lowroom) {
|
||||
YFinal[i] = val - lowroom + predicted;
|
||||
} else {
|
||||
YFinal[i] = predicted - val + highroom - 1;
|
||||
}
|
||||
} else {
|
||||
if (val & 1) {
|
||||
YFinal[i] = predicted - (val + 1) / 2;
|
||||
} else {
|
||||
YFinal[i] = predicted + val / 2;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Step2[i] = false;
|
||||
YFinal[i] = predicted;
|
||||
}
|
||||
}
|
||||
/* TODO: curve synthesis */
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Vorbis residues------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
#define RESIDUE_MAX_CLASSIFICATIONS 65
|
||||
struct Residue {
|
||||
struct Residue {
|
||||
UInt8 Type, Classifications, Classbook;
|
||||
UInt32 Begin, End, PartitionSize;
|
||||
UInt8 Cascade[RESIDUE_MAX_CLASSIFICATIONS];
|
||||
@ -270,7 +497,7 @@ struct Residue {
|
||||
ReturnCode Residue_DecodeSetup(struct VorbisState* state, struct Residue* residue, UInt16 type) {
|
||||
residue->Type = type;
|
||||
residue->Begin = Vorbis_ReadBits(state, 24);
|
||||
residue->End = Vorbis_ReadBits(state, 24);
|
||||
residue->End = Vorbis_ReadBits(state, 24);
|
||||
residue->PartitionSize = Vorbis_ReadBits(state, 24); residue->PartitionSize++;
|
||||
residue->Classifications = Vorbis_ReadBits(state, 6); residue->Classifications++;
|
||||
residue->Classbook = Vorbis_ReadBits(state, 8);
|
||||
@ -297,6 +524,57 @@ ReturnCode Residue_DecodeSetup(struct VorbisState* state, struct Residue* residu
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Residue_DecodeFrame(struct VorbisState* state, struct Residue* residue, Int32 ch, bool* doNotDecode) {
|
||||
UInt32 size = state->CurBlockSize / 2;
|
||||
if (residue->Type == 2) size *= ch;
|
||||
|
||||
UInt32 residueBeg = max(residue->Begin, size);
|
||||
UInt32 residueEnd = max(residue->End, size);
|
||||
|
||||
struct Codebook* classbook = &state->Codebooks[residue->Classbook];
|
||||
UInt32 classwordsPerCodeword = classbook->Dimensions;
|
||||
UInt32 pass, i, j, nToRead = residueEnd - residueBeg;
|
||||
UInt32 partitionsToRead = nToRead / residue->PartitionSize;
|
||||
|
||||
/* TODO: allocate and zero all vectors that will be returned. */
|
||||
if (nToRead == 0) return;
|
||||
for (pass = 0; pass < 8; pass++) {
|
||||
UInt32 partitionCount = 0;
|
||||
while (partitionCount < partitionsToRead) {
|
||||
|
||||
/* read classifications in pass 0 */
|
||||
if (pass == 0) {
|
||||
for (j = 0; j < ch; j++) {
|
||||
if (doNotDecode[j]) continue;
|
||||
|
||||
UInt32 temp = Codebook_DecodeScalar(&classbook);
|
||||
/* TODO: i must be signed, otherwise infinite loop */
|
||||
for (i = classwordsPerCodeword - 1; i >= 0; i--) {
|
||||
classifications[j][i + partitionCount] = temp % residue->Classifications;
|
||||
temp /= residue->Classifications;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < classwordsPerCodeword && partitionCount < partitionsToRead; i++) {
|
||||
for (j = 0; j < ch; j++) {
|
||||
if (doNotDecode[j]) continue;
|
||||
|
||||
UInt8 class = classifications[j][partitionCount];
|
||||
Int16 book = residue->Books[class][pass];
|
||||
|
||||
if (book >= 0) {
|
||||
decode partition into output vector number[j], starting at scalar
|
||||
offset[limit\_residue\_begin] + [partition\_count] * [residue\_partition\_size] using
|
||||
codebook number[vqbook] in VQ context
|
||||
}
|
||||
}
|
||||
partitionCount++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Vorbis mappings------------------------------------------------------*
|
||||
@ -304,6 +582,7 @@ ReturnCode Residue_DecodeSetup(struct VorbisState* state, struct Residue* residu
|
||||
#define MAPPING_MAX_COUPLINGS 256
|
||||
#define MAPPING_MAX_SUBMAPS 15
|
||||
struct Mapping {
|
||||
UInt8 CouplingSteps, Submaps;
|
||||
UInt8 Mux[VORBIS_MAX_CHANS];
|
||||
UInt8 FloorIdx[MAPPING_MAX_SUBMAPS];
|
||||
UInt8 ResidueIdx[MAPPING_MAX_SUBMAPS];
|
||||
@ -323,13 +602,15 @@ ReturnCode Mapping_DecodeSetup(struct VorbisState* state, struct Mapping* mappin
|
||||
Int32 couplingBits = iLog(state->Channels - 1);
|
||||
for (i = 0; i < couplingSteps; i++) {
|
||||
mapping->Magnitude[i] = Vorbis_ReadBits(state, couplingBits);
|
||||
mapping->Angle[i] = Vorbis_ReadBits(state, couplingBits);
|
||||
mapping->Angle[i] = Vorbis_ReadBits(state, couplingBits);
|
||||
if (mapping->Magnitude[i] == mapping->Angle[i]) return VORBIS_ERR_MAPPING_CHANS;
|
||||
}
|
||||
}
|
||||
|
||||
Int32 reserved = Vorbis_ReadBits(state, 2);
|
||||
if (reserved != 0) return VORBIS_ERR_MAPPING_RESERVED;
|
||||
mapping->Submaps = submaps;
|
||||
mapping->CouplingSteps = couplingSteps;
|
||||
|
||||
if (submaps > 1) {
|
||||
for (i = 0; i < state->Channels; i++) {
|
||||
@ -351,11 +632,11 @@ ReturnCode Mapping_DecodeSetup(struct VorbisState* state, struct Mapping* mappin
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Vorbis modes------------------------------------------------------*
|
||||
*-----------------------------------------------------Vorbis setup--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
struct Mode { UInt8 BlockSizeIdx, MappingIdx; };
|
||||
struct Mode { UInt8 BlockSizeFlag, MappingIdx; };
|
||||
ReturnCode Mode_DecodeSetup(struct VorbisState* state, struct Mode* mode) {
|
||||
mode->BlockSizeIdx = Vorbis_ReadBits(state, 1);
|
||||
mode->BlockSizeFlag = Vorbis_ReadBits(state, 1);
|
||||
UInt16 windowType = Vorbis_ReadBits(state, 16);
|
||||
if (windowType != 0) return VORBIS_ERR_MODE_WINDOW;
|
||||
|
||||
@ -365,10 +646,6 @@ ReturnCode Mode_DecodeSetup(struct VorbisState* state, struct Mode* mode) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*----------------------------------------------------Vorbis decoding------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
void Vorbis_Init(struct VorbisState* state, struct Stream* source) {
|
||||
Platform_MemSet(state, 0, sizeof(struct VorbisState));
|
||||
state->Source = source;
|
||||
@ -407,6 +684,7 @@ static ReturnCode Vorbis_DecodeIdentifier(struct VorbisState* state) {
|
||||
if (!Vorbis_ValidBlockSize(state->BlockSizes[1])) return VORBIS_ERR_BLOCKSIZE;
|
||||
if (state->BlockSizes[0] > state->BlockSizes[1]) return VORBIS_ERR_BLOCKSIZE;
|
||||
|
||||
if (state->Channels == 0 || state->Channels > VORBIS_MAX_CHANS) return VORBIS_ERR_CHANS;
|
||||
/* check framing flag */
|
||||
return (header[22] & 1) ? 0 : VORBIS_ERR_FRAMING;
|
||||
}
|
||||
@ -475,7 +753,8 @@ static ReturnCode Vorbis_DecodeSetup(struct VorbisState* state) {
|
||||
result = Mode_DecodeSetup(state, &state->Modes[i]);
|
||||
if (result) return result;
|
||||
}
|
||||
|
||||
|
||||
state->ModeNumBits = iLog(count - 1); /* ilog([vorbis_mode_count]-1) bits */
|
||||
UInt8 framing = Vorbis_ReadBits(state, 1);
|
||||
Vorbis_AlignBits(state);
|
||||
/* check framing flag */
|
||||
@ -502,4 +781,73 @@ ReturnCode Vorbis_DecodeHeaders(struct VorbisState* state) {
|
||||
if (result) return result;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*########################################################################################################################*
|
||||
*-----------------------------------------------------Vorbis frame--------------------------------------------------------*
|
||||
*#########################################################################################################################*/
|
||||
ReturnCode Vorbis_DecodeFrame(struct VorbisState* state) {
|
||||
Int32 i, j, packetType = Vorbis_ReadBits(state, 1);
|
||||
if (packetType) return VORBIS_ERR_FRAME_TYPE;
|
||||
|
||||
Int32 modeIdx = Vorbis_ReadBits(state, state->ModeNumBits);
|
||||
struct Mode* mode = &state->Modes[modeIdx];
|
||||
struct Mapping* mapping = &state->Mappings[mode->MappingIdx];
|
||||
|
||||
/* decode window shape */
|
||||
state->CurBlockSize = state->BlockSizes[mode->BlockSizeFlag];
|
||||
Int32 prev_window, next_window;
|
||||
/* long window lapping*/
|
||||
if (mode->BlockSizeFlag) {
|
||||
prev_window = Vorbis_ReadBits(state, 1);
|
||||
next_window = Vorbis_ReadBits(state, 1);
|
||||
}
|
||||
|
||||
/* decode floor */
|
||||
bool hasFloor[VORBIS_MAX_CHANS], hasResidue[VORBIS_MAX_CHANS];
|
||||
for (i = 0; i < state->Channels; i++) {
|
||||
Int32 submap = mapping->Mux[i];
|
||||
Int32 floorIdx = mapping->FloorIdx[submap];
|
||||
hasFloor[i] = Floor_DecodeFrame(state, &state->Floors[floorIdx]);
|
||||
hasResidue[i] = hasFloor[i];
|
||||
}
|
||||
|
||||
/* non-zero vector propogate */
|
||||
for (i = 0; i < mapping->CouplingSteps; i++) {
|
||||
Int32 magChannel = mapping->Magnitude[i];
|
||||
Int32 angChannel = mapping->Angle[i];
|
||||
|
||||
if (hasResidue[magChannel] || hasResidue[angChannel]) {
|
||||
hasResidue[magChannel] = true;
|
||||
hasResidue[angChannel] = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* decode residue */
|
||||
for (i = 0; i < mapping->Submaps; i++) {
|
||||
Int32 ch = 0;
|
||||
bool doNotDecode[VORBIS_MAX_CHANS];
|
||||
for (j = 0; j < state->Channels; j++) {
|
||||
if (mapping->Mux[j] != i) continue;
|
||||
|
||||
doNotDecode[ch] = !hasResidue[j];
|
||||
ch++;
|
||||
}
|
||||
|
||||
Int32 residueIdx = mapping->FloorIdx[i];
|
||||
Residue_DecodeFrame(state, &state->Residues[residueIdx], ch, doNotDecode);
|
||||
ch = 0;
|
||||
|
||||
for (j = 0; j < state->Channels; j++) {
|
||||
if (mapping->Mux[j] != i) continue;
|
||||
residue vector for channel[j] is set to decoded residue vector[ch]
|
||||
ch++;
|
||||
}
|
||||
}
|
||||
|
||||
/* compute dot product of floor and residue, producing audio spectrum vector */
|
||||
|
||||
/* inverse monolithic transform of audio spectrum vector */
|
||||
|
||||
}
|
@ -25,6 +25,7 @@ enum VORBIS_ERR {
|
||||
VORBIS_ERR_CODEBOOK_SYNC, VORBIS_ERR_CODEBOOK_ENTRY, VORBIS_ERR_CODEBOOK_LOOKUP,
|
||||
VORBIS_ERR_MODE_WINDOW, VORBIS_ERR_MODE_TRANSFORM,
|
||||
VORBIS_ERR_MAPPING_CHANS, VORBIS_ERR_MAPPING_RESERVED,
|
||||
VORBIS_ERR_FRAME_TYPE,
|
||||
};
|
||||
|
||||
struct Codebook; struct Floor; struct Residue; struct Mapping; struct Mode;
|
||||
@ -33,8 +34,8 @@ struct VorbisState {
|
||||
UInt32 NumBits; /* Number of bits in Bits buffer*/
|
||||
struct Stream* Source; /* Source for filling Input buffer */
|
||||
|
||||
Int32 Channels, SampleRate;
|
||||
Int32 BlockSizes[2];
|
||||
UInt8 Channels, ModeNumBits; UInt16 CurBlockSize;
|
||||
Int32 SampleRate; Int32 BlockSizes[2];
|
||||
|
||||
struct Codebook* Codebooks;
|
||||
struct Floor* Floors;
|
||||
|
Loading…
x
Reference in New Issue
Block a user