# stdex: include/stdex/wav.hpp Source File

Loading...
Searching...
No Matches
wav.hpp
/*
SPDX-License-Identifier: MIT
Copyright © 2023-2024 Amebis
*/
#pragma once
#include "compat.hpp"
#include "idrec.hpp"
#include "stream.hpp"
#include "string.hpp"
#include <stdint.h>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <vector>
namespace stdex
{
namespace wav {
using id_t = uint32_t;
using length_t = uint32_t;
constexpr size_t align = 2;
struct header
{
id_t type = 0;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const header& data)
{
dat << static_cast<uint32_t>(data.type);
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ header& data)
{
uint32_t pom4;
dat >> pom4;
if (!dat.ok()) _Unlikely_ goto error1;
data.type = pom4;
return dat;
error1:
data.type = 0;
return dat;
}
using record = stdex::idrec::record<header, id_t, 0x46464952 /*"RIFF"*/, length_t, align>;
};
struct wave : public header
{
using record = stdex::idrec::record<wave, id_t, 0x45564157 /*"WAVE"*/, length_t, align>;
};
struct format
{
enum class compression_t : uint16_t {
unknown = 0x0000,
pcm = 0x0001,
microsoft_adpcm = 0x0002,
pcm_float = 0x0003,
itu_g711_a_law = 0x0006,
itu_g711_mu_law = 0x0007,
ima_adpcm = 0x0011,
itu_g_723_adpcm = 0x0016,
gsm_6_10 = 0x0031,
itu_g_721_adpcm = 0x0040,
mpeg = 0x0050,
experimental = 0xffff,
} compression = compression_t::unknown;
uint16_t num_channels = 0;
uint32_t sample_rate = 0;
uint32_t bytes_per_second = 0;
uint16_t block_align = 0;
uint16_t bits_per_channel = 0;
stdex::stream::memory_file extra;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const format& data)
{
dat << static_cast<uint16_t>(data.compression);
dat << data.num_channels;
dat << data.sample_rate;
dat << data.bytes_per_second;
dat << data.block_align;
dat << data.bits_per_channel;
if (auto size = data.extra.size(); size) {
if (size > UINT16_MAX) _Unlikely_
throw std::invalid_argument("extra data too big");
dat << static_cast<uint16_t>(size);
if (dat.ok())
dat.write(data.extra.data(), static_cast<size_t>(size));
}
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ format& data)
{
uint16_t tmp16;
dat >> tmp16;
if (!dat.ok()) _Unlikely_ goto error1;
data.compression = static_cast< format::compression_t >(tmp16);
dat >> data.num_channels;
dat >> data.sample_rate;
dat >> data.bytes_per_second;
dat >> data.block_align;
dat >> data.bits_per_channel;
dat >> tmp16;
if (!dat.ok() || !tmp16) goto error7;
data.extra.seek(0);
data.extra.write_stream(dat, tmp16);
data.extra.truncate();
return dat;
error1:
data.compression = format::compression_t::unknown;
data.num_channels = 0;
data.sample_rate = 0;
data.bytes_per_second = 0;
data.block_align = 0;
data.bits_per_channel = 0;
error7:
data.extra.seek(0);
data.extra.truncate();
return dat;
}
using record = stdex::idrec::record<format, id_t, 0x20746D66 /*"fmt "*/, length_t, align>;
};
struct data
{
stdex::stream::memory_file content;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const data& data)
{
if (!dat.ok()) _Unlikely_ return dat;
dat.write(data.content.data(), static_cast<size_t>(data.content.size()));
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ data& data)
{
data.content.seek(0);
data.content.write_stream(dat);
data.content.truncate();
return dat;
}
using record = stdex::idrec::record<data, id_t, 0x61746164 /*"data"*/, length_t, align>;
};
struct silence
{
uint32_t num_samples = 0;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const silence& data)
{
dat << data.num_samples;
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ silence& data)
{
dat >> data.num_samples;
return dat;
}
using record = stdex::idrec::record<silence, id_t, 0x746E6C73 /*"slnt"*/, length_t, align>;
};
struct cue
{
uint32_t id = 0;
uint32_t position = 0;
uint32_t chunk_id = 0;
uint32_t chunk_offset = 0;
uint32_t block_start = 0;
uint32_t block_offset = 0;
};
inline int compare_by_id(_In_ const cue& a, _In_ const cue& b)
{
if (a.id < b.id) return -1;
if (a.id > b.id) return 1;
return 0;
}
inline int compare_by_pos(_In_ const cue& a, _In_ const cue& b)
{
if (a.position < b.position) return -1;
if (a.position > b.position) return 1;
return 0;
}
using cue_vector = std::vector<cue>;
using cue_vector_record = stdex::idrec::record<cue_vector, id_t, 0x20657563 /*"cue "*/, length_t, align>;
inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const cue_vector& data)
{
size_t num_cues = data.size();
if (num_cues > UINT32_MAX) _Unlikely_
throw std::invalid_argument("too many cues");
dat << static_cast<uint32_t>(num_cues);
if (dat.ok())
dat.write_array(data.data(), sizeof(cue), num_cues);
return dat;
}
inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ cue_vector& data)
{
uint32_t num_cues;
dat >> num_cues;
if (!dat.ok()) _Unlikely_ goto error1;
data.resize(num_cues);
data.resize(dat.read_array(data.data(), sizeof(cue), num_cues));
return dat;
error1:
data.clear();
return dat;
}
struct ltxt
{
uint32_t id = 0;
uint32_t duration = 0;
id_t purpose_id = 0;
uint16_t country = 0;
uint16_t language = 0;
uint16_t dialect = 0;
uint16_t charset = 0;
std::string description;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const ltxt& data)
{
dat << data.id;
dat << data.duration;
dat << data.purpose_id;
dat << data.country;
dat << data.language;
dat << data.dialect;
dat << data.charset;
if (size_t num_chars = data.description.size(); num_chars && dat.ok()) {
dat.write_array(data.description.data(), sizeof(char), num_chars);
dat << '\0';
}
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _In_ ltxt& data)
{
dat >> data.id;
dat >> data.duration;
dat >> data.purpose_id;
dat >> data.country;
dat >> data.language;
dat >> data.dialect;
dat >> data.charset;
if (dat.ok()) {
auto tmp = dat.read_remainder();
data.description.assign(
reinterpret_cast<const char*>(tmp.data()),
stdex::strnlen(reinterpret_cast<const char*>(tmp.data()), tmp.size()));
}
else
data.description.clear();
return dat;
}
using record = stdex::idrec::record<ltxt, id_t, 0x7478746C /*"ltxt"*/, length_t, align>;
};
struct label
{
uint32_t id = 0;
std::string title;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const label& data)
{
dat << data.id;
if (size_t num_chars = data.title.size(); num_chars && dat.ok()) {
dat.write_array(data.title.data(), sizeof(char), num_chars);
dat << '\0';
}
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _In_ label& data)
{
dat >> data.id;
if (dat.ok()) {
auto tmp = dat.read_remainder();
data.title.assign(
reinterpret_cast<const char*>(tmp.data()),
stdex::strnlen(reinterpret_cast<const char*>(tmp.data()), tmp.size()));
}
else
data.title.clear();
return dat;
}
using record = stdex::idrec::record<label, id_t, 0x6C62616C /*"labl"*/, length_t, align>;
};
struct note
{
uint32_t id = 0;
std::string note;
friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const stdex::wav::note& data)
{
dat << data.id;
if (size_t num_chars = data.note.size(); num_chars && dat.ok()) {
dat.write_array(data.note.data(), sizeof(char), num_chars);
dat << '\0';
}
return dat;
}
friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ stdex::wav::note& data)
{
dat >> data.id;
if (dat.ok()) {
auto tmp = dat.read_remainder();
data.note.assign(
reinterpret_cast<const char*>(tmp.data()),
stdex::strnlen(reinterpret_cast<const char*>(tmp.data()), tmp.size()));
}
else
data.note.clear();
return dat;
}
using record = stdex::idrec::record<stdex::wav::note, id_t, 0x65746F6E /*"note"*/, length_t, align>;
};
struct list : public header
{
using record = stdex::idrec::record<list, id_t, 0x5453494C /*"LIST"*/, length_t, align>;
};
struct cue_ex : public cue
{
uint32_t duration = 0;
id_t purpose_id = 0;
uint16_t country = 0;
uint16_t language = 0;
uint16_t dialect = 0;
uint16_t charset = 0;
std::string description;
std::string title;
std::string note;
};
using cue_ex_vector = std::vector<cue_ex>;
inline stdex::stream::basic_file& operator <<(_In_ stdex::stream::basic_file& dat, _In_ const cue_ex_vector& data)
{
auto start = stdex::idrec::open<id_t, length_t>(dat, cue_vector_record::id());
size_t num_cues = data.size();
if (num_cues > UINT32_MAX) _Unlikely_
throw std::invalid_argument("too many cues");
dat << static_cast<uint32_t>(num_cues);
for (size_t i = 0; i < num_cues && dat.ok(); ++i)
dat.write_array(static_cast<const cue*>(&data[i]), sizeof(cue), 1);
stdex::idrec::close<id_t, length_t, align>(dat, start);
start = stdex::idrec::open<id_t, length_t>(dat, list::record::id());
dat << *reinterpret_cast<const id_t*>("adtl");
for (size_t i = 0; i < num_cues && dat.ok(); ++i) {
const cue_ex& c = data[i];
ltxt ltxt;
ltxt.id = c.id;
ltxt.duration = c.duration;
ltxt.purpose_id = c.purpose_id;
ltxt.country = c.country;
ltxt.language = c.language;
ltxt.dialect = c.dialect;
ltxt.charset = c.charset;
ltxt.description = c.description;
dat << ltxt::record(ltxt);
if (!c.title.empty()) {
label title;
title.id = c.id;
title.title = c.title;
dat << label::record(title);
}
if (!c.note.empty()) {
note note;
note.id = c.id;
note.note = c.note;
dat << note::record(note);
}
}
stdex::idrec::close<id_t, length_t, align>(dat, start);
return dat;
}
template <class T>
_Success_(return!=0) bool find_first(
_In_ stdex::stream::basic_file& dat,
_In_ id_t subid,
_In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max,
_Out_opt_ stdex::stream::fpos_t* found_block_end = nullptr)
{
while (dat.tell() < block_end) {
if (!stdex::idrec::record<T, id_t, T::record::id(), length_t, align>::find(dat, block_end))
return false;
length_t size;
dat >> size;
if (!dat.ok()) _Unlikely_
return false;
stdex::stream::fpos_t end = dat.tell() + size;
id_t id;
dat >> id;
if (!dat.ok()) _Unlikely_
return false;
if (id == subid) {
if (found_block_end) *found_block_end = end;
return true;
}
// Block was found, but sub-ID is different.
end += (align - end) % align;
dat.seekbeg(end);
}
return false;
}
template <class T>
_Success_(return != 0) bool read_first(
_In_ stdex::stream::basic_file& dat,
_Inout_ T& content,
_In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max)
{
if (!stdex::idrec::record<T, id_t, T::record::id(), length_t, align>::find(dat, block_end))
return false;
dat >> stdex::idrec::record<T, id_t, T::record::id(), length_t, align>(content);
return dat.ok();
}
inline _Success_(return != 0) bool find_content(
_In_ stdex::stream::basic_file& dat,
_In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max,
_Out_opt_ stdex::stream::fpos_t* found_block_end = nullptr)
{
return find_first<header>(dat, wave::record::id(), block_end, found_block_end);
}
inline _Success_(return != 0) bool read_cues(
_In_ stdex::stream::basic_file& dat,
_Inout_ cue_ex_vector& cues, stdex::stream::fpos_t block_end = stdex::stream::fpos_max)
{
static auto cue_less = [](_In_ const cue& a, _In_ const cue& b) { return compare_by_id(a, b) < 0; };
static int (__cdecl* cue_cmp)(void const*, void const*) = [](_In_ void const* a, _In_ void const* b) { return compare_by_id(*reinterpret_cast<const cue*>(a), *reinterpret_cast<const cue*>(b)); };
stdex::stream::fpos_t start = dat.tell();
while (dat.tell() < block_end) {
if (stdex::idrec::record<cue_vector, id_t, cue_vector_record::id(), length_t, align>::find(dat, block_end)) {
length_t size;
dat >> size;
if (!dat.ok()) _Unlikely_ return false;
stdex::stream::file_window _dat(dat, dat.tell(), size);
uint32_t num_cues;
_dat >> num_cues;
if (!_dat.ok()) _Unlikely_ return false;
cues.resize(num_cues);
size_t i;
bool ordered = true;
for (i = 0; i < num_cues; i++) {
_dat.read_array(static_cast<cue*>(&cues[i]), sizeof(cue), 1);
if (!_dat.ok()) _Unlikely_
break;
if (i && cue_less(cues[i], cues[i - 1]))
ordered = false;
}
cues.resize(i);
if (!ordered)
std::sort(cues.begin(), cues.end(), cue_less);
}
}
// Cues are loaded. Add other data.
dat.seekbeg(start);
while (dat.tell() < block_end) {
stdex::stream::fpos_t found_block_end;
if (find_first<list>(dat, *(const id_t*)"adtl", block_end, &found_block_end)) {
while (dat.tell() < found_block_end) {
id_t id;
dat >> id;
if (!dat.ok()) break;
if (id == ltxt::record::id()) {
ltxt ltxt;
dat >> ltxt::record(ltxt);
cue_ex tmp;
tmp.id = ltxt.id;
cue_ex* c = reinterpret_cast<cue_ex*>(std::bsearch(&tmp, cues.data(), cues.size(), sizeof(cues[0]), cue_cmp));
if (c) {
c->duration = ltxt.duration;
c->purpose_id = ltxt.purpose_id;
c->country = ltxt.country;
c->language = ltxt.language;
c->dialect = ltxt.dialect;
c->charset = ltxt.charset;
c->description = ltxt.description;
}
}
else if (id == label::record::id()) {
label title;
dat >> label::record(title);
cue_ex tmp;
tmp.id = title.id;
cue_ex* c = reinterpret_cast<cue_ex*>(std::bsearch(&tmp, cues.data(), cues.size(), sizeof(cues[0]), cue_cmp));
if (c)
c->title = title.title;
}
else if (id == note::record::id()) {
note note;
dat >> note::record(note);
cue_ex tmp;
tmp.id = note.id;
cue_ex* c = reinterpret_cast<cue_ex*>(std::bsearch(&tmp, cues.data(), cues.size(), sizeof(cues[0]), cue_cmp));
if (c)
c->note = note.note;
}
else if (!stdex::idrec::ignore<length_t, align>(dat)) _Unlikely_
return false;
}
}
}
dat.seekbeg(start);
return true;
}
inline _Success_(return != 0) bool remove_cues(
_Inout_ stdex::stream::basic_file& input,
_Inout_ stdex::stream::basic_file& output,
_In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max)
{
static id_t removable[] = {
cue_vector_record::id(),
ltxt::record::id(),
label::record::id(),
note::record::id(),
};
while (input.tell() < block_end) {
id_t id;
input >> id;
if (!input.ok()) break;
for (size_t i = 0; i < _countof(removable); i++)
if (id == removable[i])
goto remove;
if (!stdex::idrec::ignore<length_t, align>(input)) _Unlikely_
return false;
continue;
remove:
length_t size;
input >> size;
if (!input.ok()) _Unlikely_ return false;
auto start = stdex::idrec::open<id_t, length_t>(output, id);
id_t id2 = id;
stdex::strupr(reinterpret_cast<char*>(&id2), sizeof(id_t) / sizeof(char));
if (id != id2 || id == *reinterpret_cast<const id_t*>("ICRD")) {
// ID is not all uppercase (or is an exception). Element is trivial and may be copied.
if (!output.ok()) _Unlikely_ return false;
output.write_stream(input, size);
if (!input.ok()) _Unlikely_ return false;
stdex::idrec::close<id_t, length_t, align>(output, start);
size = static_cast<length_t>(align - size) % align;
if (size)
input.seekcur(size);
}
else {
// ID is all uppercase. Needs recursive treatment.
id_t id3;
input >> id3;
if (!input.ok()) _Unlikely_ return false;
output << id3;
if (!output.ok()) _Unlikely_ return false;
stdex::stream::fpos_t end = output.tell();
if (!remove_cues(input, output, input.tell() + size - sizeof(id_t))) _Unlikely_
return false;
if (end != output.tell())
stdex::idrec::close<id_t, length_t, align>(output, start);
else
output.seekbeg(start);
}
}
output.truncate();
return true;
}
}
}
stdex::idrec::record
Helper class for read/write of records to/from memory.
Definition idrec.hpp:291
stdex::idrec::record::id
static constexpr T_id id()
Returns record id.
Definition idrec.hpp:310
stdex::stream::basic_file
Basic seekable stream operations.
Definition stream.hpp:818
stdex::stream::basic
Basic stream operations.
Definition stream.hpp:85
stdex::stream::file_window
Limits file reading/writing to a predefined window.
Definition stream.hpp:1695
stdex::stream::memory_file
In-memory file.
Definition stream.hpp:3222
stdex::stream::memory_file::size
virtual fsize_t size() const
Returns file size Should the file size cannot be determined, the method returns fsize_max and it does...
Definition stream.hpp:3924
stdex::stream::memory_file::write_stream
size_t write_stream(basic &stream, size_t amount=SIZE_MAX)
Writes content of another stream.
Definition stream.hpp:3839
stdex::stream::memory_file::seek
virtual fpos_t seek(foff_t offset, seek_t how=seek_t::beg)
Seeks to specified relative file position.
Definition stream.hpp:3903
stdex::stream::memory_file::truncate
virtual void truncate()
Sets file size - truncates the remainder of file content from the current file position to the end of...
Definition stream.hpp:3929
stdex::stream::memory_file::data
const void * data() const
Returns pointer to data.
Definition stream.hpp:3552
stdex::wav::cue_ex
Extended cue.
Definition wav.hpp:397
stdex::wav::cue_ex::duration
uint32_t duration
How many samples from the cue point the region or section spans.
Definition wav.hpp:398
stdex::wav::cue_ex::note
std::string note
Note text.
Definition wav.hpp:406
stdex::wav::cue_ex::description
std::string description
Description text.
Definition wav.hpp:404
stdex::wav::cue_ex::title
std::string title
Title text.
Definition wav.hpp:405
stdex::wav::cue_ex::country
uint16_t country
Country code used by texts.
Definition wav.hpp:400
stdex::wav::cue_ex::charset
uint16_t charset
Charset used by texts.
Definition wav.hpp:403
stdex::wav::cue_ex::purpose_id
id_t purpose_id
What the text is used for. For example a value of "scrp" means script text, and "capt" means close-ca...
Definition wav.hpp:399
stdex::wav::cue_ex::language
uint16_t language
Language code used by texts.
Definition wav.hpp:401
stdex::wav::cue_ex::dialect
uint16_t dialect
Dialect code used by texts.
Definition wav.hpp:402
stdex::wav::cue
Cue point.
Definition wav.hpp:208
stdex::wav::cue::chunk_id
uint32_t chunk_id
The four byte ID used by the chunk containing the sample that corresponds to this cue point....
Definition wav.hpp:211
stdex::wav::cue::id
uint32_t id
Each cue point has a unique identification value used to associate cue points with information in oth...
Definition wav.hpp:209
stdex::wav::cue::block_start
uint32_t block_start
The byte offset into the "data" or "slnt" Chunk to the start of the block containing the sample....
Definition wav.hpp:213
stdex::wav::cue::position
uint32_t position
The sample offset associated with the cue point in terms of the sample's position in the final stream...
Definition wav.hpp:210
stdex::wav::cue::chunk_offset
uint32_t chunk_offset
The byte offset into the Wave List Chunk of the chunk containing the sample that corresponds to this ...
Definition wav.hpp:212
stdex::wav::cue::block_offset
uint32_t block_offset
An offset into the block (specified by Block Start) for the sample that corresponds to the cue point....
Definition wav.hpp:214
stdex::wav::data
Encoded waveform content.
Definition wav.hpp:161
stdex::wav::data::content
stdex::stream::memory_file content
Encoded waveform.
Definition wav.hpp:162
stdex::wav::format
Waveform format.
Definition wav.hpp:79
stdex::wav::format::bytes_per_second
uint32_t bytes_per_second
How many bytes of wave data must be streamed to a D/A converter per second in order to play the wave ...
Definition wav.hpp:96
stdex::wav::format::sample_rate
uint32_t sample_rate
The number of sample slices per second (Hz). This value is unaffected by the number of channels.
Definition wav.hpp:95
stdex::wav::format::bits_per_channel
uint16_t bits_per_channel
The number of bits used to define each sample. This value is usually 8, 16, 24 or 32....
Definition wav.hpp:98
stdex::wav::format::extra
stdex::stream::memory_file extra
Additional format data.
Definition wav.hpp:99
stdex::wav::format::compression
enum stdex::wav::format::compression_t compression
Waveform compression.
stdex::wav::format::compression_t
compression_t
Definition wav.hpp:80
stdex::wav::format::compression_t::ima_adpcm
@ ima_adpcm
IMA ADPCM.
stdex::wav::format::compression_t::mpeg
@ mpeg
MPEG.
stdex::wav::format::compression_t::itu_g711_a_law
@ itu_g711_a_law
ITU G.711 a-law.
stdex::wav::format::compression_t::itu_g_723_adpcm
@ itu_g_723_adpcm
ITU G.723 ADPCM (Yamaha)
stdex::wav::format::compression_t::gsm_6_10
@ gsm_6_10
GSM 6.10.
stdex::wav::format::compression_t::itu_g711_mu_law
@ itu_g711_mu_law
ITU G.711 µ-law.
stdex::wav::format::compression_t::experimental
@ experimental
Experimental.
stdex::wav::format::compression_t::unknown
@ unknown
Unknown.
stdex::wav::format::compression_t::itu_g_721_adpcm
@ itu_g_721_adpcm
ITU G.721 ADPCM.
stdex::wav::format::compression_t::pcm_float
@ pcm_float
PCM/uncompressed floating point.
stdex::wav::format::compression_t::microsoft_adpcm
@ microsoft_adpcm
Microsoft ADPCM.
stdex::wav::format::compression_t::pcm
@ pcm
PCM/uncompressed integral.
stdex::wav::format::num_channels
uint16_t num_channels
The number of channels specifies how many separate audio signals that are encoded in the wave data ch...
Definition wav.hpp:94
stdex::wav::format::block_align
uint16_t block_align
The number of bytes per sample slice (all channels). This value is not affected by the number of chan...
Definition wav.hpp:97
stdex::wav::header
File header.
Definition wav.hpp:42
stdex::wav::header::type
id_t type
RIFF type.
Definition wav.hpp:43
stdex::wav::label
Label.
Definition wav.hpp:319
stdex::wav::label::title
std::string title
Title text.
Definition wav.hpp:321
stdex::wav::list
Associated data list.
Definition wav.hpp:389
stdex::wav::ltxt
Labeled text.
Definition wav.hpp:266
stdex::wav::ltxt::charset
uint16_t charset
Charset used by text.
Definition wav.hpp:273
stdex::wav::ltxt::id
uint32_t id
The starting sample point that corresponds to this text label by providing the ID of a Cue Point defi...
Definition wav.hpp:267
stdex::wav::ltxt::language
uint16_t language
Language code used by text.
Definition wav.hpp:271
stdex::wav::ltxt::country
uint16_t country
Country code used by text.
Definition wav.hpp:270
stdex::wav::ltxt::description
std::string description
Description text.
Definition wav.hpp:274
stdex::wav::ltxt::purpose_id
id_t purpose_id
What the text is used for. For example a value of "scrp" means script text, and "capt" means close-ca...
Definition wav.hpp:269
stdex::wav::ltxt::duration
uint32_t duration
How many samples from the cue point the region or section spans.
Definition wav.hpp:268
stdex::wav::ltxt::dialect
uint16_t dialect
Dialect code used by text.
Definition wav.hpp:272
stdex::wav::note
Note.
Definition wav.hpp:354
stdex::wav::note::note
std::string note
Note text.
Definition wav.hpp:356
stdex::wav::note::id
uint32_t id
The sample point that corresponds to this text comment by providing the ID of a Cue Point defined in ...
Definition wav.hpp:355
stdex::wav::silence
Silence.
Definition wav.hpp:186
stdex::wav::silence::num_samples
uint32_t num_samples
The number of silent samples that appear in the waveform at this point in the wave list chunk.
Definition wav.hpp:187
stdex::wav::wave
Waveform block.
Definition wav.hpp:71