mirror of
https://github.com/nostar/tcd.git
synced 2026-11-08 12:28:41 +00:00
53 lines
2.4 KiB
C++
53 lines
2.4 KiB
C++
// The encoder's input history and the analysis of its last three frames, kept together in one block.
|
|
//
|
|
// The analysis reads the input around a position set by two options (pitch_window_offset and
|
|
// amplitude_window_offset). With the defaults the reads stay within the 1024 input samples; with positive
|
|
// offsets they run past the newest sample into what follows in this block (the frame counter, then the analysis
|
|
// slots), and the output depends on those values. sample() returns them the same way: index i reads the i-th
|
|
// 32-bit word of the block as a float. The options are clamped so that every read stays inside the block.
|
|
#pragma once
|
|
#include <array>
|
|
#include <cstddef>
|
|
#include <cstdint>
|
|
#include <cstring>
|
|
|
|
#include "analysis.h"
|
|
|
|
namespace halfrate::enc {
|
|
|
|
constexpr int kHistorySamples = 1024;
|
|
constexpr int kFrameSamples = 160;
|
|
|
|
// The analysis of one input frame.
|
|
struct AnalysisSlot {
|
|
Spectrum pitch_spectrum; // 256-point window: pitch search
|
|
Spectrum amplitude_spectrum; // 160-point window: harmonic amplitudes
|
|
float level_db; // energy of the pitch spectrum's fitted bins, dB
|
|
float peak; // largest sample magnitude around the amplitude window
|
|
int32_t low_band; // 1: weak energy below 250 Hz (only set with low_band_threshold_db < 0)
|
|
std::array<float, kPitchCount> fit_cost; // harmonic fit cost per grid pitch
|
|
};
|
|
|
|
struct SignalHistory {
|
|
std::array<float, kHistorySamples> samples; // newest 160 at the end, scaled to +-1
|
|
int64_t frame_count; // frames pushed so far
|
|
std::array<AnalysisSlot, 3> slots; // frame n is in slots[n % 3]
|
|
|
|
static constexpr int kWords = kHistorySamples + 2 + 3 * (sizeof(AnalysisSlot) / 4);
|
|
|
|
// 32-bit word i of this block as a float, 0 <= i < kWords.
|
|
float sample(int i) const {
|
|
if (static_cast<unsigned>(i) < static_cast<unsigned>(kHistorySamples)) return samples[i];
|
|
float f;
|
|
std::memcpy(&f, reinterpret_cast<const unsigned char*>(this) + 4 * static_cast<size_t>(i), 4);
|
|
return f;
|
|
}
|
|
};
|
|
|
|
static_assert(sizeof(AnalysisSlot) == 1151 * 4, "analysis slot: 1151 words, no padding");
|
|
static_assert(sizeof(SignalHistory) >= SignalHistory::kWords * 4, "history block holds every word");
|
|
static_assert(offsetof(SignalHistory, frame_count) == kHistorySamples * 4, "frame counter right after the samples");
|
|
static_assert(offsetof(SignalHistory, slots) == (kHistorySamples + 2) * 4, "slots right after the counter");
|
|
|
|
} // namespace halfrate::enc
|