mirror of
https://github.com/curioustorvald/tsvm.git
synced 2026-03-07 11:51:49 +09:00
TAD: quantised value stats
This commit is contained in:
@@ -382,9 +382,17 @@ typedef struct {
|
||||
size_t capacity;
|
||||
} CoeffAccumulator;
|
||||
|
||||
typedef struct {
|
||||
int16_t *data;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
} QuantAccumulator;
|
||||
|
||||
// Global accumulators for statistics
|
||||
static CoeffAccumulator *mid_accumulators = NULL;
|
||||
static CoeffAccumulator *side_accumulators = NULL;
|
||||
static QuantAccumulator *mid_quant_accumulators = NULL;
|
||||
static QuantAccumulator *side_quant_accumulators = NULL;
|
||||
static int num_subbands = 0;
|
||||
static int stats_initialized = 0;
|
||||
static int stats_dwt_levels = 0;
|
||||
@@ -397,6 +405,8 @@ static void init_statistics(int dwt_levels) {
|
||||
|
||||
mid_accumulators = calloc(num_subbands, sizeof(CoeffAccumulator));
|
||||
side_accumulators = calloc(num_subbands, sizeof(CoeffAccumulator));
|
||||
mid_quant_accumulators = calloc(num_subbands, sizeof(QuantAccumulator));
|
||||
side_quant_accumulators = calloc(num_subbands, sizeof(QuantAccumulator));
|
||||
|
||||
for (int i = 0; i < num_subbands; i++) {
|
||||
mid_accumulators[i].capacity = 1024;
|
||||
@@ -406,6 +416,14 @@ static void init_statistics(int dwt_levels) {
|
||||
side_accumulators[i].capacity = 1024;
|
||||
side_accumulators[i].data = malloc(side_accumulators[i].capacity * sizeof(float));
|
||||
side_accumulators[i].count = 0;
|
||||
|
||||
mid_quant_accumulators[i].capacity = 1024;
|
||||
mid_quant_accumulators[i].data = malloc(mid_quant_accumulators[i].capacity * sizeof(int16_t));
|
||||
mid_quant_accumulators[i].count = 0;
|
||||
|
||||
side_quant_accumulators[i].capacity = 1024;
|
||||
side_quant_accumulators[i].data = malloc(side_quant_accumulators[i].capacity * sizeof(int16_t));
|
||||
side_quant_accumulators[i].count = 0;
|
||||
}
|
||||
|
||||
stats_initialized = 1;
|
||||
@@ -442,6 +460,37 @@ static void accumulate_coefficients(const float *coeffs, int dwt_levels, int chu
|
||||
free(sideband_starts);
|
||||
}
|
||||
|
||||
static void accumulate_quantized(const int16_t *quant, int dwt_levels, int chunk_size, QuantAccumulator *accumulators) {
|
||||
int first_band_size = chunk_size >> dwt_levels;
|
||||
|
||||
int *sideband_starts = malloc((dwt_levels + 2) * sizeof(int));
|
||||
sideband_starts[0] = 0;
|
||||
sideband_starts[1] = first_band_size;
|
||||
for (int i = 2; i <= dwt_levels + 1; i++) {
|
||||
sideband_starts[i] = sideband_starts[i-1] + (first_band_size << (i-2));
|
||||
}
|
||||
|
||||
for (int s = 0; s <= dwt_levels; s++) {
|
||||
size_t start = sideband_starts[s];
|
||||
size_t end = sideband_starts[s + 1];
|
||||
size_t band_size = end - start;
|
||||
|
||||
// Expand capacity if needed
|
||||
while (accumulators[s].count + band_size > accumulators[s].capacity) {
|
||||
accumulators[s].capacity *= 2;
|
||||
accumulators[s].data = realloc(accumulators[s].data,
|
||||
accumulators[s].capacity * sizeof(int16_t));
|
||||
}
|
||||
|
||||
// Copy coefficients
|
||||
memcpy(accumulators[s].data + accumulators[s].count,
|
||||
quant + start, band_size * sizeof(int16_t));
|
||||
accumulators[s].count += band_size;
|
||||
}
|
||||
|
||||
free(sideband_starts);
|
||||
}
|
||||
|
||||
static void calculate_coeff_stats(const float *coeffs, size_t count, CoeffStats *stats) {
|
||||
if (count == 0) {
|
||||
stats->min = stats->q1 = stats->median = stats->q3 = stats->max = 0.0f;
|
||||
@@ -531,6 +580,77 @@ static void print_histogram(const float *coeffs, size_t count, const char *title
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
int16_t value;
|
||||
size_t count;
|
||||
float percentage;
|
||||
} ValueFrequency;
|
||||
|
||||
static int compare_value_frequency(const void *a, const void *b) {
|
||||
const ValueFrequency *va = (const ValueFrequency*)a;
|
||||
const ValueFrequency *vb = (const ValueFrequency*)b;
|
||||
// Sort by count descending
|
||||
if (vb->count > va->count) return 1;
|
||||
if (vb->count < va->count) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_top5_quantized_values(const int16_t *quant, size_t count, const char *title) {
|
||||
if (count == 0) {
|
||||
fprintf(stderr, " %s: No data\n", title);
|
||||
return;
|
||||
}
|
||||
|
||||
// Create a hash map to count frequencies
|
||||
// For simplicity, we'll use an array with a reasonable range
|
||||
// Find min/max first
|
||||
int16_t min_val = quant[0];
|
||||
int16_t max_val = quant[0];
|
||||
for (size_t i = 1; i < count; i++) {
|
||||
if (quant[i] < min_val) min_val = quant[i];
|
||||
if (quant[i] > max_val) max_val = quant[i];
|
||||
}
|
||||
|
||||
int range = max_val - min_val + 1;
|
||||
if (range > 100000) {
|
||||
fprintf(stderr, " %s: Value range too large for analysis\n", title);
|
||||
return;
|
||||
}
|
||||
|
||||
// Count frequencies
|
||||
size_t *freq = calloc(range, sizeof(size_t));
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
freq[quant[i] - min_val]++;
|
||||
}
|
||||
|
||||
// Find all unique values with their frequencies
|
||||
ValueFrequency *values = malloc(range * sizeof(ValueFrequency));
|
||||
int unique_count = 0;
|
||||
for (int i = 0; i < range; i++) {
|
||||
if (freq[i] > 0) {
|
||||
values[unique_count].value = min_val + i;
|
||||
values[unique_count].count = freq[i];
|
||||
values[unique_count].percentage = (float)(freq[i] * 100.0) / count;
|
||||
unique_count++;
|
||||
}
|
||||
}
|
||||
|
||||
// Sort by frequency
|
||||
qsort(values, unique_count, sizeof(ValueFrequency), compare_value_frequency);
|
||||
|
||||
// Print top 5
|
||||
fprintf(stderr, " %s Top 5 Values:\n", title);
|
||||
int print_count = (unique_count < 5) ? unique_count : 10;
|
||||
for (int i = 0; i < print_count; i++) {
|
||||
fprintf(stderr, " %6d: %8zu occurrences (%5.2f%%)\n",
|
||||
values[i].value, values[i].count, values[i].percentage);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
free(freq);
|
||||
free(values);
|
||||
}
|
||||
|
||||
void tad32_print_statistics(void) {
|
||||
if (!stats_initialized) return;
|
||||
|
||||
@@ -604,6 +724,33 @@ void tad32_print_statistics(void) {
|
||||
print_histogram(side_accumulators[s].data, side_accumulators[s].count, band_name);
|
||||
}
|
||||
|
||||
// Print quantized values statistics
|
||||
fprintf(stderr, "\n=== TAD Quantized Values Statistics (after quantization) ===\n");
|
||||
|
||||
// Print Mid channel quantized values
|
||||
fprintf(stderr, "\nMid Channel Quantized Values:\n");
|
||||
for (int s = 0; s < num_subbands; s++) {
|
||||
char band_name[32];
|
||||
if (s == 0) {
|
||||
snprintf(band_name, sizeof(band_name), "LL (L%d)", stats_dwt_levels);
|
||||
} else {
|
||||
snprintf(band_name, sizeof(band_name), "H (L%d)", stats_dwt_levels - s + 1);
|
||||
}
|
||||
print_top5_quantized_values(mid_quant_accumulators[s].data, mid_quant_accumulators[s].count, band_name);
|
||||
}
|
||||
|
||||
// Print Side channel quantized values
|
||||
fprintf(stderr, "\nSide Channel Quantized Values:\n");
|
||||
for (int s = 0; s < num_subbands; s++) {
|
||||
char band_name[32];
|
||||
if (s == 0) {
|
||||
snprintf(band_name, sizeof(band_name), "LL (L%d)", stats_dwt_levels);
|
||||
} else {
|
||||
snprintf(band_name, sizeof(band_name), "H (L%d)", stats_dwt_levels - s + 1);
|
||||
}
|
||||
print_top5_quantized_values(side_quant_accumulators[s].data, side_quant_accumulators[s].count, band_name);
|
||||
}
|
||||
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
@@ -613,12 +760,18 @@ void tad32_free_statistics(void) {
|
||||
for (int i = 0; i < num_subbands; i++) {
|
||||
free(mid_accumulators[i].data);
|
||||
free(side_accumulators[i].data);
|
||||
free(mid_quant_accumulators[i].data);
|
||||
free(side_quant_accumulators[i].data);
|
||||
}
|
||||
free(mid_accumulators);
|
||||
free(side_accumulators);
|
||||
free(mid_quant_accumulators);
|
||||
free(side_quant_accumulators);
|
||||
|
||||
mid_accumulators = NULL;
|
||||
side_accumulators = NULL;
|
||||
mid_quant_accumulators = NULL;
|
||||
side_quant_accumulators = NULL;
|
||||
stats_initialized = 0;
|
||||
}
|
||||
|
||||
@@ -671,7 +824,7 @@ size_t tad32_encode_chunk(const float *pcm32_stereo, size_t num_samples,
|
||||
// Step 3.5: Accumulate coefficient statistics if enabled
|
||||
static int stats_enabled = -1;
|
||||
if (stats_enabled == -1) {
|
||||
stats_enabled = getenv("TAD_COEFF_STATS") != NULL;
|
||||
stats_enabled = 1;//getenv("TAD_COEFF_STATS") != NULL;
|
||||
if (stats_enabled) {
|
||||
init_statistics(dwt_levels);
|
||||
}
|
||||
@@ -685,6 +838,12 @@ size_t tad32_encode_chunk(const float *pcm32_stereo, size_t num_samples,
|
||||
quantize_dwt_coefficients(dwt_mid, quant_mid, num_samples, 1, num_samples, dwt_levels, max_index, NULL);
|
||||
quantize_dwt_coefficients(dwt_side, quant_side, num_samples, 1, num_samples, dwt_levels, max_index, NULL);
|
||||
|
||||
// Step 4.5: Accumulate quantized coefficient statistics if enabled
|
||||
if (stats_enabled) {
|
||||
accumulate_quantized(quant_mid, dwt_levels, num_samples, mid_quant_accumulators);
|
||||
accumulate_quantized(quant_side, dwt_levels, num_samples, side_quant_accumulators);
|
||||
}
|
||||
|
||||
// Step 5: Encode with pure bitplanes (quant_bits + 1 bits per coefficient)
|
||||
uint8_t *temp_buffer = malloc(num_samples * 4 * sizeof(int32_t));
|
||||
size_t mid_size = encode_bitplanes(quant_mid, num_samples, temp_buffer, max_index);
|
||||
|
||||
Reference in New Issue
Block a user