Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
ts::WaveStreams Struct Reference

The two raw streams that make up one wave: a signed delta per sample, and a shift exponent per 16-sample block packed two to a byte. More...

#include <tabulasonora/wave_rom.hpp>

Public Attributes

std::vector< std::uint8_t > delta
 One signed byte per sample, sample_count + 1 long — the ping-pong sampler turns around on index sample_count, so that extra step is read.
std::vector< std::uint8_t > preamble_delta
 The deltas between the 32-sample exponent-block boundary and the data start — scale_phase of them, empty for an aligned wave.
std::vector< std::uint8_t > scale
 Shift-exponent nibbles: byte i >> 5 holds the exponents for samples i, with the low nibble used when (i >> 4) & 1 is zero and the high nibble otherwise.
std::int32_t sample_count = 0
 Number of decodable samples.
std::int32_t data_start = 0
 The descriptor's data start, exactly as given — not rounded to a block.
std::int32_t scale_phase = 0
 Where data_start falls inside its 32-sample exponent block, i.e.

Detailed Description

The two raw streams that make up one wave: a signed delta per sample, and a shift exponent per 16-sample block packed two to a byte.

Member Data Documentation

◆ delta

std::vector<std::uint8_t> ts::WaveStreams::delta

One signed byte per sample, sample_count + 1 long — the ping-pong sampler turns around on index sample_count, so that extra step is read.

◆ preamble_delta

std::vector<std::uint8_t> ts::WaveStreams::preamble_delta

The deltas between the 32-sample exponent-block boundary and the data start — scale_phase of them, empty for an aligned wave.

The engine's decoder does not begin at the data start: its predictor is zero at the block boundary below it, and these deltas are integrated in on the way. Their sum rides under every sample of the wave as a constant — measured live, Crash Cym.1's eleven preamble deltas sum to exactly −0.041015625, and subtracting the module's predictor trace from this engine's decode of the same wave leaves precisely that constant at correlation 1.0. This is the in-signal DC the verification article documents on the crashes and the sine kick.

◆ scale

std::vector<std::uint8_t> ts::WaveStreams::scale

Shift-exponent nibbles: byte i >> 5 holds the exponents for samples i, with the low nibble used when (i >> 4) & 1 is zero and the high nibble otherwise.

◆ sample_count

std::int32_t ts::WaveStreams::sample_count = 0

Number of decodable samples.

◆ data_start

std::int32_t ts::WaveStreams::data_start = 0

The descriptor's data start, exactly as given — not rounded to a block.

◆ scale_phase

std::int32_t ts::WaveStreams::scale_phase = 0

Where data_start falls inside its 32-sample exponent block, i.e.

loop & 0x1F.

The codec carries no absolute value per block, only differences, so a wave may legitimately begin partway into an exponent block and end partway through another. Decoding just has to index the exponents by the absolute sample position rather than by the offset into what was read, which is what this carries.


The documentation for this struct was generated from the following file: