TAD: working kotlin decoder

This commit is contained in:
minjaesong
2025-10-30 17:08:42 +09:00
parent 480d2d8538
commit 991d035bcc
9 changed files with 405 additions and 134 deletions

View File

@@ -312,7 +312,7 @@ static void dwt_dd4_inverse_1d(float *data, int length) {
free(temp);
}
static void dwt_haar_inverse_multilevel(float *data, int length, int levels) {
static void dwt_inverse_multilevel(float *data, int length, int levels) {
// Calculate the length at the deepest level (size of low-pass after all forward DWTs)
int current_length = length;
for (int level = 0; level < levels; level++) {
@@ -588,8 +588,8 @@ static int decode_chunk(const uint8_t *input, size_t input_size, uint8_t *pcmu8_
dequantize_dwt_coefficients(quant_side, dwt_side, sample_count, sample_count, dwt_levels, max_index, quantiser_scale);
// Inverse DWT
dwt_haar_inverse_multilevel(dwt_mid, sample_count, dwt_levels);
dwt_haar_inverse_multilevel(dwt_side, sample_count, dwt_levels);
dwt_inverse_multilevel(dwt_mid, sample_count, dwt_levels);
dwt_inverse_multilevel(dwt_side, sample_count, dwt_levels);
float err[2][2] = {{0,0},{0,0}};

View File

@@ -36,9 +36,8 @@ static const float BASE_QUANTISER_WEIGHTS[] = {
// Forward declarations for internal functions
static void dwt_dd4_forward_1d(float *data, int length);
static void dwt_dd4_forward_multilevel(float *data, int length, int levels);
static void dwt_forward_multilevel(float *data, int length, int levels);
static void quantize_dwt_coefficients(const float *coeffs, int8_t *quantized, size_t count, int apply_deadzone, int chunk_size, int dwt_levels, int quant_bits, int *current_subband_index, float quantiser_scale);
static size_t encode_twobitmap(const int8_t *values, size_t count, uint8_t *output);
static inline float FCLAMP(float x, float min, float max) {
return x < min ? min : (x > max ? max : x);
@@ -190,7 +189,7 @@ static void dwt_97_forward_1d(float *data, int length) {
}
// Apply multi-level DWT (using DD-4 wavelet)
static void dwt_dd4_forward_multilevel(float *data, int length, int levels) {
static void dwt_forward_multilevel(float *data, int length, int levels) {
int current_length = length;
for (int level = 0; level < levels; level++) {
// dwt_dd4_forward_1d(data, current_length);
@@ -315,61 +314,6 @@ static void quantize_dwt_coefficients(const float *coeffs, int8_t *quantized, si
free(sideband_starts);
}
//=============================================================================
// Twobit-map Significance Map Encoding
//=============================================================================
// Twobit-map encoding: 2 bits per coefficient for common values
// 00 = 0
// 01 = +1
// 10 = -1
// 11 = other value (followed by int8_t in separate array)
static size_t encode_twobitmap(const int8_t *values, size_t count, uint8_t *output) {
// Calculate size needed for twobit map
size_t map_bytes = (count * 2 + 7) / 8; // 2 bits per coefficient
// First pass: create significance map and count "other" values
uint8_t *map = output;
memset(map, 0, map_bytes);
size_t other_count = 0;
for (size_t i = 0; i < count; i++) {
int8_t val = values[i];
uint8_t code;
if (val == 0) {
code = 0; // 00
} else if (val == 1) {
code = 1; // 01
} else if (val == -1) {
code = 2; // 10
} else {
code = 3; // 11
other_count++;
}
// Write 2-bit code into map
size_t bit_offset = i * 2;
size_t byte_idx = bit_offset / 8;
size_t bit_in_byte = bit_offset % 8;
map[byte_idx] |= (code << bit_in_byte);
}
// Second pass: write "other" values
int8_t *other_values = (int8_t*)(output + map_bytes);
size_t other_idx = 0;
for (size_t i = 0; i < count; i++) {
int8_t val = values[i];
if (val != 0 && val != 1 && val != -1) {
other_values[other_idx++] = val;
}
}
return map_bytes + other_count;
}
//=============================================================================
// Coefficient Statistics
//=============================================================================
@@ -818,8 +762,8 @@ size_t tad32_encode_chunk(const float *pcm32_stereo, size_t num_samples,
dwt_side[i] = pcm32_side[i];
}
dwt_dd4_forward_multilevel(dwt_mid, num_samples, dwt_levels);
dwt_dd4_forward_multilevel(dwt_side, num_samples, dwt_levels);
dwt_forward_multilevel(dwt_mid, num_samples, dwt_levels);
dwt_forward_multilevel(dwt_side, num_samples, dwt_levels);
// Step 3.5: Accumulate coefficient statistics if enabled
static int stats_enabled = -1;

View File

@@ -48,8 +48,13 @@ static void print_usage(const char *prog_name) {
printf("Options:\n");
printf(" -i <file> Input audio file (any format supported by FFmpeg)\n");
printf(" -o <file> Output TAD32 file (optional, auto-generated as input.qN.tad)\n");
printf(" -q <bits> Positive side quantization steps (default: 47, range: up to 127)\n");
printf(" Higher = more precision, larger files\n");
printf(" -q <level> Quality level (0-5, default: %d)\n", TAD32_QUALITY_DEFAULT);
printf(" 0 = lowest quality/smallest (max_index=31)\n");
printf(" 1 = low quality (max_index=35)\n");
printf(" 2 = medium quality (max_index=39)\n");
printf(" 3 = good quality (max_index=47) [DEFAULT]\n");
printf(" 4 = high quality (max_index=56)\n");
printf(" 5 = very high quality/largest (max_index=89)\n");
printf(" -s <scale> Quantiser scaling factor (default: 1.0, range: 0.5-4.0)\n");
printf(" Higher = more aggressive quantization, smaller files\n");
printf(" 2.0 = quantize 2x coarser than baseline\n");
@@ -65,7 +70,7 @@ int main(int argc, char *argv[]) {
char *input_file = NULL;
char *output_file = NULL;
int max_index = 47; // Default QUANT_BITS
int quality = TAD32_QUALITY_DEFAULT; // Default quality level (0-5)
float quantiser_scale = 1.0f; // Default quantiser scaling
int verbose = 0;
@@ -86,7 +91,11 @@ int main(int argc, char *argv[]) {
output_file = optarg;
break;
case 'q':
max_index = atoi(optarg);
quality = atoi(optarg);
if (quality < TAD32_QUALITY_MIN || quality > TAD32_QUALITY_MAX) {
fprintf(stderr, "Error: Quality must be in range %d-%d\n", TAD32_QUALITY_MIN, TAD32_QUALITY_MAX);
return 1;
}
break;
case 's':
quantiser_scale = atof(optarg);
@@ -113,6 +122,9 @@ int main(int argc, char *argv[]) {
return 1;
}
// Convert quality (0-5) to max_index for quantization
int max_index = tad32_quality_to_max_index(quality);
// Generate output filename if not provided
if (!output_file) {
// Allocate space for output filename
@@ -140,8 +152,8 @@ int main(int argc, char *argv[]) {
strcpy(output_file + dir_len, basename_start);
}
// Append .qNN.tad
sprintf(output_file + strlen(output_file), ".q%d.tad", max_index);
// Append .qNN.tad (use quality level for filename)
sprintf(output_file + strlen(output_file), ".q%d.tad", quality);
if (verbose) {
printf("Auto-generated output path: %s\n", output_file);
@@ -152,7 +164,7 @@ int main(int argc, char *argv[]) {
printf("%s\n", ENCODER_VENDOR_STRING);
printf("Input: %s\n", input_file);
printf("Output: %s\n", output_file);
printf("Quant bits: %d\n", max_index);
printf("Quality level: %d (max_index=%d)\n", quality, max_index);
printf("Quantiser scale: %.2f\n", quantiser_scale);
}

View File

@@ -9041,7 +9041,7 @@ static int write_tad_packet_samples(tav_encoder_t *enc, FILE *output, int sample
if (enc->verbose) {
printf("TAD32 packet: %d samples, %u bytes compressed (Q%d)\n",
sample_count, tad_payload_size, tad_quality);
sample_count, tad_payload_size, quant_size);
}
// Cleanup