22WaveWriter::~WaveWriter ()
27wav_header (
const uint8_t n_bits,
const uint32_t n_channels,
const uint32_t sample_freq,
const uint32_t n_samples)
34 puts (
const char *str)
41 const uint32_t byte_per_sample = n_channels * n_bits / 8;
42 const uint32_t byte_per_second = byte_per_sample * sample_freq;
43 const uint32_t n_data_bytes = (n_samples * byte_per_sample + 1) / 2 * 2;
46 ByteStream b { &buffer[0] };
48 const ByteStream lpos = b;
50 const ByteStream cpos = b;
53 const uint16_t fmt = n_bits == 32 ? 3 : 1;
54 const bool extensible = n_channels > 2 || fmt == 3;
55 const uint32_t fmtsz = extensible ? 18 : 16;
56 *b.u32++ = htole32 (fmtsz);
57 *b.u16++ = htole16 (fmt);
58 *b.u16++ = htole16 (n_channels);
59 *b.u32++ = htole32 (sample_freq);
60 *b.u32++ = htole32 (byte_per_second);
61 *b.u16++ = htole16 (byte_per_sample);
62 *b.u16++ = htole16 (n_bits);
64 *b.u16++ = htole16 (0);
68 *b.u32++ = htole32 (4);
69 *b.u32++ = htole32 (n_samples);
72 *b.u32++ = htole32 (n_data_bytes);
73 const uint32_t length = b.c - cpos.c + n_data_bytes;
74 *lpos.u32 = htole32 (length);
75 buffer.resize (b.u8 - &buffer[0]);
80wav_write (
int fd, uint8_t n_bits, uint32_t n_channels, uint32_t sample_freq,
const float *samples,
size_t n_frames)
82 const size_t n_samples = n_channels * n_frames;
85 uint8_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
86 for (
size_t n = 0; n < n_samples; )
88 const uint8_t u8 = 127.5 + 127.5 * samples[n++];
90 if (b + 1 >= e || n >= n_samples)
92 if (n >= n_samples && (n_channels & 1) && (n_samples & 1))
94 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
102 uint8_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
103 for (
size_t n = 0; n < n_samples; )
105 const int32_t i24 = samples[n++] * 8388607.5 - 0.5;
109 if (b + 4 >= e || n >= n_samples)
111 if (n >= n_samples && (n_channels & 1) && (n_samples & 1))
113 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
121 uint16_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
122 for (
size_t n = 0; n < n_samples; )
124 const int16_t i16 = samples[n++] * 32767.5 - 0.5;
125 *b++ = htole16 (i16);
126 if (b >= e || n >= n_samples)
128 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
136 uint32_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
137 for (
size_t n = 0; n < n_samples; )
139 union {
float f;
uint32_t u32; } u { samples[n++] };
140 *b++ = htole32 (u.u32);
141 if (b >= e || n >= n_samples)
143 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
158 size_t n_samples_ = 0;
163 flush_atquit = [
this] () { close(); };
164 atquit_add (&flush_atquit);
168 atquit_del (&flush_atquit);
176 assert_return (n_bits == 8 || n_bits == 16 || n_bits == 24 || n_bits == 32,
false);
180 fd_ = ::open (filename.
c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644);
183 if (
lseek (fd_, 0, SEEK_SET) < 0)
190 filename_ = filename;
192 n_channels_ = n_channels;
193 sample_freq_ = sample_freq;
197 if (::write (fd_, header.data(), header.size()) < 0)
206 name ()
const override
211 write (
const float *frames,
size_t n_frames)
override
217 n_samples_ += n_frames * n_channels_;
219 return wav_write (fd_, n_bits_, n_channels_, sample_freq_, frames, n_frames) >= 0;
227 if (
lseek (fd_, 0, SEEK_SET) >= 0)
228 ok &= ::write (fd_, header.data(), header.size()) >= 0;
229 ok &=::close (fd_) >= 0;
236wave_writer_create_wav (
int rate,
int channels,
const String &filename,
int mode, uint8_t n_bits)
239 if (wavw->open (filename, n_bits, channels, rate) ==
false)
246wave_writer_opus_version()
248 return opus_get_version_string();
253 OpusEncoder *enc_ =
nullptr;
255 float *bmark_ =
nullptr;
257 ogg_stream_state ostream_ = { 0, };
268 flush_atquit = [
this] () { finish_and_close (
true); };
269 atquit_add (&flush_atquit);
273 atquit_del (&flush_atquit);
275 opus_encoder_destroy (enc_);
277 ogg_stream_clear (&ostream_);
280 name()
const override
289 fd_ =
open (name_.c_str(), O_CREAT | O_TRUNC | O_WRONLY, mode);
293 setup_encoder (
int rate,
int channels,
int complexity,
float bitrate)
302 n_channels_ = channels;
303 enc_ = opus_encoder_create (rate_, n_channels_, OPUS_APPLICATION_AUDIO, &error);
304 if (error == OPUS_OK)
306 bitrate = n_channels_ * bitrate * 1000;
308 if (OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_BITRATE (
MIN (256000 * n_channels_, bitrate))) &&
309 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_VBR (1)) &&
310 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_VBR_CONSTRAINT (0)) &&
311 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_FORCE_CHANNELS (n_channels_)) &&
312 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_COMPLEXITY (complexity)) &&
313 ogg_stream_init (&ostream_, serialno) >= 0)
315 const int std_fragment_size = 20 * 48000 / 1000;
316 int fragment_size = std_fragment_size * rate_ / 48000;
317 buffer_.resize (fragment_size * n_channels_);
318 bmark_ = buffer_.data();
319 if (write_header() > 0)
323 finish_and_close (
false);
328 write_packet (ogg_packet *op,
bool force_flush)
330 ogg_stream_packetin (&ostream_, op);
332 auto stream_pageout = force_flush ? ogg_stream_flush : ogg_stream_pageout;
333 while (stream_pageout (&ostream_, &opage))
337 n = ::write (fd_, opage.header, opage.header_len);
339 if (n != opage.header_len)
return -1;
341 n = ::write (fd_, opage.body, opage.body_len);
343 if (n != opage.body_len)
return -1;
351 if (OPUS_OK != opus_encoder_ctl (enc_, OPUS_GET_LOOKAHEAD (&lookahead)))
356 char magic[8] = {
'O',
'p',
'u',
's',
'H',
'e',
'a',
'd' };
364 } __attribute__ ((packed));
366 .channels = n_channels_,
367 .pre_skip_le = htole16 (lookahead),
368 .rate_le = htole32 (rate_),
370 static_assert (
sizeof (oh) == 19);
373 .bytes =
sizeof (oh),
374 .b_o_s = 0, .e_o_s = 0,
376 .packetno = packetno_++
378 if (write_packet (&op0,
true) < 0)
383 cmtheader +=
"OpusTags";
384 const String opus_version = opus_get_version_string();
385 u32_le = htole32 (opus_version.
size());
386 cmtheader +=
String ((
char*) &u32_le, 4);
387 cmtheader += opus_version;
391 u32_le = htole32 (tags.
size());
392 cmtheader +=
String ((
char*) &u32_le, 4);
393 for (
const auto &tag : tags)
395 u32_le = htole32 (tag.size());
396 cmtheader +=
String ((
char*) &u32_le, 4);
402 .b_o_s = 0, .e_o_s = 0,
404 .packetno = packetno_++
406 if (write_packet (&op1,
true) < 0)
411 write_ogg (
uint8_t *data,
long l,
bool force_flush)
416 .b_o_s = 0, .e_o_s = eos_,
417 .granulepos = granulepos_,
418 .packetno = packetno_++
420 if (write_packet (&op, force_flush) < 0)
425 write (
const float *frames,
size_t n_frames)
override
427 return write_opus (frames, n_frames,
false);
430 write_opus (
const float *frames,
size_t n_frames,
bool force_flush)
437 const float *fend = frames + n_frames * n_channels_;
438 const float *bmax = buffer_.data() + buffer_.size();
439 while (frames < fend)
441 ssize_t l =
MIN (bmax - bmark_, fend - frames);
448 bmark_ = buffer_.data();
449 const uint n_frames = buffer_.size() / n_channels_;
450 granulepos_ += n_frames;
451 l = opus_encode_float (enc_, bmark_, n_frames, pmem,
sizeof (pmem));
454 printerr (
"%s: OpusWriter encoding error: %s\n", name_, opus_strerror (l));
455 finish_and_close (
false);
459 if (l > 0 && write_ogg (pmem, l, force_flush) < 0)
461 const int serrno =
errno;
462 finish_and_close (
false);
471 finish_and_close (
bool flush)
477 const size_t n_filled = bmark_ - buffer_.data();
479 const size_t n_floats = buffer_.size() - n_filled;
480 float zeros[n_floats];
483 err &= write_opus (zeros, n_floats / n_channels_,
true) < 0;
486 err &= ::close (fd_) < 0;
495 return finish_and_close (
true);
500wave_writer_create_opus (
int rate,
int channels,
const String &filename,
int mode,
int complexity,
float bitrate)
503 if (ow->create (mode) ==
false)
505 if (!ow->setup_encoder (rate, channels, complexity, bitrate))
512wave_writer_flac_version()
514 return FLAC__VERSION_STRING;
519 FLAC__StreamEncoder *enc_ =
nullptr;
520 FLAC__StreamMetadata *metadata_[2] = {
nullptr,
nullptr };
529 ibuffer_.reserve (65536);
530 flush_atquit = [
this] () {
if (enc_) close(); };
531 atquit_add (&flush_atquit);
535 atquit_del (&flush_atquit);
542 FLAC__stream_encoder_delete (enc_);
545 FLAC__metadata_object_delete (metadata_[0]);
546 metadata_[0] =
nullptr;
553 const bool ok = FLAC__stream_encoder_finish (enc_);
554 const int saved_errno =
errno;
558 printerr (
"%s: FlacWriter error: %s\n", name_,
strerror (saved_errno ? saved_errno :
EIO));
562 create (
int mode,
int rate,
int channels,
int compresion)
569 const int fd =
open (name_.c_str(), O_CREAT | O_TRUNC | O_RDWR, mode);
571 FILE *file =
fdopen (fd,
"w+b");
577 enc_ = FLAC__stream_encoder_new();
584 n_channels_ = channels;
585 bool setup_ok =
true;
586 setup_ok &= FLAC__stream_encoder_set_channels (enc_, n_channels_);
587 setup_ok &= FLAC__stream_encoder_set_bits_per_sample (enc_, 24);
588 setup_ok &= FLAC__stream_encoder_set_sample_rate (enc_, rate_);
589 setup_ok &= FLAC__stream_encoder_set_compression_level (enc_, compresion);
592 metadata_[0] = FLAC__metadata_object_new (FLAC__METADATA_TYPE_VORBIS_COMMENT);
593 for (
const auto &tag : tags)
595 FLAC__StreamMetadata_VorbisComment_Entry entry = {
uint32_t (tag.size()), (
uint8_t*) tag.data() };
596 setup_ok &= FLAC__metadata_object_vorbiscomment_append_comment (metadata_[0], entry,
true);
598 setup_ok &= FLAC__stream_encoder_set_metadata (enc_, metadata_, 1);
599 printerr (
"%s:%d: ok=%d\n", __FILE__, __LINE__, setup_ok);
600 setup_ok &= FLAC__STREAM_ENCODER_INIT_STATUS_OK == FLAC__stream_encoder_init_FILE (enc_, file,
nullptr,
nullptr);
601 printerr (
"%s:%d: ok=%d\n", __FILE__, __LINE__, setup_ok);
609 write (
const float *frames,
size_t n_frames)
override
615 const size_t n_samples = n_frames * n_channels_;
616 if (ibuffer_.size() < n_samples)
617 ibuffer_.resize (n_samples);
618 for (
size_t i = 0; i < n_samples; i++)
620 int32_t v = frames[i] * 8388607.5 - 0.5;
621 ibuffer_[i] =
CLAMP (v, -8388608, +8388607);
623 const bool ok = FLAC__stream_encoder_process_interleaved (enc_, ibuffer_.data(), n_frames);
627 name()
const override
634wave_writer_create_flac (
int rate,
int channels,
const String &filename,
int mode,
int compresion)
637 if (ow->create (mode, rate, channels, compresion) ==
false)
#define assert_return(expr,...)
Return from the current function if expr is unmet and issue an assertion warning.
#define MIN(a, b)
Yield minimum of a and b.
#define return_unless(cond,...)
Return silently if cond does not evaluate to true with return value ...
#define CLAMP(v, mi, ma)
Yield v clamped to [mi … ma].
The Anklang C++ API namespace.
void floatfill(float *dst, float f, size_t n)
Fill n values of dst with f.
std::string String
Convenience alias for std::string.
uint32_t uint
Provide 'uint' as convenience type.
void fast_copy(size_t n, float *d, const float *s)
Copy a block of floats.
uint64_t random_int64()
Generate a non-deterministic, uniformly distributed 64 bit pseudo-random number.