stdex Additional custom or not Standard C++ covered algorithms

Loading...
Searching...
No Matches
wav.hpp
1/*
2 SPDX-License-Identifier: MIT
3 Copyright © 2023-2024 Amebis
4*/
5
6#pragma once
7
8#include "compat.hpp"
9#include "idrec.hpp"
10#include "stream.hpp"
11#include "string.hpp"
12#include <stdint.h>
13#include <algorithm>
14#include <cstdlib>
15#include <string>
16#include <vector>
17
18 namespace stdex
19{
20 namespace wav {
26 using id_t = uint32_t;
27
31 using length_t = uint32_t;
32
36 constexpr size_t align = 2;
37
41 struct header
42 {
43 id_t type = 0;
44
45 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const header& data)
46 {
47 dat << static_cast<uint32_t>(data.type);
48 return dat;
49 }
50
51 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ header& data)
52 {
53 uint32_t pom4;
54 dat >> pom4;
55 if (!dat.ok()) _Unlikely_ goto error1;
56 data.type = pom4;
57 return dat;
58
59 error1:
60 data.type = 0;
61 return dat;
62 }
63
64 using record = stdex::idrec::record<header, id_t, 0x46464952 /*"RIFF"*/, length_t, align>;
65 };
66
70 struct wave : public header
71 {
72 using record = stdex::idrec::record<wave, id_t, 0x45564157 /*"WAVE"*/, length_t, align>;
73 };
74
78 struct format
79 {
80 enum class compression_t : uint16_t {
81 unknown = 0x0000,
82 pcm = 0x0001,
83 microsoft_adpcm = 0x0002,
84 pcm_float = 0x0003,
85 itu_g711_a_law = 0x0006,
86 itu_g711_mu_law = 0x0007,
87 ima_adpcm = 0x0011,
88 itu_g_723_adpcm = 0x0016,
89 gsm_6_10 = 0x0031,
90 itu_g_721_adpcm = 0x0040,
91 mpeg = 0x0050,
92 experimental = 0xffff,
93 } compression = compression_t::unknown;
94 uint16_t num_channels = 0;
95 uint32_t sample_rate = 0;
96 uint32_t bytes_per_second = 0;
97 uint16_t block_align = 0;
98 uint16_t bits_per_channel = 0;
99 stdex::stream::memory_file extra;
100
101 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const format& data)
102 {
103 dat << static_cast<uint16_t>(data.compression);
104 dat << data.num_channels;
105 dat << data.sample_rate;
106 dat << data.bytes_per_second;
107 dat << data.block_align;
108 dat << data.bits_per_channel;
109
110 if (auto size = data.extra.size(); size) {
111 if (size > UINT16_MAX) _Unlikely_
112 throw std::invalid_argument("extra data too big");
113 dat << static_cast<uint16_t>(size);
114 if (dat.ok())
115 dat.write(data.extra.data(), static_cast<size_t>(size));
116 }
117
118 return dat;
119 }
120
121 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ format& data)
122 {
123 uint16_t tmp16;
124
125 dat >> tmp16;
126 if (!dat.ok()) _Unlikely_ goto error1;
127 data.compression = static_cast<format::compression_t>(tmp16);
128 dat >> data.num_channels;
129 dat >> data.sample_rate;
130 dat >> data.bytes_per_second;
131 dat >> data.block_align;
132 dat >> data.bits_per_channel;
133 dat >> tmp16;
134 if (!dat.ok() || !tmp16) goto error7;
135 data.extra.seek(0);
136 data.extra.write_stream(dat, tmp16);
137 data.extra.truncate();
138
139 return dat;
140
141 error1:
142 data.compression = format::compression_t::unknown;
143 data.num_channels = 0;
144 data.sample_rate = 0;
145 data.bytes_per_second = 0;
146 data.block_align = 0;
147 data.bits_per_channel = 0;
148 error7:
149 data.extra.seek(0);
150 data.extra.truncate();
151 return dat;
152 }
153
154 using record = stdex::idrec::record<format, id_t, 0x20746D66 /*"fmt "*/, length_t, align>;
155 };
156
160 struct data
161 {
162 stdex::stream::memory_file content;
163
164 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const data& data)
165 {
166 if (!dat.ok()) _Unlikely_ return dat;
167 dat.write(data.content.data(), static_cast<size_t>(data.content.size()));
168 return dat;
169 }
170
171 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ data& data)
172 {
173 data.content.seek(0);
174 data.content.write_stream(dat);
175 data.content.truncate();
176 return dat;
177 }
178
179 using record = stdex::idrec::record<data, id_t, 0x61746164 /*"data"*/, length_t, align>;
180 };
181
185 struct silence
186 {
187 uint32_t num_samples = 0;
188
189 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const silence& data)
190 {
191 dat << data.num_samples;
192 return dat;
193 }
194
195 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ silence& data)
196 {
197 dat >> data.num_samples;
198 return dat;
199 }
200
201 using record = stdex::idrec::record<silence, id_t, 0x746E6C73 /*"slnt"*/, length_t, align>;
202 };
203
207 struct cue
208 {
209 uint32_t id = 0;
210 uint32_t position = 0;
211 uint32_t chunk_id = 0;
212 uint32_t chunk_offset = 0;
213 uint32_t block_start = 0;
214 uint32_t block_offset = 0;
215 };
216
217 inline int compare_by_id(_In_ const cue& a, _In_ const cue& b)
218 {
219 if (a.id < b.id) return -1;
220 if (a.id > b.id) return 1;
221 return 0;
222 }
223
224 inline int compare_by_pos(_In_ const cue& a, _In_ const cue& b)
225 {
226 if (a.position < b.position) return -1;
227 if (a.position > b.position) return 1;
228 return 0;
229 }
230
234 using cue_vector = std::vector<cue>;
235 using cue_vector_record = stdex::idrec::record<cue_vector, id_t, 0x20657563 /*"cue "*/, length_t, align>;
236
237 inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const cue_vector& data)
238 {
239 size_t num_cues = data.size();
240 if (num_cues > UINT32_MAX) _Unlikely_
241 throw std::invalid_argument("too many cues");
242 dat << static_cast<uint32_t>(num_cues);
243 if (dat.ok())
244 dat.write_array(data.data(), sizeof(cue), num_cues);
245 return dat;
246 }
247
248 inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ cue_vector& data)
249 {
250 uint32_t num_cues;
251 dat >> num_cues;
252 if (!dat.ok()) _Unlikely_ goto error1;
253 data.resize(num_cues);
254 data.resize(dat.read_array(data.data(), sizeof(cue), num_cues));
255 return dat;
256
257 error1:
258 data.clear();
259 return dat;
260 }
261
265 struct ltxt
266 {
267 uint32_t id = 0;
268 uint32_t duration = 0;
269 id_t purpose_id = 0;
270 uint16_t country = 0;
271 uint16_t language = 0;
272 uint16_t dialect = 0;
273 uint16_t charset = 0;
274 std::string description;
275
276 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const ltxt& data)
277 {
278 dat << data.id;
279 dat << data.duration;
280 dat << data.purpose_id;
281 dat << data.country;
282 dat << data.language;
283 dat << data.dialect;
284 dat << data.charset;
285 if (size_t num_chars = data.description.size(); num_chars && dat.ok()) {
286 dat.write_array(data.description.data(), sizeof(char), num_chars);
287 dat << '\0';
288 }
289 return dat;
290 }
291
292 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _In_ ltxt& data)
293 {
294 dat >> data.id;
295 dat >> data.duration;
296 dat >> data.purpose_id;
297 dat >> data.country;
298 dat >> data.language;
299 dat >> data.dialect;
300 dat >> data.charset;
301 if (dat.ok()) {
302 auto tmp = dat.read_remainder();
303 data.description.assign(
304 reinterpret_cast<const char*>(tmp.data()),
305 stdex::strnlen(reinterpret_cast<const char*>(tmp.data()), tmp.size()));
306 }
307 else
308 data.description.clear();
309 return dat;
310 }
311
312 using record = stdex::idrec::record<ltxt, id_t, 0x7478746C /*"ltxt"*/, length_t, align>;
313 };
314
318 struct label
319 {
320 uint32_t id = 0;
321 std::string title;
322
323 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const label& data)
324 {
325 dat << data.id;
326 if (size_t num_chars = data.title.size(); num_chars && dat.ok()) {
327 dat.write_array(data.title.data(), sizeof(char), num_chars);
328 dat << '\0';
329 }
330 return dat;
331 }
332
333 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _In_ label& data)
334 {
335 dat >> data.id;
336 if (dat.ok()) {
337 auto tmp = dat.read_remainder();
338 data.title.assign(
339 reinterpret_cast<const char*>(tmp.data()),
340 stdex::strnlen(reinterpret_cast<const char*>(tmp.data()), tmp.size()));
341 }
342 else
343 data.title.clear();
344 return dat;
345 }
346
347 using record = stdex::idrec::record<label, id_t, 0x6C62616C /*"labl"*/, length_t, align>;
348 };
349
353 struct note
354 {
355 uint32_t id = 0;
356 std::string note;
357
358 friend inline stdex::stream::basic& operator <<(_In_ stdex::stream::basic& dat, _In_ const stdex::wav::note& data)
359 {
360 dat << data.id;
361 if (size_t num_chars = data.note.size(); num_chars && dat.ok()) {
362 dat.write_array(data.note.data(), sizeof(char), num_chars);
363 dat << '\0';
364 }
365 return dat;
366 }
367
368 friend inline stdex::stream::basic& operator >>(_In_ stdex::stream::basic& dat, _Out_ stdex::wav::note& data)
369 {
370 dat >> data.id;
371 if (dat.ok()) {
372 auto tmp = dat.read_remainder();
373 data.note.assign(
374 reinterpret_cast<const char*>(tmp.data()),
375 stdex::strnlen(reinterpret_cast<const char*>(tmp.data()), tmp.size()));
376 }
377 else
378 data.note.clear();
379 return dat;
380 }
381
382 using record = stdex::idrec::record<stdex::wav::note, id_t, 0x65746F6E /*"note"*/, length_t, align>;
383 };
384
388 struct list : public header
389 {
390 using record = stdex::idrec::record<list, id_t, 0x5453494C /*"LIST"*/, length_t, align>;
391 };
392
396 struct cue_ex : public cue
397 {
398 uint32_t duration = 0;
399 id_t purpose_id = 0;
400 uint16_t country = 0;
401 uint16_t language = 0;
402 uint16_t dialect = 0;
403 uint16_t charset = 0;
404 std::string description;
405 std::string title;
406 std::string note;
407 };
408
412 using cue_ex_vector = std::vector<cue_ex>;
413
414 inline stdex::stream::basic_file& operator <<(_In_ stdex::stream::basic_file& dat, _In_ const cue_ex_vector& data)
415 {
416 auto start = stdex::idrec::open<id_t, length_t>(dat, cue_vector_record::id());
417 size_t num_cues = data.size();
418 if (num_cues > UINT32_MAX) _Unlikely_
419 throw std::invalid_argument("too many cues");
420 dat << static_cast<uint32_t>(num_cues);
421 for (size_t i = 0; i < num_cues && dat.ok(); ++i)
422 dat.write_array(static_cast<const cue*>(&data[i]), sizeof(cue), 1);
423 stdex::idrec::close<id_t, length_t, align>(dat, start);
424
425 start = stdex::idrec::open<id_t, length_t>(dat, list::record::id());
426 dat << *reinterpret_cast<const id_t*>("adtl");
427 for (size_t i = 0; i < num_cues && dat.ok(); ++i) {
428 const cue_ex& c = data[i];
429 ltxt ltxt;
430 ltxt.id = c.id;
431 ltxt.duration = c.duration;
432 ltxt.purpose_id = c.purpose_id;
433 ltxt.country = c.country;
434 ltxt.language = c.language;
435 ltxt.dialect = c.dialect;
436 ltxt.charset = c.charset;
437 ltxt.description = c.description;
438 dat << ltxt::record(ltxt);
439 if (!c.title.empty()) {
440 label title;
441 title.id = c.id;
442 title.title = c.title;
443 dat << label::record(title);
444 }
445 if (!c.note.empty()) {
446 note note;
447 note.id = c.id;
448 note.note = c.note;
449 dat << note::record(note);
450 }
451 }
452 stdex::idrec::close<id_t, length_t, align>(dat, start);
453
454 return dat;
455 }
456
457 template <class T>
458 _Success_(return!=0) bool find_first(
459 _In_ stdex::stream::basic_file& dat,
460 _In_ id_t subid,
461 _In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max,
462 _Out_opt_ stdex::stream::fpos_t* found_block_end = nullptr)
463 {
464 while (dat.tell() < block_end) {
465 if (!stdex::idrec::record<T, id_t, T::record::id(), length_t, align>::find(dat, block_end))
466 return false;
467
468 length_t size;
469 dat >> size;
470 if (!dat.ok()) _Unlikely_
471 return false;
472 stdex::stream::fpos_t end = dat.tell() + size;
473 id_t id;
474 dat >> id;
475 if (!dat.ok()) _Unlikely_
476 return false;
477 if (id == subid) {
478 if (found_block_end) *found_block_end = end;
479 return true;
480 }
481
482 // Block was found, but sub-ID is different.
483 end += (align - end) % align;
484 dat.seekbeg(end);
485 }
486 return false;
487 }
488
489 template <class T>
490 _Success_(return != 0) bool read_first(
491 _In_ stdex::stream::basic_file& dat,
492 _Inout_ T& content,
493 _In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max)
494 {
495 if (!stdex::idrec::record<T, id_t, T::record::id(), length_t, align>::find(dat, block_end))
496 return false;
497 dat >> stdex::idrec::record<T, id_t, T::record::id(), length_t, align>(content);
498 return dat.ok();
499 }
500
501 inline _Success_(return != 0) bool find_content(
502 _In_ stdex::stream::basic_file& dat,
503 _In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max,
504 _Out_opt_ stdex::stream::fpos_t* found_block_end = nullptr)
505 {
506 return find_first<header>(dat, wave::record::id(), block_end, found_block_end);
507 }
508
509 inline _Success_(return != 0) bool read_cues(
510 _In_ stdex::stream::basic_file& dat,
511 _Inout_ cue_ex_vector& cues, stdex::stream::fpos_t block_end = stdex::stream::fpos_max)
512 {
513 static auto cue_less = [](_In_ const cue& a, _In_ const cue& b) { return compare_by_id(a, b) < 0; };
514 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)); };
515
516 stdex::stream::fpos_t start = dat.tell();
517 while (dat.tell() < block_end) {
518 if (stdex::idrec::record<cue_vector, id_t, cue_vector_record::id(), length_t, align>::find(dat, block_end)) {
519 length_t size;
520 dat >> size;
521 if (!dat.ok()) _Unlikely_ return false;
522 stdex::stream::file_window _dat(dat, dat.tell(), size);
523 uint32_t num_cues;
524 _dat >> num_cues;
525 if (!_dat.ok()) _Unlikely_ return false;
526 cues.resize(num_cues);
527 size_t i;
528 bool ordered = true;
529 for (i = 0; i < num_cues; i++) {
530 _dat.read_array(static_cast<cue*>(&cues[i]), sizeof(cue), 1);
531 if (!_dat.ok()) _Unlikely_
532 break;
533 if (i && cue_less(cues[i], cues[i - 1]))
534 ordered = false;
535 }
536 cues.resize(i);
537 if (!ordered)
538 std::sort(cues.begin(), cues.end(), cue_less);
539 }
540 }
541
542 // Cues are loaded. Add other data.
543 dat.seekbeg(start);
544 while (dat.tell() < block_end) {
545 stdex::stream::fpos_t found_block_end;
546 if (find_first<list>(dat, *(const id_t*)"adtl", block_end, &found_block_end)) {
547 while (dat.tell() < found_block_end) {
548 id_t id;
549 dat >> id;
550 if (!dat.ok()) break;
551
552 if (id == ltxt::record::id()) {
553 ltxt ltxt;
554 dat >> ltxt::record(ltxt);
555 cue_ex tmp;
556 tmp.id = ltxt.id;
557 cue_ex* c = reinterpret_cast<cue_ex*>(std::bsearch(&tmp, cues.data(), cues.size(), sizeof(cues[0]), cue_cmp));
558 if (c) {
559 c->duration = ltxt.duration;
560 c->purpose_id = ltxt.purpose_id;
561 c->country = ltxt.country;
562 c->language = ltxt.language;
563 c->dialect = ltxt.dialect;
564 c->charset = ltxt.charset;
565 c->description = ltxt.description;
566 }
567 }
568 else if (id == label::record::id()) {
569 label title;
570 dat >> label::record(title);
571 cue_ex tmp;
572 tmp.id = title.id;
573 cue_ex* c = reinterpret_cast<cue_ex*>(std::bsearch(&tmp, cues.data(), cues.size(), sizeof(cues[0]), cue_cmp));
574 if (c)
575 c->title = title.title;
576 }
577 else if (id == note::record::id()) {
578 note note;
579 dat >> note::record(note);
580 cue_ex tmp;
581 tmp.id = note.id;
582 cue_ex* c = reinterpret_cast<cue_ex*>(std::bsearch(&tmp, cues.data(), cues.size(), sizeof(cues[0]), cue_cmp));
583 if (c)
584 c->note = note.note;
585 }
586 else if (!stdex::idrec::ignore<length_t, align>(dat)) _Unlikely_
587 return false;
588 }
589 }
590 }
591
592 dat.seekbeg(start);
593 return true;
594 }
595
596 inline _Success_(return != 0) bool remove_cues(
597 _Inout_ stdex::stream::basic_file& input,
598 _Inout_ stdex::stream::basic_file& output,
599 _In_ stdex::stream::fpos_t block_end = stdex::stream::fpos_max)
600 {
601 static id_t removable[] = {
602 cue_vector_record::id(),
603 ltxt::record::id(),
604 label::record::id(),
605 note::record::id(),
606 };
607
608 while (input.tell() < block_end) {
609 id_t id;
610 input >> id;
611 if (!input.ok()) break;
612 for (size_t i = 0; i < _countof(removable); i++)
613 if (id == removable[i])
614 goto remove;
615 if (!stdex::idrec::ignore<length_t, align>(input)) _Unlikely_
616 return false;
617 continue;
618
619 remove:
620 length_t size;
621 input >> size;
622 if (!input.ok()) _Unlikely_ return false;
623 auto start = stdex::idrec::open<id_t, length_t>(output, id);
624 id_t id2 = id;
625 stdex::strupr(reinterpret_cast<char*>(&id2), sizeof(id_t) / sizeof(char));
626 if (id != id2 || id == *reinterpret_cast<const id_t*>("ICRD")) {
627 // ID is not all uppercase (or is an exception). Element is trivial and may be copied.
628 if (!output.ok()) _Unlikely_ return false;
629 output.write_stream(input, size);
630 if (!input.ok()) _Unlikely_ return false;
631 stdex::idrec::close<id_t, length_t, align>(output, start);
632 size = static_cast<length_t>(align - size) % align;
633 if (size)
634 input.seekcur(size);
635 }
636 else {
637 // ID is all uppercase. Needs recursive treatment.
638 id_t id3;
639 input >> id3;
640 if (!input.ok()) _Unlikely_ return false;
641 output << id3;
642 if (!output.ok()) _Unlikely_ return false;
643 stdex::stream::fpos_t end = output.tell();
644 if (!remove_cues(input, output, input.tell() + size - sizeof(id_t))) _Unlikely_
645 return false;
646 if (end != output.tell())
647 stdex::idrec::close<id_t, length_t, align>(output, start);
648 else
649 output.seekbeg(start);
650 }
651 }
652
653 output.truncate();
654 return true;
655 }
656 }
657}
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:815
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:1692
stdex::stream::memory_file
In-memory file.
Definition stream.hpp:3219
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:3921
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:3836
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:3900
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:3926
stdex::stream::memory_file::data
const void * data() const
Returns pointer to data.
Definition stream.hpp:3549
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