WIP vorbis frame decoding

This commit is contained in:
UnknownShadow200 2018-07-29 14:23:44 +10:00
parent c481aa32f6
commit 7e9b6a8dd9
2 changed files with 380 additions and 31 deletions

View File

@ -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,19 +337,151 @@ 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------------------------------------------------------*
@ -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;
}
@ -476,6 +754,7 @@ static ReturnCode Vorbis_DecodeSetup(struct VorbisState* state) {
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 */
@ -503,3 +782,72 @@ ReturnCode Vorbis_DecodeHeaders(struct VorbisState* state) {
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 */
}

View File

@ -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;