-
Notifications
You must be signed in to change notification settings - Fork 13
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Very direct port from C# version. Same files, function/variable names. Band extension isn't handled. Tables are pre-generated instead of being created at runtime. Extensive testing has not been done.
- Loading branch information
1 parent
109e63b
commit 46d4203
Showing
28 changed files
with
5,556 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
#include "bit_allocation.h" | ||
#include "tables.h" | ||
#include "utility.h" | ||
#include <string.h> | ||
|
||
at9_status CreateGradient(block* block) | ||
{ | ||
int valueCount = block->GradientEndValue - block->GradientStartValue; | ||
int unitCount = block->GradientEndUnit - block->GradientStartUnit; | ||
|
||
for (int i = 0; i < block->GradientEndUnit; i++) | ||
{ | ||
block->Gradient[i] = block->GradientStartValue; | ||
} | ||
|
||
for (int i = block->GradientEndUnit; i <= block->QuantizationUnitCount; i++) | ||
{ | ||
block->Gradient[i] = block->GradientEndValue; | ||
} | ||
if (unitCount <= 0) return ERR_SUCCESS; | ||
if (valueCount == 0) return ERR_SUCCESS; | ||
|
||
const unsigned char* curve = GradientCurves[unitCount - 1]; | ||
if (valueCount <= 0) | ||
{ | ||
double scale = (-valueCount - 1) / 31.0; | ||
int baseVal = block->GradientStartValue - 1; | ||
for (int i = block->GradientStartUnit; i < block->GradientEndUnit; i++) | ||
{ | ||
block->Gradient[i] = baseVal - (int)(curve[i - block->GradientStartUnit] * scale); | ||
} | ||
} | ||
else | ||
{ | ||
double scale = (valueCount - 1) / 31.0; | ||
int baseVal = block->GradientStartValue + 1; | ||
for (int i = block->GradientStartUnit; i < block->GradientEndUnit; i++) | ||
{ | ||
block->Gradient[i] = baseVal + (int)(curve[i - block->GradientStartUnit] * scale); | ||
} | ||
} | ||
|
||
return ERR_SUCCESS; | ||
} | ||
|
||
void CalculateMask(channel* channel) | ||
{ | ||
memset(channel->PrecisionMask, 0, sizeof(channel->PrecisionMask)); | ||
for (int i = 1; i < channel->Block->QuantizationUnitCount; i++) | ||
{ | ||
const int delta = channel->ScaleFactors[i] - channel->ScaleFactors[i - 1]; | ||
if (delta > 1) | ||
{ | ||
channel->PrecisionMask[i] += min(delta - 1, 5); | ||
} | ||
else if (delta < -1) | ||
{ | ||
channel->PrecisionMask[i - 1] += min(delta * -1 - 1, 5); | ||
} | ||
} | ||
} | ||
|
||
void CalculatePrecisions(channel* channel) | ||
{ | ||
block* block = channel->Block; | ||
|
||
if (block->GradientMode != 0) | ||
{ | ||
for (int i = 0; i < block->QuantizationUnitCount; i++) | ||
{ | ||
channel->Precisions[i] = channel->ScaleFactors[i] + channel->PrecisionMask[i] - block->Gradient[i]; | ||
if (channel->Precisions[i] > 0) | ||
{ | ||
switch (block->GradientMode) | ||
{ | ||
case 1: | ||
channel->Precisions[i] /= 2; | ||
break; | ||
case 2: | ||
channel->Precisions[i] = 3 * channel->Precisions[i] / 8; | ||
break; | ||
case 3: | ||
channel->Precisions[i] /= 4; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
for (int i = 0; i < block->QuantizationUnitCount; i++) | ||
{ | ||
channel->Precisions[i] = channel->ScaleFactors[i] - block->Gradient[i]; | ||
} | ||
} | ||
|
||
for (int i = 0; i < block->QuantizationUnitCount; i++) | ||
{ | ||
if (channel->Precisions[i] < 1) | ||
{ | ||
channel->Precisions[i] = 1; | ||
} | ||
} | ||
|
||
for (int i = 0; i < block->GradientBoundary; i++) | ||
{ | ||
channel->Precisions[i]++; | ||
} | ||
|
||
for (int i = 0; i < block->QuantizationUnitCount; i++) | ||
{ | ||
channel->PrecisionsFine[i] = 0; | ||
if (channel->Precisions[i] > 15) | ||
{ | ||
channel->PrecisionsFine[i] = channel->Precisions[i] - 15; | ||
channel->Precisions[i] = 15; | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#pragma once | ||
#include "unpack.h" | ||
|
||
at9_status CreateGradient(block* block); | ||
void CalculateMask(channel* channel); | ||
void CalculatePrecisions(channel* channel); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#include "bit_reader.h" | ||
#include "utility.h" | ||
|
||
static int peek_int_fallback(bit_reader_cxt* br, int bit_count); | ||
|
||
void init_bit_reader_cxt(bit_reader_cxt* br, const void * buffer) | ||
{ | ||
br->buffer = buffer; | ||
br->position = 0; | ||
} | ||
|
||
int read_int(bit_reader_cxt* br, const int bits) | ||
{ | ||
const int value = peek_int(br, bits); | ||
br->position += bits; | ||
return value; | ||
} | ||
|
||
int read_signed_int(bit_reader_cxt* br, const int bits) | ||
{ | ||
const int value = peek_int(br, bits); | ||
br->position += bits; | ||
return SignExtend32(value, bits); | ||
} | ||
|
||
int read_offset_binary(bit_reader_cxt* br, const int bits) | ||
{ | ||
const int offset = 1 << (bits - 1); | ||
const int value = peek_int(br, bits) - offset; | ||
br->position += bits; | ||
return value; | ||
} | ||
|
||
int peek_int(bit_reader_cxt* br, const int bits) | ||
{ | ||
const int byte_index = br->position / 8; | ||
const int bit_index = br->position % 8; | ||
const unsigned char* buffer = br->buffer; | ||
|
||
if (bits <= 9) | ||
{ | ||
int value = buffer[byte_index] << 8 | buffer[byte_index + 1]; | ||
value &= 0xFFFF >> bit_index; | ||
value >>= 16 - bits - bit_index; | ||
return value; | ||
} | ||
|
||
if (bits <= 17) | ||
{ | ||
int value = buffer[byte_index] << 16 | buffer[byte_index + 1] << 8 | buffer[byte_index + 2]; | ||
value &= 0xFFFFFF >> bit_index; | ||
value >>= 24 - bits - bit_index; | ||
return value; | ||
} | ||
|
||
if (bits <= 25) | ||
{ | ||
int value = buffer[byte_index] << 24 | ||
| buffer[byte_index + 1] << 16 | ||
| buffer[byte_index + 2] << 8 | ||
| buffer[byte_index + 3]; | ||
|
||
value &= (int)(0xFFFFFFFF >> bit_index); | ||
value >>= 32 - bits - bit_index; | ||
return value; | ||
} | ||
return peek_int_fallback(br, bits); | ||
} | ||
|
||
void align_position(bit_reader_cxt* br, const unsigned int multiple) | ||
{ | ||
const int position = br->position; | ||
if (position % multiple == 0) | ||
{ | ||
return; | ||
} | ||
|
||
br->position = position + multiple - position % multiple; | ||
} | ||
|
||
static int peek_int_fallback(bit_reader_cxt* br, int bit_count) | ||
{ | ||
int value = 0; | ||
int byte_index = br->position / 8; | ||
int bit_index = br->position % 8; | ||
const unsigned char* buffer = br->buffer; | ||
|
||
while (bit_count > 0) | ||
{ | ||
if (bit_index >= 8) | ||
{ | ||
bit_index = 0; | ||
byte_index++; | ||
} | ||
|
||
int bits_to_read = bit_count; | ||
if (bits_to_read > 8 - bit_index) | ||
{ | ||
bits_to_read = 8 - bit_index; | ||
} | ||
|
||
const int mask = 0xFF >> bit_index; | ||
const int current_byte = (mask & buffer[byte_index]) >> (8 - bit_index - bits_to_read); | ||
|
||
value = (value << bits_to_read) | current_byte; | ||
bit_index += bits_to_read; | ||
bit_count -= bits_to_read; | ||
} | ||
return value; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
#pragma once | ||
|
||
typedef struct { | ||
const unsigned char * buffer; | ||
int position; | ||
} bit_reader_cxt; | ||
|
||
void init_bit_reader_cxt(bit_reader_cxt* br, const void * buffer); | ||
int peek_int(bit_reader_cxt* br, const int bits); | ||
int read_int(bit_reader_cxt* br, const int bits); | ||
int read_signed_int(bit_reader_cxt* br, const int bits); | ||
int read_offset_binary(bit_reader_cxt* br, const int bits); | ||
void align_position(bit_reader_cxt* br, const unsigned int multiple); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,110 @@ | ||
#include "bit_reader.h" | ||
#include "decinit.h" | ||
#include "error_codes.h" | ||
#include "structures.h" | ||
#include "tables.h" | ||
#include <string.h> | ||
|
||
static int BlockTypeToChannelCount(BlockType block_type); | ||
|
||
at9_status init_decoder(atrac9_handle* handle, unsigned char* config_data, int wlength) | ||
{ | ||
ERROR_CHECK(init_config_data(&handle->config, config_data)); | ||
ERROR_CHECK(init_frame(handle)); | ||
handle->wlength = wlength; | ||
handle->initialized = 1; | ||
return ERR_SUCCESS; | ||
} | ||
|
||
at9_status init_config_data(ConfigData* config, unsigned char* config_data) | ||
{ | ||
memcpy(config->ConfigData, config_data, CONFIG_DATA_SIZE); | ||
ERROR_CHECK(read_config_data(config)); | ||
|
||
config->FramesPerSuperframe = 1 << config->SuperframeIndex; | ||
config->SuperframeBytes = config->FrameBytes << config->SuperframeIndex; | ||
|
||
config->ChannelConfig = ChannelConfigs[config->ChannelConfigIndex]; | ||
config->ChannelCount = config->ChannelConfig.ChannelCount; | ||
config->SampleRate = SampleRates[config->SampleRateIndex]; | ||
config->HighSampleRate = config->SampleRateIndex > 7; | ||
config->FrameSamplesPower = SamplingRateIndexToFrameSamplesPower[config->SampleRateIndex]; | ||
config->FrameSamples = 1 << config->FrameSamplesPower; | ||
config->SuperframeSamples = config->FrameSamples * config->FramesPerSuperframe; | ||
|
||
return ERR_SUCCESS; | ||
} | ||
|
||
at9_status read_config_data(ConfigData* config) | ||
{ | ||
bit_reader_cxt br; | ||
init_bit_reader_cxt(&br, &config->ConfigData); | ||
|
||
const int header = read_int(&br, 8); | ||
config->SampleRateIndex = read_int(&br, 4); | ||
config->ChannelConfigIndex = read_int(&br, 3); | ||
const int validation_bit = read_int(&br, 1); | ||
config->FrameBytes = read_int(&br, 11) + 1; | ||
config->SuperframeIndex = read_int(&br, 2); | ||
|
||
if (header != 0xFE || validation_bit != 0) | ||
{ | ||
return ERR_BAD_CONFIG_DATA; | ||
} | ||
|
||
return ERR_SUCCESS; | ||
} | ||
|
||
at9_status init_frame(atrac9_handle* handle) | ||
{ | ||
const int block_count = handle->config.ChannelConfig.BlockCount; | ||
handle->frame.config = &handle->config; | ||
|
||
for (int i = 0; i < block_count; i++) | ||
{ | ||
ERROR_CHECK(init_block(&handle->frame.Blocks[i], &handle->frame, i)); | ||
} | ||
|
||
return ERR_SUCCESS; | ||
} | ||
|
||
at9_status init_block(block* block, frame* parent_frame, int block_index) | ||
{ | ||
block->Frame = parent_frame; | ||
block->BlockIndex = block_index; | ||
block->config = parent_frame->config; | ||
block->BlockType = block->config->ChannelConfig.Types[block_index]; | ||
block->ChannelCount = BlockTypeToChannelCount(block->BlockType); | ||
|
||
for (int i = 0; i < block->ChannelCount; i++) | ||
{ | ||
ERROR_CHECK(init_channel(&block->Channels[i], block, i)); | ||
} | ||
|
||
return ERR_SUCCESS; | ||
} | ||
|
||
at9_status init_channel(channel* channel, block* parent_block, int channel_index) | ||
{ | ||
channel->Block = parent_block; | ||
channel->Frame = parent_block->Frame; | ||
channel->config = parent_block->config; | ||
channel->ChannelIndex = channel_index; | ||
channel->mdct.bits = parent_block->config->FrameSamplesPower; | ||
return ERR_SUCCESS; | ||
} | ||
|
||
static int BlockTypeToChannelCount(BlockType block_type) | ||
{ | ||
switch (block_type) | ||
{ | ||
case Mono: | ||
return 1; | ||
case Stereo: | ||
return 2; | ||
case LFE: | ||
return 1; | ||
default: | ||
return 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
#pragma once | ||
|
||
#include "error_codes.h" | ||
#include "structures.h" | ||
|
||
at9_status init_decoder(atrac9_handle* handle, unsigned char * config_data, int wlength); | ||
at9_status init_config_data(ConfigData* config, unsigned char * config_data); | ||
at9_status read_config_data(ConfigData* config); | ||
at9_status init_frame(atrac9_handle* handle); | ||
at9_status init_block(block* block, frame* parent_frame, int block_index); | ||
at9_status init_channel(channel* channel, block* parent_block, int channel_index); |
Oops, something went wrong.