Skip to content

Commit

Permalink
Decode LFE blocks and band extension
Browse files Browse the repository at this point in the history
  • Loading branch information
Thealexbarney committed Jan 3, 2018
1 parent 46d4203 commit c9b9866
Show file tree
Hide file tree
Showing 13 changed files with 569 additions and 45 deletions.
191 changes: 191 additions & 0 deletions C/band_extension.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
#include "band_extension.h"
#include "tables.h"
#include "utility.h"
#include <math.h>

void ApplyBandExtension(block* block)
{
if (!block->BandExtensionEnabled || !block->HasExtensionData) return;

for (int i = 0; i < block->ChannelCount; i++)
{
ApplyBandExtensionChannel(&block->Channels[i]);
}
}

void ApplyBandExtensionChannel(channel* channel)
{
const int groupAUnit = channel->Block->QuantizationUnitCount;
int* scaleFactors = channel->ScaleFactors;
double* spectra = channel->Spectra;
double scales[6];
int* values = channel->BexValues;

const bex_group* bex_info = &BexGroupInfo[channel->Block->QuantizationUnitCount - 13];
const int bandCount = bex_info->band_count;
const int groupBUnit = bex_info->group_b_unit;
const int groupCUnit = bex_info->group_c_unit;

const int totalUnits = max(groupCUnit, 22);
const int bexQuantUnits = totalUnits - groupAUnit;

const int groupABin = QuantUnitToCoeffIndex[groupAUnit];
const int groupBBin = QuantUnitToCoeffIndex[groupBUnit];
const int groupCBin = QuantUnitToCoeffIndex[groupCUnit];
const int totalBins = QuantUnitToCoeffIndex[totalUnits];

FillHighFrequencies(spectra, groupABin, groupBBin, groupCBin, totalBins);

double groupAScale, groupBScale, groupCScale;
double rate, scale, mult;

switch (channel->BexMode)
{
case 0:
switch (bandCount)
{
case 3:
scales[0] = BexMode0Bands3[0][values[0]];
scales[1] = BexMode0Bands3[1][values[0]];
scales[2] = BexMode0Bands3[2][values[1]];
scales[3] = BexMode0Bands3[3][values[2]];
scales[4] = BexMode0Bands3[4][values[3]];
break;
case 4:
scales[0] = BexMode0Bands4[0][values[0]];
scales[1] = BexMode0Bands4[1][values[0]];
scales[2] = BexMode0Bands4[2][values[1]];
scales[3] = BexMode0Bands4[3][values[2]];
scales[4] = BexMode0Bands4[4][values[3]];
break;
case 5:
scales[0] = BexMode0Bands5[0][values[0]];
scales[1] = BexMode0Bands5[1][values[1]];
scales[2] = BexMode0Bands5[2][values[1]];
break;
}

scales[bexQuantUnits - 1] = SpectrumScale[scaleFactors[groupAUnit]];

AddNoiseToSpectrum(channel, QuantUnitToCoeffIndex[totalUnits - 1],
QuantUnitToCoeffCount[totalUnits - 1]);
ScaleBexQuantUnits(spectra, scales, groupAUnit, totalUnits);
break;
case 1:
for (int i = groupAUnit; i < totalUnits; i++)
{
scales[i - groupAUnit] = SpectrumScale[scaleFactors[i]];
}

AddNoiseToSpectrum(channel, groupABin, totalBins - groupABin);
ScaleBexQuantUnits(spectra, scales, groupAUnit, totalUnits);
break;
case 2:
groupAScale = BexMode2Scale[values[0]];
groupBScale = BexMode2Scale[values[1]];

for (int i = groupABin; i < groupBBin; i++)
{
spectra[i] *= groupAScale;
}

for (int i = groupBBin; i < groupCBin; i++)
{
spectra[i] *= groupBScale;
}
return;
case 3:
rate = pow(2, BexMode3Rate[values[1]]);
scale = BexMode3Initial[values[0]];
for (int i = groupABin; i < totalBins; i++)
{
scale *= rate;
spectra[i] *= scale;
}
return;
case 4:
mult = BexMode4Multiplier[values[0]];
groupAScale = 0.7079468 * mult;
groupBScale = 0.5011902 * mult;
groupCScale = 0.3548279 * mult;

for (int i = groupABin; i < groupBBin; i++)
{
spectra[i] *= groupAScale;
}

for (int i = groupBBin; i < groupCBin; i++)
{
spectra[i] *= groupBScale;
}

for (int i = groupCBin; i < totalBins; i++)
{
spectra[i] *= groupCScale;
}
}
}

void ScaleBexQuantUnits(double* spectra, double* scales, int startUnit, int totalUnits)
{
for (int i = startUnit; i < totalUnits; i++)
{
for (int k = QuantUnitToCoeffIndex[i]; k < QuantUnitToCoeffIndex[i + 1]; k++)
{
spectra[k] *= scales[i - startUnit];
}
}
}

void FillHighFrequencies(double* spectra, int groupABin, int groupBBin, int groupCBin, int totalBins)
{
for (int i = 0; i < groupBBin - groupABin; i++)
{
spectra[groupABin + i] = spectra[groupABin - i - 1];
}

for (int i = 0; i < groupCBin - groupBBin; i++)
{
spectra[groupBBin + i] = spectra[groupBBin - i - 1];
}

for (int i = 0; i < totalBins - groupCBin; i++)
{
spectra[groupCBin + i] = spectra[groupCBin - i - 1];
}
}

void AddNoiseToSpectrum(channel* channel, int index, int count)
{
if (!channel->rng.initialized)
{
int* sf = channel->ScaleFactors;
const unsigned short seed = (unsigned short)(543 * (sf[8] + sf[12] + sf[15] + 1));
rng_init(&channel->rng, seed);
}
for (int i = 0; i < count; i++)
{
channel->Spectra[i + index] = rng_next(&channel->rng) / 65535.0 * 2.0 - 1.0;
}
}

void rng_init(rng_cxt* rng, unsigned short seed)
{
const int startValue = 0x4D93 * (seed ^ (seed >> 14));

rng->stateA = (unsigned short)(3 - startValue);
rng->stateB = (unsigned short)(2 - startValue);
rng->stateC = (unsigned short)(1 - startValue);
rng->stateD = (unsigned short)(0 - startValue);
rng->initialized = TRUE;
}

unsigned short rng_next(rng_cxt* rng)
{
const unsigned short t = (unsigned short)(rng->stateD ^ (rng->stateD << 5));
rng->stateD = rng->stateC;
rng->stateC = rng->stateB;
rng->stateB = rng->stateA;
rng->stateA = (unsigned short)(t ^ rng->stateA ^ ((t ^ (rng->stateA >> 5)) >> 4));
return rng->stateA;
}
13 changes: 13 additions & 0 deletions C/band_extension.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include "structures.h"

void ApplyBandExtension(block* block);
void ApplyBandExtensionChannel(channel* channel);

void ScaleBexQuantUnits(double* spectra, double* scales, int startUnit, int totalUnits);
void FillHighFrequencies(double* spectra, int groupABin, int groupBBin, int groupCBin, int totalBins);
void AddNoiseToSpectrum(channel* channel, int index, int count);

void rng_init(rng_cxt* rng, unsigned short seed);
unsigned short rng_next(rng_cxt* rng);
20 changes: 18 additions & 2 deletions C/decoder.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
#include <string.h>
#include "decoder.h"
#include "unpack.h"
#include "quantization.h"
#include "tables.h"
#include "imdct.h"
#include <math.h>
#include "utility.h"
#include "band_extension.h"

at9_status Decode(atrac9_handle* handle, const unsigned char* audio, unsigned char* pcm, int* bytesUsed)
{
Expand All @@ -15,8 +17,8 @@ at9_status Decode(atrac9_handle* handle, const unsigned char* audio, unsigned ch

PcmFloatToShort(&handle->frame, (short*)pcm);


*bytesUsed = br.position / 8;
*bytesUsed = br.position / 8;
return ERR_SUCCESS;
}

Expand All @@ -31,6 +33,7 @@ at9_status DecodeFrame(frame* frame, bit_reader_cxt* br)
DequantizeSpectra(block);
ApplyIntensityStereo(block);
ScaleSpectrumBlock(block);
ApplyBandExtension(block);
ImdctBlock(block);
}

Expand Down Expand Up @@ -97,3 +100,16 @@ void ApplyIntensityStereo(block* block)
}
}
}

int GetCodecInfo(atrac9_handle* handle, CodecInfo * pCodecInfo)
{
pCodecInfo->channels = handle->config.ChannelCount;
pCodecInfo->channelConfigIndex = handle->config.ChannelConfigIndex;
pCodecInfo->samplingRate = handle->config.SampleRate;
pCodecInfo->superframeSize = handle->config.SuperframeBytes;
pCodecInfo->framesInSuperframe = handle->config.FramesPerSuperframe;
pCodecInfo->frameSamples = handle->config.FrameSamples;
pCodecInfo->wlength = handle->wlength;
memcpy(pCodecInfo->configData, handle->config.ConfigData, CONFIG_DATA_SIZE);
return ERR_SUCCESS;
}
3 changes: 2 additions & 1 deletion C/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ at9_status Decode(atrac9_handle* handle, const unsigned char* audio, unsigned ch
at9_status DecodeFrame(frame* frame, bit_reader_cxt* br);
void ImdctBlock(block* block);
void ApplyIntensityStereo(block* block);
void PcmFloatToShort(frame* frame, short* pcmOut);
void PcmFloatToShort(frame* frame, short* pcmOut);
int GetCodecInfo(atrac9_handle* handle, CodecInfo* pCodecInfo);
4 changes: 3 additions & 1 deletion C/error_codes.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ typedef enum at9_status
ERR_UNPACK_GRAD_END_UNIT_INVALID, // start_unit > end_unit

ERR_UNPACK_SCALE_FACTOR_MODE_INVALID,
ERR_UNPACK_SCALE_FACTOR_OOB
ERR_UNPACK_SCALE_FACTOR_OOB,

ERR_UNPACK_EXTENSION_DATA_INVALID
} at9_status;

#define ERROR_CHECK(x) do { \
Expand Down
34 changes: 8 additions & 26 deletions C/libatrac9.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,47 +5,29 @@
#include "decinit.h"
#include "decoder.h"

HANDLE_ATRAC9 GetHandle()
void* Atrac9GetHandle()
{
struct atrac9_handle* handle = malloc(sizeof(atrac9_handle));
memset(handle, 0, sizeof(atrac9_handle));
return handle;
}

void ReleaseHandle(HANDLE_ATRAC9 handle)
void Atrac9ReleaseHandle(void* handle)
{
free(handle);
}

int DecInit(HANDLE_ATRAC9 handle, unsigned char * pConfigData, int wlength)
int Atrac9InitDecoder(void* handle, unsigned char * pConfigData)
{
if (wlength != 16)
{
return -1;
}

ERROR_CHECK(init_decoder(handle, pConfigData, wlength));

return 0;
return init_decoder(handle, pConfigData, 16);
}

int DecDecode(HANDLE_ATRAC9 handle, const unsigned char * pStreamBuffer, int * pNByteUsed, void * pPcmBuffer)
int Atrac9Decode(void* handle, const unsigned char *pAtrac9Buffer, short *pPcmBuffer, int *pNBytesUsed)
{
at9_status status = Decode(handle, pStreamBuffer, pPcmBuffer, pNByteUsed);
return status;
return Decode(handle, pAtrac9Buffer, (unsigned char*)pPcmBuffer, pNBytesUsed);
}

int GetCodecInfo(HANDLE_ATRAC9 handle, CodecInfo * pCodecInfo)
int Atrac9GetCodecInfo(void* handle, Atrac9CodecInfo * pCodecInfo)
{
atrac9_handle* h = handle;

pCodecInfo->channels = h->config.ChannelCount;
pCodecInfo->channelConfigIndex = h->config.ChannelConfigIndex;
pCodecInfo->samplingRate = h->config.SampleRate;
pCodecInfo->superframeSize = h->config.SuperframeBytes;
pCodecInfo->framesInSuperframe = h->config.FramesPerSuperframe;
pCodecInfo->frameSamples = h->config.FrameSamples;
pCodecInfo->wlength = h->wlength;
memcpy(pCodecInfo->configData, h->config.ConfigData, CONFIG_DATA_SIZE);
return ERR_SUCCESS;
return GetCodecInfo(handle, (CodecInfo*)pCodecInfo);
}
17 changes: 9 additions & 8 deletions C/libatrac9.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ extern "C" {
#define DLLEXPORT __declspec(dllimport)
#endif

typedef void* HANDLE_ATRAC9;
#define ATRAC9_CONFIG_DATA_SIZE 4

typedef struct {
int channels;
Expand All @@ -19,15 +19,16 @@ typedef struct {
int framesInSuperframe;
int frameSamples;
int wlength;
unsigned char configData[4];
} CodecInfo;
unsigned char configData[ATRAC9_CONFIG_DATA_SIZE];
} Atrac9CodecInfo;

DLLEXPORT HANDLE_ATRAC9 GetHandle(void);
DLLEXPORT void ReleaseHandle(HANDLE_ATRAC9 handle);
DLLEXPORT void* Atrac9GetHandle(void);
DLLEXPORT void Atrac9ReleaseHandle(void* handle);

DLLEXPORT int DecInit(HANDLE_ATRAC9 handle, unsigned char *pConfigData, int wlength);
DLLEXPORT int DecDecode(HANDLE_ATRAC9 handle, const unsigned char *pStreamBuffer, int *pNByteUsed, void *pPcmBuffer);
DLLEXPORT int GetCodecInfo(HANDLE_ATRAC9 handle, CodecInfo *pCodecInfo);
DLLEXPORT int Atrac9InitDecoder(void* handle, unsigned char *pConfigData);
DLLEXPORT int Atrac9Decode(void* handle, const unsigned char *pAtrac9Buffer, short *pPcmBuffer, int *pNBytesUsed);

DLLEXPORT int Atrac9GetCodecInfo(void* handle, Atrac9CodecInfo *pCodecInfo);

#ifdef __cplusplus
}
Expand Down
2 changes: 2 additions & 0 deletions C/libatrac9.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="band_extension.h" />
<ClInclude Include="bit_allocation.h" />
<ClInclude Include="bit_reader.h" />
<ClInclude Include="decinit.h" />
Expand All @@ -141,6 +142,7 @@
<ClInclude Include="utility.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="band_extension.c" />
<ClCompile Include="bit_allocation.c" />
<ClCompile Include="bit_reader.c" />
<ClCompile Include="decinit.c" />
Expand Down
Loading

0 comments on commit c9b9866

Please sign in to comment.