diff --git a/coder/bit_alloc.h b/coder/bit_alloc.h index 3be0beb..6c35d5e 100644 --- a/coder/bit_alloc.h +++ b/coder/bit_alloc.h @@ -44,6 +44,9 @@ inline DualAllocResult allocate_bits_dual( } + for (auto& x : max_bits_in) { + x = 8; + } static thread_local std::vector bits0, bits1, max_b, active; static thread_local std::vector s2_0, s2_1, factor0, factor1, global_score; diff --git a/coder/energy_shape.h b/coder/energy_shape.h index 6e2ce2d..28bb47a 100644 --- a/coder/energy_shape.h +++ b/coder/energy_shape.h @@ -93,14 +93,24 @@ inline void apply_highfreq_attenuation(std::vector& e0, std::vector= 48.0f) return; + if (target_kbps / float(num_channels) >= 64.0f) return; - int64_t start; - if (!has_transient) - start = 3 * (int64_t)e0.size() / 8; - else - start = 4 * (int64_t)e0.size() / 8; + if (target_kbps / float(num_channels) < 48.0) { + int64_t start; + if (!has_transient && target_kbps / float(num_channels) < 48) + start = 3 * (int64_t)e0.size() / 8; + else + start = 4 * (int64_t)e0.size() / 8; + + for (int64_t i = start; i < (int64_t)e0.size(); ++i) + e0[i] *= 0.25f; + } + else { + const size_t half = e0.size() / 2; - for (int64_t i = start; i < (int64_t)e0.size(); ++i) - e0[i] *= 0.25f; + if (!has_transient) { + for (size_t i = half; i < e0.size(); ++i) + e0[i] *= 0.25f; + } + } } diff --git a/coder/quantize.h b/coder/quantize.h index 1f10520..5a261b4 100644 --- a/coder/quantize.h +++ b/coder/quantize.h @@ -8,25 +8,34 @@ inline float percentile85_abs(const std::vector& arr) { if (arr.empty()) return 0.0f; + std::vector tmp(arr.size()); - for (size_t i = 0; i < arr.size(); ++i) tmp[i] = std::abs(arr[i]); + for (size_t i = 0; i < arr.size(); ++i) + tmp[i] = std::abs(arr[i]); + size_t idx = tmp.size() * 83 / 100; std::nth_element(tmp.begin(), tmp.begin() + idx, tmp.end()); return tmp[idx]; } inline float compute_powerlaw_deadzone(float step, float rms) { - if (step < 1e-12f) return 0.0f; - + if (step < 1e-12f) + return 0.0f; + float energy_ratio = rms / step; - float mult = 0.55f + 0.10f * std::log2f(1.0f + energy_ratio); - mult = std::clamp(mult, 0.50f, 0.70f); - + return mult * step; } +struct TemporalMaskingState { + std::vector prev_effective_rms; + bool initialized = false; + + float decay_factor = 0.85f; +}; + struct QuantResult { std::vector scales; std::vector> quantized_per_level; @@ -35,124 +44,200 @@ struct QuantResult { inline QuantResult quantize_levels( const std::vector>>& coeffs_channels, const std::vector& bits_per_level, - float target_kbps) + float target_kbps, + TemporalMaskingState* tm_state = nullptr) { const int num_channels = static_cast(coeffs_channels.size()); const int band_count = static_cast(coeffs_channels[0].size()); + if (tm_state && !tm_state->initialized) { + tm_state->prev_effective_rms.assign(band_count, 0.0f); + tm_state->initialized = true; + } + std::vector scales(band_count); std::vector> quantized_per_level(band_count); float deadzone_scale = 1.0f; + if (target_kbps > 192.0f) { float t = (target_kbps - 192.0f) / (320.0f - 192.0f); t = std::clamp(t, 0.0f, 1.0f); deadzone_scale = 1.0f - std::pow(t, 1.5f); } + deadzone_scale = std::clamp(deadzone_scale, 0.0f, 1.0f); + const int block_size = std::max(4, 256 / band_count); + for (int l = 0; l < band_count; ++l) { const int bbits = bits_per_level[l]; - size_t total_samples = 0; - for (int ch = 0; ch < num_channels; ++ch) - total_samples += coeffs_channels[ch][l].size(); - if (total_samples == 0 || bbits <= 0) { + const size_t len = coeffs_channels[0][l].size(); + const size_t total_samples = len * static_cast(num_channels); + + if (len == 0 || bbits <= 0) { scales[l] = 0.0f; quantized_per_level[l].assign(total_samples, 0); + + if (tm_state) + tm_state->prev_effective_rms[l] = 0.0f; + continue; } float max_abs = 0.0f; + + const int num_blocks = static_cast(len / block_size); + + std::vector block_sum_sq(num_blocks, 0.0f); + if (bbits <= 2) { std::vector abs_vals; abs_vals.reserve(total_samples); + for (int ch = 0; ch < num_channels; ++ch) { const auto& arr = coeffs_channels[ch][l]; - for (float v : arr) { - float av = std::abs(v); + + for (size_t i = 0; i < len; ++i) { + const float v = arr[i]; + const float av = std::abs(v); + abs_vals.push_back(av); - if (av > max_abs) max_abs = av; + + if (av > max_abs) + max_abs = av; + + const int b = static_cast(i / block_size); + + if (b < num_blocks) + block_sum_sq[b] += v * v; } } - float p85 = percentile85_abs(abs_vals); - const float THRESH = 3.5f; - max_abs /= 2.0; - // max_abs = (max_abs > THRESH * p85) ? max_abs / 2.0f : p85; - // max_abs /= 2.0f; - } else { + + max_abs *= 0.5f; + } + else { for (int ch = 0; ch < num_channels; ++ch) { const auto& arr = coeffs_channels[ch][l]; - for (float v : arr) { - float av = std::abs(v); - if (av > max_abs) max_abs = av; + + for (size_t i = 0; i < len; ++i) { + const float v = arr[i]; + const float av = std::abs(v); + + if (av > max_abs) + max_abs = av; + + const int b = static_cast(i / block_size); + + if (b < num_blocks) + block_sum_sq[b] += v * v; } } } - if (max_abs < 1e-12f) max_abs = 1.0f; + + if (max_abs < 1e-12f) + max_abs = 1.0f; int sgn = 1; - if (bbits == 2) { - double sum = 0.0; - for (int ch = 0; ch < num_channels; ++ch) - for (float v : coeffs_channels[ch][l]) sum += v; - sgn = (sum >= 0.0) ? 1 : -1; - } - int max_int = (bbits > 1) ? ((1 << (bbits - 1)) - 1) : 1; - float step = max_abs / static_cast(max_int); + const int max_int = + (bbits > 1) ? ((1 << (bbits - 1)) - 1) : 1; - float sum_sq = 0.0f; - for (int ch = 0; ch < num_channels; ++ch) { - for (float v : coeffs_channels[ch][l]) { - sum_sq += v * v; + const float step = + max_abs / static_cast(max_int); + + std::vector block_deadzones(num_blocks); + + float current_prev_rms = + tm_state ? tm_state->prev_effective_rms[l] : 0.0f; + + for (int b = 0; b < num_blocks; ++b) { + const float block_rms = + std::sqrt( + block_sum_sq[b] / + static_cast(block_size * num_channels) + + 1e-12f + ); + + float effective_rms = block_rms; + + if (tm_state) { + const float masked_rms = + current_prev_rms * tm_state->decay_factor; + + effective_rms = std::max(block_rms, masked_rms); + current_prev_rms = effective_rms; } + + block_deadzones[b] = + compute_powerlaw_deadzone( + step, + effective_rms + ) * deadzone_scale; } - float rms = std::sqrt(sum_sq / static_cast(total_samples) + 1e-12f); - - float deadzone = compute_powerlaw_deadzone(step, rms); + + if (tm_state) + tm_state->prev_effective_rms[l] = current_prev_rms; std::vector quantized; - quantized.reserve(total_samples); + quantized.resize(total_samples); + + size_t out_pos = 0; for (int ch = 0; ch < num_channels; ++ch) { const auto& arr = coeffs_channels[ch][l]; - for (float v : arr) { + + int b = 0; + size_t next_boundary = block_size; + + for (size_t i = 0; i < len; ++i) { + if (i >= next_boundary) { + ++b; + next_boundary += block_size; + } + + const float v = arr[i]; + const float av = std::abs(v); + int32_t q; - float av = std::abs(v); if (bbits == 1) { - float v_clip = (sgn == 1) ? std::max(0.0f, v) : std::max(0.0f, -v); - q = static_cast(std::round(v_clip / step)); + const float v_clip = + (sgn == 1) + ? std::max(0.0f, v) + : std::max(0.0f, -v); + + q = static_cast( + std::round(v_clip / step) + ); + q = std::clamp(q, 0, 1); - } else { - if (av < deadzone * deadzone_scale) { + } + else { + if (av < block_deadzones[b]) { q = 0; - } else { - float scaled = v / step; - q = static_cast(std::round(scaled)); + } + else { + q = static_cast( + std::round(v / step) + ); } } - quantized.push_back(q); + + quantized[out_pos++] = q; } } - scales[l] = (bbits == 1) ? ((sgn == 1) ? max_abs : -max_abs) : max_abs; + scales[l] = + (bbits == 1) + ? ((sgn == 1) ? max_abs : -max_abs) + : max_abs; + quantized_per_level[l] = std::move(quantized); } - // for (auto y : quantized_per_level) { - // int64_t k = 0; - // for (auto x : y) { - // k += std::abs(x); - // // std::cout << x << ' '; - // } - // std::cout << k << ' '; - // std::cout << "| "; - // } - // std::cout << '\n'; - - return { scales, quantized_per_level }; + return { std::move(scales), std::move(quantized_per_level) }; } #endif // QUANTIZE_H \ No newline at end of file diff --git a/decoder/decoder.cpp b/decoder/decoder.cpp index 04d0e29..65bab67 100644 --- a/decoder/decoder.cpp +++ b/decoder/decoder.cpp @@ -537,4 +537,5 @@ int main(int argc, char** argv) { } return 0; -} +} // DECODER +