21WaveWriter::~WaveWriter ()
26wav_header (
const uint8_t n_bits,
const uint32_t n_channels,
const uint32_t sample_freq,
const uint32_t n_samples)
33 puts (
const char *str)
40 const uint32_t byte_per_sample = n_channels * n_bits / 8;
41 const uint32_t byte_per_second = byte_per_sample * sample_freq;
42 const uint32_t n_data_bytes = (n_samples * byte_per_sample + 1) / 2 * 2;
45 ByteStream b { &buffer[0] };
47 const ByteStream lpos = b;
49 const ByteStream cpos = b;
52 const uint16_t fmt = n_bits == 32 ? 3 : 1;
53 const bool extensible = n_channels > 2 || fmt == 3;
54 const uint32_t fmtsz = extensible ? 18 : 16;
55 *b.u32++ = htole32 (fmtsz);
56 *b.u16++ = htole16 (fmt);
57 *b.u16++ = htole16 (n_channels);
58 *b.u32++ = htole32 (sample_freq);
59 *b.u32++ = htole32 (byte_per_second);
60 *b.u16++ = htole16 (byte_per_sample);
61 *b.u16++ = htole16 (n_bits);
63 *b.u16++ = htole16 (0);
67 *b.u32++ = htole32 (4);
68 *b.u32++ = htole32 (n_samples);
71 *b.u32++ = htole32 (n_data_bytes);
72 const uint32_t length = b.c - cpos.c + n_data_bytes;
73 *lpos.u32 = htole32 (length);
74 buffer.resize (b.u8 - &buffer[0]);
79wav_write (
int fd, uint8_t n_bits, uint32_t n_channels, uint32_t sample_freq,
const float *samples,
size_t n_frames)
81 const size_t n_samples = n_channels * n_frames;
84 uint8_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
85 for (
size_t n = 0; n < n_samples; )
87 const uint8_t u8 = 127.5 + 127.5 * samples[n++];
89 if (b + 1 >= e || n >= n_samples)
91 if (n >= n_samples && (n_channels & 1) && (n_samples & 1))
93 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
101 uint8_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
102 for (
size_t n = 0; n < n_samples; )
104 const int32_t i24 = samples[n++] * 8388607.5 - 0.5;
108 if (b + 4 >= e || n >= n_samples)
110 if (n >= n_samples && (n_channels & 1) && (n_samples & 1))
112 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
120 uint16_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
121 for (
size_t n = 0; n < n_samples; )
123 const int16_t i16 = samples[n++] * 32767.5 - 0.5;
124 *b++ = htole16 (i16);
125 if (b >= e || n >= n_samples)
127 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
135 uint32_t buffer[16384], *
const e = buffer +
sizeof (buffer) /
sizeof (buffer[0]), *b = buffer;
136 for (
size_t n = 0; n < n_samples; )
138 union {
float f;
uint32_t u32; } u { samples[n++] };
139 *b++ = htole32 (u.u32);
140 if (b >= e || n >= n_samples)
142 if (write (fd, buffer, (b - buffer) *
sizeof (buffer[0])) < 0)
157 size_t n_samples_ = 0;
162 flush_atquit = [
this] () { close(); };
163 atquit_add (&flush_atquit);
167 atquit_del (&flush_atquit);
175 assert_return (n_bits == 8 || n_bits == 16 || n_bits == 24 || n_bits == 32,
false);
179 fd_ = ::open (filename.
c_str(), O_CREAT | O_WRONLY | O_TRUNC, 0644);
182 if (
lseek (fd_, 0, SEEK_SET) < 0)
189 filename_ = filename;
191 n_channels_ = n_channels;
192 sample_freq_ = sample_freq;
196 if (::write (fd_, header.data(), header.size()) < 0)
205 name ()
const override
210 write (
const float *frames,
size_t n_frames)
override
216 n_samples_ += n_frames * n_channels_;
218 return wav_write (fd_, n_bits_, n_channels_, sample_freq_, frames, n_frames) >= 0;
226 if (
lseek (fd_, 0, SEEK_SET) >= 0)
227 ok &= ::write (fd_, header.data(), header.size()) >= 0;
228 ok &=::close (fd_) >= 0;
235wave_writer_create_wav (
int rate,
int channels,
const String &filename,
int mode, uint8_t n_bits)
238 if (wavw->open (filename, n_bits, channels, rate) ==
false)
245wave_writer_opus_version()
247 return opus_get_version_string();
252 OpusEncoder *enc_ =
nullptr;
254 float *bmark_ =
nullptr;
256 ogg_stream_state ostream_ = { 0, };
267 flush_atquit = [
this] () { finish_and_close (
true); };
268 atquit_add (&flush_atquit);
272 atquit_del (&flush_atquit);
274 opus_encoder_destroy (enc_);
276 ogg_stream_clear (&ostream_);
279 name()
const override
288 fd_ =
open (name_.c_str(), O_CREAT | O_TRUNC | O_WRONLY, mode);
292 setup_encoder (
int rate,
int channels,
int complexity,
float bitrate)
301 n_channels_ = channels;
302 enc_ = opus_encoder_create (rate_, n_channels_, OPUS_APPLICATION_AUDIO, &error);
303 if (error == OPUS_OK)
305 bitrate = n_channels_ * bitrate * 1000;
307 if (OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_BITRATE (
MIN (256000 * n_channels_, bitrate))) &&
308 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_VBR (1)) &&
309 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_VBR_CONSTRAINT (0)) &&
310 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_FORCE_CHANNELS (n_channels_)) &&
311 OPUS_OK == opus_encoder_ctl (enc_, OPUS_SET_COMPLEXITY (complexity)) &&
312 ogg_stream_init (&ostream_, serialno) >= 0)
314 const int std_fragment_size = 20 * 48000 / 1000;
315 int fragment_size = std_fragment_size * rate_ / 48000;
316 buffer_.resize (fragment_size * n_channels_);
317 bmark_ = buffer_.data();
318 if (write_header() > 0)
322 finish_and_close (
false);
327 write_packet (ogg_packet *op,
bool force_flush)
329 ogg_stream_packetin (&ostream_, op);
331 auto stream_pageout = force_flush ? ogg_stream_flush : ogg_stream_pageout;
332 while (stream_pageout (&ostream_, &opage))
336 n = ::write (fd_, opage.header, opage.header_len);
338 if (n != opage.header_len)
return -1;
340 n = ::write (fd_, opage.body, opage.body_len);
342 if (n != opage.body_len)
return -1;
350 if (OPUS_OK != opus_encoder_ctl (enc_, OPUS_GET_LOOKAHEAD (&lookahead)))
355 char magic[8] = {
'O',
'p',
'u',
's',
'H',
'e',
'a',
'd' };
363 } __attribute__ ((packed));
365 .channels = n_channels_,
366 .pre_skip_le = htole16 (lookahead),
367 .rate_le = htole32 (rate_),
369 static_assert (
sizeof (oh) == 19);
372 .bytes =
sizeof (oh),
373 .b_o_s = 0, .e_o_s = 0,
375 .packetno = packetno_++
377 if (write_packet (&op0,
true) < 0)
382 cmtheader +=
"OpusTags";
383 const String opus_version = opus_get_version_string();
384 u32_le = htole32 (opus_version.
size());
385 cmtheader +=
String ((
char*) &u32_le, 4);
386 cmtheader += opus_version;
390 u32_le = htole32 (tags.
size());
391 cmtheader +=
String ((
char*) &u32_le, 4);
392 for (
const auto &tag : tags)
394 u32_le = htole32 (tag.size());
395 cmtheader +=
String ((
char*) &u32_le, 4);
401 .b_o_s = 0, .e_o_s = 0,
403 .packetno = packetno_++
405 if (write_packet (&op1,
true) < 0)
410 write_ogg (
uint8_t *data,
long l,
bool force_flush)
415 .b_o_s = 0, .e_o_s = eos_,
416 .granulepos = granulepos_,
417 .packetno = packetno_++
419 if (write_packet (&op, force_flush) < 0)
424 write (
const float *frames,
size_t n_frames)
override
426 return write_opus (frames, n_frames,
false);
429 write_opus (
const float *frames,
size_t n_frames,
bool force_flush)
436 const float *fend = frames + n_frames * n_channels_;
437 const float *bmax = buffer_.data() + buffer_.size();
438 while (frames < fend)
440 ssize_t l =
MIN (bmax - bmark_, fend - frames);
447 bmark_ = buffer_.data();
448 const uint n_frames = buffer_.size() / n_channels_;
449 granulepos_ += n_frames;
450 l = opus_encode_float (enc_, bmark_, n_frames, pmem,
sizeof (pmem));
453 printerr (
"%s: OpusWriter encoding error: %s\n", name_, opus_strerror (l));
454 finish_and_close (
false);
458 if (l > 0 && write_ogg (pmem, l, force_flush) < 0)
460 const int serrno =
errno;
461 finish_and_close (
false);
470 finish_and_close (
bool flush)
476 const size_t n_filled = bmark_ - buffer_.data();
478 const size_t n_floats = buffer_.size() - n_filled;
479 float zeros[n_floats];
482 err &= write_opus (zeros, n_floats / n_channels_,
true) < 0;
485 err &= ::close (fd_) < 0;
494 return finish_and_close (
true);
499wave_writer_create_opus (
int rate,
int channels,
const String &filename,
int mode,
int complexity,
float bitrate)
502 if (ow->create (mode) ==
false)
504 if (!ow->setup_encoder (rate, channels, complexity, bitrate))
511wave_writer_flac_version()
513 return FLAC__VERSION_STRING;
518 FLAC__StreamEncoder *enc_ =
nullptr;
519 FLAC__StreamMetadata *metadata_[2] = {
nullptr,
nullptr };
528 ibuffer_.reserve (65536);
529 flush_atquit = [
this] () {
if (enc_) close(); };
530 atquit_add (&flush_atquit);
534 atquit_del (&flush_atquit);
541 FLAC__stream_encoder_delete (enc_);
544 FLAC__metadata_object_delete (metadata_[0]);
545 metadata_[0] =
nullptr;
552 const bool ok = FLAC__stream_encoder_finish (enc_);
553 const int saved_errno =
errno;
557 printerr (
"%s: FlacWriter error: %s\n", name_,
strerror (saved_errno ? saved_errno :
EIO));
561 create (
int mode,
int rate,
int channels,
int compresion)
568 const int fd =
open (name_.c_str(), O_CREAT | O_TRUNC | O_RDWR, mode);
570 FILE *file =
fdopen (fd,
"w+b");
576 enc_ = FLAC__stream_encoder_new();
583 n_channels_ = channels;
584 bool setup_ok =
true;
585 setup_ok &= FLAC__stream_encoder_set_channels (enc_, n_channels_);
586 setup_ok &= FLAC__stream_encoder_set_bits_per_sample (enc_, 24);
587 setup_ok &= FLAC__stream_encoder_set_sample_rate (enc_, rate_);
588 setup_ok &= FLAC__stream_encoder_set_compression_level (enc_, compresion);
591 metadata_[0] = FLAC__metadata_object_new (FLAC__METADATA_TYPE_VORBIS_COMMENT);
592 for (
const auto &tag : tags)
594 FLAC__StreamMetadata_VorbisComment_Entry entry = {
uint32_t (tag.size()), (
uint8_t*) tag.data() };
595 setup_ok &= FLAC__metadata_object_vorbiscomment_append_comment (metadata_[0], entry,
true);
597 setup_ok &= FLAC__stream_encoder_set_metadata (enc_, metadata_, 1);
598 printerr (
"%s:%d: ok=%d\n", __FILE__, __LINE__, setup_ok);
599 setup_ok &= FLAC__STREAM_ENCODER_INIT_STATUS_OK == FLAC__stream_encoder_init_FILE (enc_, file,
nullptr,
nullptr);
600 printerr (
"%s:%d: ok=%d\n", __FILE__, __LINE__, setup_ok);
608 write (
const float *frames,
size_t n_frames)
override
614 const size_t n_samples = n_frames * n_channels_;
615 if (ibuffer_.size() < n_samples)
616 ibuffer_.resize (n_samples);
617 for (
size_t i = 0; i < n_samples; i++)
619 int32_t v = frames[i] * 8388607.5 - 0.5;
620 ibuffer_[i] =
CLAMP (v, -8388608, +8388607);
622 const bool ok = FLAC__stream_encoder_process_interleaved (enc_, ibuffer_.data(), n_frames);
626 name()
const override
633wave_writer_create_flac (
int rate,
int channels,
const String &filename,
int mode,
int compresion)
636 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.