Tabula Sonora 0.1.0
A native C++20 implementation of the Roland Sound Canvas VA synth voice
Loading...
Searching...
No Matches
wave_descriptor.hpp
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <span>
5
6namespace ts {
7
16 static constexpr int stride = 0x16;
17
19 int region = 0;
21 int loop = 0;
23 int end = 0;
25 int start = 0;
27 int root_key = 0;
29 int fine_tune = 0;
32 int flags = 0;
33
35 [[nodiscard]] constexpr int bank() const noexcept { return (region >> 4) & 1; }
36
38 [[nodiscard]] constexpr bool reverse() const noexcept { return ((flags >> 2) & 1) != 0; }
39
41 [[nodiscard]] constexpr bool ping_pong() const noexcept { return (flags & 1) != 0; }
42
44 [[nodiscard]] constexpr double native_pitch() const noexcept
45 {
46 return root_key + ((1024.0 - fine_tune) / 1000.0);
47 }
48
50 [[nodiscard]] static constexpr WaveDescriptor
51 parse(std::span<const std::uint8_t> record) noexcept
52 {
53 // The three position fields are 20-bit, stored most-significant nibble first.
54 const int loop = ((record[0x01] & 0x0F) << 16) | (record[0x02] << 8) | record[0x03];
55 const int end = ((record[0x07] & 0x0F) << 16) | (record[0x08] << 8) | record[0x09];
56 const int start = ((record[0x0B] & 0x0F) << 16) | (record[0x0C] << 8) | record[0x0D];
57
58 return WaveDescriptor{
59 .region = record[0x00] & 0x7F,
60 .loop = loop,
61 .end = end,
62 .start = start,
63 .root_key = record[0x06],
64 .fine_tune = record[0x04] | (record[0x05] << 8),
65 .flags = record[0x0A],
66 };
67 }
68
69 [[nodiscard]] friend constexpr bool operator==(const WaveDescriptor&,
70 const WaveDescriptor&) noexcept = default;
71};
72
75 int key_low = 0;
76 int key_high = 0;
77 int wave = 0;
78};
79
80} // namespace ts
Definition control_decode.hpp:7
A key range within a multisample and the wave it selects.
Definition wave_descriptor.hpp:74
int key_high
Definition wave_descriptor.hpp:76
int key_low
Definition wave_descriptor.hpp:75
int wave
Definition wave_descriptor.hpp:77
One entry of the wave-descriptor table: where a sample lives in the wave ROM, how it is tuned,...
Definition wave_descriptor.hpp:14
static constexpr WaveDescriptor parse(std::span< const std::uint8_t > record) noexcept
Parses a descriptor from its stride raw bytes.
Definition wave_descriptor.hpp:51
int start
The physical end of the data.
Definition wave_descriptor.hpp:25
constexpr bool reverse() const noexcept
True when the sampler plays this wave backwards.
Definition wave_descriptor.hpp:38
int fine_tune
Fine-tune word; native pitch is root_key + (1024 - fine_tune) / 1000.
Definition wave_descriptor.hpp:29
int end
The loop point.
Definition wave_descriptor.hpp:23
constexpr bool ping_pong() const noexcept
True when the sampler plays this wave bidirectionally (ping-pong).
Definition wave_descriptor.hpp:41
int loop
Start of the sample data — delta index zero.
Definition wave_descriptor.hpp:21
static constexpr int stride
Bytes per descriptor record.
Definition wave_descriptor.hpp:16
int flags
Raw flag byte.
Definition wave_descriptor.hpp:32
friend constexpr bool operator==(const WaveDescriptor &, const WaveDescriptor &) noexcept=default
int region
ROM region, 0–127. Bit 4 selects the bank.
Definition wave_descriptor.hpp:19
int root_key
MIDI note at which the sample plays back untransposed.
Definition wave_descriptor.hpp:27
constexpr int bank() const noexcept
ROM bank: 0 for bank A, 1 for bank B.
Definition wave_descriptor.hpp:35
constexpr double native_pitch() const noexcept
Native pitch in semitones — the effective root, including fine tune.
Definition wave_descriptor.hpp:44