kwave  18.07.70
OpusEncoder.cpp
Go to the documentation of this file.
1 /*************************************************************************
2  OpusEncoder.cpp - sub encoder base class for Opus in an Ogg container
3  -------------------
4  begin : Thu Jan 03 2013
5  copyright : (C) 2013 by Thomas Eschenbacher
6  email : Thomas.Eschenbacher@gmx.de
7 
8  ***************************************************************************
9  * *
10  * This program is free software; you can redistribute it and/or modify *
11  * it under the terms of the GNU General Public License as published by *
12  * the Free Software Foundation; either version 2 of the License, or *
13  * (at your option) any later version. *
14  * *
15  ***************************************************************************
16 
17  parts based on source snippets taken from "opusenc.c", opus-tools-0.1.5
18  -------------------------------------------------------------------------
19  Copyright (C) 2002-2011 Jean-Marc Valin <jmvalin@jmvalin.ca>
20  Copyright (C) 2007-2012 Xiph.Org Foundation <monty@xiph.org/>
21  Copyright (C) 2008-2012 Gregory Maxwell <greg@xiph.org>
22  File: opusenc.c
23 
24  Redistribution and use in source and binary forms, with or without
25  modification, are permitted provided that the following conditions
26  are met:
27 
28  - Redistributions of source code must retain the above copyright
29  notice, this list of conditions and the following disclaimer.
30 
31  - Redistributions in binary form must reproduce the above copyright
32  notice, this list of conditions and the following disclaimer in the
33  documentation and/or other materials provided with the distribution.
34 
35  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
36  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
38  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
39  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
40  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
41  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
42  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
43  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
44  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
45  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 
47  ***************************************************************************/
48 
49 #include "config.h"
50 
51 #include <math.h>
52 #include <string.h>
53 
54 #include <opus/opus_defines.h>
55 
56 #include <QApplication>
57 #include <QBuffer>
58 #include <QByteArray>
59 #include <QList>
60 #include <QString>
61 #include <QTime>
62 #include <QtGlobal>
63 #include <QtEndian>
64 
65 #include <KLocalizedString>
66 
67 #include "libkwave/BitrateMode.h"
68 #include "libkwave/Connect.h"
69 #include "libkwave/MessageBox.h"
71 #include "libkwave/Sample.h"
72 #include "libkwave/SampleArray.h"
73 #include "libkwave/Utils.h"
76 
77 #include "OpusCommon.h"
78 #include "OpusEncoder.h"
79 
81 #define BITRATE_MIN 500
82 
84 #define BITRATE_MAX 256000
85 
87 #define SAMPLE_RATE_MIN 1000
88 
90 #define SAMPLE_RATE_MAX 512000
91 
93 #define DEFAULT_COMPLEXITY 10
94 
95 /***************************************************************************/
97  :m_comments_map(),
98  m_info(),
99  m_downmix(DOWNMIX_AUTO),
100  m_bitrate(0),
101  m_coding_rate(0),
102  m_encoder_channels(0),
103  m_channel_mixer(Q_NULLPTR),
104  m_rate_converter(Q_NULLPTR),
105  m_frame_size(0),
106  m_extra_out(0),
107  m_opus_header(),
108  m_max_frame_bytes(0),
109  m_packet_buffer(Q_NULLPTR),
110  m_encoder(Q_NULLPTR),
111  m_encoder_input(Q_NULLPTR),
112  m_last_queue_element(Q_NULLPTR),
113  m_buffer(Q_NULLPTR)
114 {
115 
116  memset(&m_opus_header, 0x00, sizeof(m_opus_header));
117  memset(&m_opus_header.map, 0xFF, sizeof(m_opus_header.map));
118 }
119 
120 /***************************************************************************/
122 {
123 }
124 
125 /***************************************************************************/
126 bool Kwave::OpusEncoder::setupDownMix(QWidget *widget, unsigned int tracks,
127  int bitrate)
128 {
129  // get "downmix" setting, default is "auto"
130  m_downmix = DOWNMIX_AUTO; // currently not user configurable
131 
132  if ((m_downmix == DOWNMIX_AUTO) &&
133  (bitrate > 0) && (bitrate < (32000 * Kwave::toInt(tracks))))
134  {
135  if (tracks > 8) {
136  // downmix from more than 8 channels to mono
138  widget,
139  i18n("Surround bitrate would be less than 32kBit/sec per "
140  "channel, this file should be mixed down to mono."),
141  QString(), QString(), QString(),
142  _("opus_accept_down_mix_on_export")) != KMessageBox::Continue)
143  {
144  return false;
145  }
147  } else if (tracks > 2) {
148  // downmix from more than stereo to stereo
150  widget,
151  i18n("Surround bitrate would be less than 32kBit/sec per "
152  "channel, this file should be mixed down to stereo."),
153  QString(), QString(), QString(),
154  _("opus_accept_down_mix_on_export")) != KMessageBox::Continue)
155  {
156  return false;
157  }
159  }
160  }
161  if (m_downmix == DOWNMIX_AUTO) // if still "auto"
162  m_downmix = DOWNMIX_OFF; // then switch it off
163 
164  switch (m_downmix) {
165  case DOWNMIX_MONO: m_encoder_channels = 1; break;
166  case DOWNMIX_STEREO: m_encoder_channels = 2; break;
167  default: m_encoder_channels = tracks; break;
168  }
169 
170  if (m_encoder_channels != tracks) {
171  // create a channel mixer
173  Q_ASSERT(m_channel_mixer);
174  if (!m_channel_mixer || !m_channel_mixer->init()) {
175  qWarning("creating channel mixer failed");
176  return false;
177  }
178 
179  // connect it to the end of the current preprocessing queue
180  // (normally this is the original sample source)
181  if (!Kwave::connect(
182  *m_last_queue_element, SIGNAL(output(Kwave::SampleArray)),
183  *m_channel_mixer, SLOT(input(Kwave::SampleArray))))
184  {
185  qWarning("connecting the channel mixer failed");
186  return false;
187  }
189  }
190 
191  return true;
192 }
193 
194 /***************************************************************************/
195 bool Kwave::OpusEncoder::setupBitrate(QWidget *widget, unsigned int tracks)
196 {
197  int bitrate_nominal = m_info.contains(Kwave::INF_BITRATE_NOMINAL) ?
198  QVariant(m_info.get(Kwave::INF_BITRATE_NOMINAL)).toInt() : -1;
199  int bitrate_lower = m_info.contains(Kwave::INF_BITRATE_LOWER) ?
200  QVariant(m_info.get(Kwave::INF_BITRATE_LOWER)).toInt() : -1;
201  int bitrate_upper = m_info.contains(Kwave::INF_BITRATE_UPPER) ?
202  QVariant(m_info.get(Kwave::INF_BITRATE_UPPER)).toInt() : -1;
203 
204  // prefer bitrates in this order:
205  // nominal -> upper -> lower -> "auto" (-1)
206  int bitrate = -1;
207  if (bitrate_nominal > 0) bitrate = bitrate_nominal;
208  else if (bitrate_upper > 0) bitrate = bitrate_upper;
209  else if (bitrate_lower > 0) bitrate = bitrate_lower;
210 
211  if ((bitrate > 0) && ((bitrate > (BITRATE_MAX * Kwave::toInt(tracks)))
212  || (bitrate < BITRATE_MIN)))
213  {
214  int bitrate_new =
215  qBound<int>(BITRATE_MIN, bitrate, BITRATE_MAX * tracks);
216 
218  widget,
219  i18nc("%1=original bitrate, %2=new/limited bitrate",
220  "Bitrate %1 kBit/sec is out of range, "
221  "limited to %2 kBit/sec",
222  bitrate / 1000,
223  bitrate_new / 1000),
224  QString(), QString(), QString(),
225  _("opus_bitrate_limit")) != KMessageBox::Continue)
226  {
227  return false;
228  }
229  }
230 
231  if (bitrate > 0)
232  qDebug(" OpusEncoder: bitrate %d bits/sec (configured)", bitrate);
233  m_bitrate = bitrate;
234  return true;
235 }
236 
237 /***************************************************************************/
239  unsigned int tracks, double rate)
240 {
241  Q_UNUSED(widget);
242 
243  Q_ASSERT(!m_rate_converter);
244 
245  int rate_orig = Kwave::toInt(rate);
246  int rate_supp = Kwave::opus_next_sample_rate(rate_orig);
247 
248  m_coding_rate = rate_supp;
249 
250  if (rate_orig == rate_supp) {
251  qDebug(" OpusEncoder: using sample rate %d", rate_orig);
252  return true; // no conversion needed :-)
253  }
254 
255  double rate_from = static_cast<double>(rate_orig);
256  double rate_to = static_cast<double>(rate_supp);
257  double ratio = rate_to / rate_from;
258 
259  qDebug(" OpusEncoder: converting sample rate: %d -> %d",
260  rate_orig, rate_supp);
261 
262  // range check: conversion ration must be between 1/256 and 256
263  if ((ratio < (1.0 / 256.0)) || (ratio > 256.0)) {
264  int lowest = qMin<int>(SAMPLE_RATE_MIN,
265  Kwave::toInt(ceil( rate_to / 256.0)));
266  int highest = qMax<int>(Kwave::toInt(floor(rate_to * 256.0)),
269  widget,
270  i18nc("%1=requested sample rate, "
271  "%2=lowest supported, %3=highest supported",
272  "Sample rate %1 samples/sec is out of range,\n"
273  "supported are %2 ... %3 samples/sec.",
274  rate_supp, lowest, highest),
275  QString()
276  );
277  return false;
278  }
279 
280  // create a new rate converter
283  Q_ASSERT(m_rate_converter);
284  if (!m_rate_converter)
285  return false;
286 
288  SLOT(setRatio(QVariant)),
289  QVariant(ratio)
290  );
291 
292  // connect the rate converter to the end of the current preprocessing
293  // queue/ (normally this is either the original sample source or
294  // a channel mixer)
295  if (!Kwave::connect(
296  *m_last_queue_element, SIGNAL(output(Kwave::SampleArray)),
297  *m_rate_converter, SLOT(input(Kwave::SampleArray))))
298  {
299  qWarning("connecting the rate converter failed");
300  return false;
301  }
303 
304  return true;
305 }
306 
307 /***************************************************************************/
308 bool Kwave::OpusEncoder::setupEncoder(QWidget *widget, unsigned int tracks,
309  double rate)
310 {
311  // get the frame size in ms if present,
312  // otherwise fall back to the default of 20ms
313  // (supported values are 2.5, 5, 10, 20, 40, or 60 ms)
314  qreal ms_per_frame = 20.0; // default is 20ms
316  double len = m_info.get(INF_OPUS_FRAME_LEN).toDouble();
317  if (len >= 60)
318  ms_per_frame = 60.0;
319  else if (len >= 40)
320  ms_per_frame = 40.0;
321  else if (len >= 20)
322  ms_per_frame = 20.0;
323  else if (len >= 5)
324  ms_per_frame = 5;
325  else
326  ms_per_frame = 2.5;
327  qDebug(" OpusEncoder: %0.1f ms/frame", ms_per_frame);
328  } else {
329  ms_per_frame = 20.0; // <- default
330  qDebug(" OpusEncoder: %0.1f ms/frame (default)", ms_per_frame);
331  }
332 
333  // calculate the frame size in samples from the frame duration in ms
334  // = frame_length [ms] * bitrate [bits/sec] / 1000 [ms/sec]
336  (ms_per_frame * m_coding_rate) / 1000);
337 
338  if (tracks > 255) {
339  qWarning("too many tracks: %u, supported: 255", tracks);
340  return false; // more than 255 tracks are not supported
341  }
342 
343  // fill out all header fields
344  m_opus_header.channels = static_cast<quint8>(tracks);
345  m_opus_header.preskip = 0;
346  m_opus_header.sample_rate = static_cast<quint32>(rate);
347  m_opus_header.gain = 0;
348  m_opus_header.channel_mapping = 255;
349  m_opus_header.streams = static_cast<quint8>(tracks);
350  m_opus_header.coupled = 0;
351 
352  // determine channel mapping and coupling
353  quint8 force_narrow = 0x00;
354  if (tracks <= 8) {
355  /* apply a mapping as done in opusenc.c from opus-tools-0.1.5 */
356  static const quint8 opusenc_streams[8][10]= {
357  /* Coupled, NB_bitmap, mapping...*/
358  /* 1 */ {0, 0, 0 },
359  /* 2 */ {1, 0, 0, 1 },
360  /* 3 */ {1, 0, 0, 2, 1 },
361  /* 4 */ {2, 0, 0, 1, 2, 3 },
362  /* 5 */ {2, 0, 0, 4, 1, 2, 3 },
363  /* 6 */ {2, 1 << 3, 0, 4, 1, 2, 3, 5 },
364  /* 7 */ {2, 1 << 4, 0, 4, 1, 2, 3, 5, 6 },
365  /* 8 */ {3, 1 << 4, 0, 6, 1, 2, 3, 4, 5, 7 }
366  };
367  for (unsigned int i = 0; i < tracks; i++)
368  m_opus_header.map[i] = opusenc_streams[tracks - 1][i + 2];
369  force_narrow = opusenc_streams[tracks - 1][1];
370  m_opus_header.coupled = opusenc_streams[tracks - 1][0];
371  m_opus_header.streams = static_cast<quint8>(
372  tracks - m_opus_header.coupled);
373  m_opus_header.channel_mapping = (m_opus_header.streams > 1);
374 
375  qDebug(" OpusEncoder: %d stream(s) / %d coupled (mapping=%d)",
376  m_opus_header.streams, m_opus_header.coupled,
377  m_opus_header.channel_mapping);
378  } else {
379  /* map all channels 1:1 */
380  for (quint8 i = 0; i < m_opus_header.channels; ++i)
381  m_opus_header.map[i] = i;
382  qDebug(" OpusEncoder: mapping channels 1:1");
383  }
384 
385  // allocate a packet buffer
386  m_max_frame_bytes = ((1275 * 3) + 7) * m_opus_header.streams;
387  qDebug(" OpusEncoder: max frame size %u bytes", m_max_frame_bytes);
388  Q_ASSERT(!m_packet_buffer);
389  m_packet_buffer = static_cast<unsigned char *>(malloc(m_max_frame_bytes));
390  if (!m_packet_buffer) {
391  Kwave::MessageBox::error(widget, i18n("Out of memory"));
392  return false;
393  }
394 
395  // initialize the Opus encoder:
396  // frame sizes < 10ms can only use the MDCT modes,
397  // so we switch on RESTRICTED_LOWDELAY to save the extra 2.5ms of codec
398  // lookahead when we'll be using only small frames
399 
400  int err = OPUS_ALLOC_FAIL;
401  Q_ASSERT(!m_encoder);
402  m_encoder = opus_multistream_encoder_create(
403  m_coding_rate,
404  tracks,
405  m_opus_header.streams,
406  m_opus_header.coupled,
407  m_opus_header.map,
408  (ms_per_frame < 10.0) ? OPUS_APPLICATION_RESTRICTED_LOWDELAY :
409  OPUS_APPLICATION_AUDIO,
410  &err
411  );
412  if (err != OPUS_OK) {
414  i18n("Opus encoder failed"));
415  return false;
416  }
417 
418  if (force_narrow) {
419  for (unsigned int i = 0; i < m_opus_header.streams; i++ ) {
420  if (force_narrow & (1 << i)) {
421  ::OpusEncoder *oe = Q_NULLPTR;
422 
423  opus_multistream_encoder_ctl(
424  m_encoder,
425  OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, i, &oe
426  );
427 
428  int err_ctl = opus_encoder_ctl(oe,
429  OPUS_SET_MAX_BANDWIDTH_REQUEST, OPUS_BANDWIDTH_NARROWBAND);
430 
431  if (err_ctl != OPUS_OK) {
433  i18n("Opus encoder failed"));
434  return false;
435  }
436  }
437  }
438  }
439 
440  // allocate a buffer to be used as input of the encoder
441  m_encoder_input = static_cast<float *>(
442  malloc(sizeof(float) * m_frame_size * tracks));
443  if (!m_encoder_input) {
444  Kwave::MessageBox::error(widget, i18n("Out of memory"));
445  return false;
446  }
447 
448  return true;
449 }
450 
451 /***************************************************************************/
453 {
454  const bool with_cvbr = false;
455  int err;
456 
457  // determine a reasonable bitrate in case we still use "autodetect"
458  if (m_bitrate < 0) {
459  m_bitrate = (64000 * m_opus_header.streams) +
460  (32000 * m_opus_header.coupled);
461  m_bitrate = qBound<int>(500, m_bitrate, 256000);
462  qDebug(" OpusEncoder: bitrate %d bits/sec (auto)", m_bitrate);
463  }
464 
465  err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_BITRATE(
466  static_cast<opus_int32>(m_bitrate)));
467  if (err != OPUS_OK) {
469  i18n("Opus encoder failed setting bitrate: '%1'",
470  Kwave::opus_error(err)));
471  return false;
472  }
473 
474  int bitrate_mode = m_info.get(INF_BITRATE_MODE).toInt();
475  bool with_hard_cbr = (bitrate_mode == BITRATE_MODE_CBR_HARD);
476 
477  err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_VBR(
478  static_cast<opus_int32>(with_hard_cbr ? 0 : 1)));
479  if (err != OPUS_OK) {
481  i18n("Opus encoder failed configuring VBR mode: '%1'",
482  Kwave::opus_error(err)));
483  return false;
484  }
485 
486  if (!with_hard_cbr ) {
487  err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_VBR_CONSTRAINT(
488  static_cast<opus_int32>(with_cvbr ? 1 : 0)));
489  if (err != OPUS_OK) {
491  i18n("Opus encoder failed configuring VBR constraint: '%1'",
492  Kwave::opus_error(err)));
493  return false;
494  }
495  }
496 
497  return true;
498 }
499 
500 /***************************************************************************/
501 bool Kwave::OpusEncoder::open(QWidget *widget, const Kwave::FileInfo &info,
503 {
504  // get info: tracks, sample rate, bitrate(s)
505  m_info = info;
506  const unsigned int src_tracks = m_info.tracks();
507  const double sample_rate = m_info.rate();
508  int err;
509 
510  // reset everything to defaults
512  m_bitrate = -1;
513  m_coding_rate = 0;
514  m_extra_out = 0;
515  m_frame_size = 0;
516  memset(&m_opus_header, 0x00, sizeof(m_opus_header));
517  memset(&m_opus_header.map, 0xFF, sizeof(m_opus_header.map));
518  m_max_frame_bytes = 0;
519  m_last_queue_element = &src;
520 
521  // get the desired bitrate
522  if (!setupBitrate(widget, src_tracks))
523  return false;
524 
525  // determine the down mixing mode
526  // and set up the mixer if necessary
527  if (!setupDownMix(widget, src_tracks, m_bitrate))
528  return false;
529 
530  // determine the decoding sample rate
531  // and set up the rate converter if necessary
532  if (!setupCodingRate(widget, m_encoder_channels, sample_rate))
533  return false;
534 
535  // set up mapping, packet size and encoder
536  if (!setupEncoder(widget, m_encoder_channels, sample_rate))
537  return false;
538 
539  // set up bitrate mode (e.g. VBR, ABR, ...)
540  if (!setupBitrateMode(widget))
541  return false;
542 
543  // create a sample buffer at the end of the filter chain
546  );
547  Q_ASSERT(m_buffer);
548  if (!m_buffer) {
549  qWarning("cannot create sample buffer");
550  return false;
551  }
552  if (!Kwave::connect(
553  *m_last_queue_element, SIGNAL(output(Kwave::SampleArray)),
554  *m_buffer, SLOT(input(Kwave::SampleArray))) )
555  {
556  qWarning("failed to connect sample buffer");
557  return false;
558  }
559 
560  // set up the encoder complexity (ignore errors)
561  opus_int32 complexity = DEFAULT_COMPLEXITY;
562  err = opus_multistream_encoder_ctl(m_encoder,
563  OPUS_SET_COMPLEXITY(complexity));
564  if (err != OPUS_OK) {
565  qWarning("OpusEncoder: failed setting encoder complexity: '%s'",
566  DBG(Kwave::opus_error(err)));
567  }
568 
569  // set up the expected loss [percent] (ignore errors)
570  opus_int32 expect_loss = 0;
571  err = opus_multistream_encoder_ctl(m_encoder,
572  OPUS_SET_PACKET_LOSS_PERC(expect_loss));
573  if (err != OPUS_OK) {
574  qWarning("OpusEncoder: failed setting expected loss: '%s'",
575  DBG(Kwave::opus_error(err)));
576  }
577 
578 #ifdef OPUS_SET_LSB_DEPTH
579  // set up the LSB depth
580  opus_int32 bits = qBound<unsigned int>(8, m_info.bits(), 24);
581  err = opus_multistream_encoder_ctl(m_encoder, OPUS_SET_LSB_DEPTH(bits));
582  if (err != OPUS_OK) {
583  qWarning("OpusEncoder: failed setting LSB depth loss: '%s'",
584  DBG(Kwave::opus_error(err)));
585  }
586 #endif /* OPUS_SET_LSB_DEPTH */
587 
588  // get the lookahead value
589  opus_int32 lookahead;
590  err = opus_multistream_encoder_ctl(m_encoder,
591  OPUS_GET_LOOKAHEAD(&lookahead));
592  if (err != OPUS_OK) {
594  i18n("Opus encoder failed getting lookahead value: '%1'",
595  Kwave::opus_error(err)));
596  return false;
597  }
598 
599  // regardless of the rate we're coding at the ogg timestamping/skip is
600  // always timed at 48000 kBit/s
601  m_opus_header.preskip = static_cast<quint16>(
602  lookahead * (48000.0 / m_coding_rate));
603  qDebug(" OpusEncoder: preskip=%d", m_opus_header.preskip);
604 
605  /* Extra samples that need to be read to compensate for the pre-skip */
606  m_extra_out = lookahead;
607 
608 
609  // set up our packet->stream encoder
610  // pick a random serial number; that way we can more likely build
611  // chained streams just by concatenation
612  qsrand(QTime::currentTime().msec() ^ qrand());
613  ogg_stream_init(&m_os, qrand());
614 
615  return true;
616 }
617 
618 /***************************************************************************/
619 static inline void _writeInt(QBuffer &buffer, quint32 value)
620 {
621  quint32 x = qToLittleEndian<quint32>(value);
622  buffer.write(reinterpret_cast<const char *>(&x), sizeof(x));
623 }
624 
625 /***************************************************************************/
627 {
628  Kwave::opus_header_t header;
629  unsigned int len;
630 
631  // create an Opus header, using correct byte order
632  memset(&header, 0x00, sizeof(header));
633  memset(&header.map, 0xFF, sizeof(header.map));
634 
635  memcpy(&(header.magic[0]), "OpusHead", 8);
636  header.version = 1;
637  header.channels = m_opus_header.channels;
638  header.preskip = qToLittleEndian<quint16>(m_opus_header.preskip);
639  header.sample_rate = qToLittleEndian<quint32>(m_opus_header.sample_rate);
640  header.gain = qToLittleEndian<quint16>(m_opus_header.gain);
641  header.channel_mapping = m_opus_header.channel_mapping;
642  len = 19; // bytes so far
643  if (m_opus_header.channel_mapping) {
644  header.streams = m_opus_header.streams;
645  header.coupled = m_opus_header.coupled;
646  len += 2;
647 
648  for (quint8 i = 0; i < m_opus_header.channels; ++i)
649  header.map[i] = m_opus_header.map[i];
650  len += m_opus_header.channels;
651  }
652 
653  // write the header into the ogg stream
654  m_op.packet = reinterpret_cast<unsigned char *>(&header);
655  m_op.bytes = len;
656  m_op.b_o_s = 1;
657  m_op.e_o_s = 0;
658  m_op.granulepos = 0;
659  m_op.packetno = 0;
660  ogg_stream_packetin(&m_os, &m_op);
661 
662  while (ogg_stream_flush(&m_os, &m_og)) {
663  dst.write(reinterpret_cast<char *>(m_og.header),
664  m_og.header_len);
665  dst.write(reinterpret_cast<char *>(m_og.body),
666  m_og.body_len);
667  }
668 
669  return true;
670 }
671 
672 /***************************************************************************/
674 {
675  QBuffer buffer;
676 
677  buffer.open(QBuffer::ReadWrite);
678 
679  // let the header start with the magic string "OpusTags"
680  buffer.write("OpusTags", 8);
681 
682  // write the vendor string == name + version of the encoder library
683  const char *opus_version = opus_get_version_string();
684  quint32 len = quint32(strlen(opus_version));
685  _writeInt(buffer, len);
686  buffer.write(opus_version, len);
687 
688  // iterate over all known properties and collect them in a list
689  QList<QByteArray> tags;
690  len = 0;
691  foreach (const QString &key, m_comments_map.keys()) {
692  Kwave::FileProperty property = m_comments_map[key];
693  if (!m_info.contains(property)) continue; // skip if not present
694 
695  // convert the value into a byte array, UTF-8 encoded
696  QString str = key + _("=") + m_info.get(property).toString();
697  QByteArray v = str.toUtf8();
698 
699  // make sure that the "ENCODER" tag is at the start of the list
700  if ((property == INF_SOFTWARE) && (!tags.isEmpty()))
701  tags.prepend(v);
702  else
703  tags.append(v);
704 
705  len += (4 + v.size()); // sum up the data length
706  }
707 
708  // write the number of user tags
709  _writeInt(buffer, tags.count());
710 
711  // serialize the tags into the buffer
712  foreach (const QByteArray &tag, tags) {
713  _writeInt(buffer, tag.size());
714  buffer.write(tag);
715  }
716 
717  m_op.packet = reinterpret_cast<unsigned char *>(buffer.buffer().data());
718  m_op.bytes = static_cast<long int>(buffer.size());
719  m_op.b_o_s = 0;
720  m_op.e_o_s = 0;
721  m_op.granulepos = 0;
722  m_op.packetno = 1;
723  ogg_stream_packetin(&m_os, &m_op);
724 
725  while (ogg_stream_flush(&m_os, &m_og)) {
726  if (!writeOggPage(dst)) return false;
727  }
728 
729  return true;
730 }
731 
732 /***************************************************************************/
734 {
735  if (!writeOpusHeader(dst))
736  return false;
737 
738  if (!writeOpusTags(dst))
739  return false;
740 
741  return true;
742 }
743 
744 /***************************************************************************/
746 {
747  qint64 n;
748 
749  n = dst.write(reinterpret_cast<char *>(m_og.header), m_og.header_len);
750  if (n != m_og.header_len) {
751  qWarning("OpusEncoder: I/O error writing header, len=%u, written=%u",
752  static_cast<unsigned int>(n),
753  static_cast<unsigned int>(m_og.header_len));
754  return false; // write error ?
755  }
756 
757  n = dst.write(reinterpret_cast<char *>(m_og.body), m_og.body_len);
758  if (n != m_og.body_len) {
759  qWarning("OpusEncoder: I/O error writing body, len=%u, written=%u",
760  static_cast<unsigned int>(n),
761  static_cast<unsigned int>(m_og.body_len));
762  return false; // write error ?
763  }
764 
765  // update the progress bar
766  QApplication::processEvents();
767 
768  return true;
769 }
770 
771 /***************************************************************************/
773 {
774  unsigned int min_count = m_frame_size + 1; // will be used as "invalid"
775 
776  for (unsigned int t = 0; t < m_encoder_channels; ++t) {
777  Kwave::SampleBuffer *buf = m_buffer->at(t);
778  Q_ASSERT(buf);
779  if (!buf) return 0;
780 
781  unsigned int count = 0;
782  unsigned int rest = m_frame_size;
783  while (rest) {
784  float *p = m_encoder_input + t;
785 
786  // while buffer is empty and source is not at eof:
787  // trigger the start of the chain to produce some data
788  while (!buf->available() && !src.eof())
789  src.goOn();
790  const unsigned int avail = buf->available();
791  if (!avail) break; // reached EOF
792 
793  // while there is something in the current buffer
794  // and some rest is still to do
795  unsigned int len = qMin<unsigned int>(rest, avail);
796  const sample_t *s = buf->get(len);
797  Q_ASSERT(s);
798  if (!s) break;
799 
800  // fill the frame data
801  rest -= len;
802  count += len;
803  while (len--) {
804  *p = sample2float(*(s++));
805  p += m_encoder_channels;
806  }
807  }
808  if (count < min_count) min_count = count;
809  }
810 
811  // take the minimum number of samples if valid, otherwise zero (eof?)
812  unsigned int n = (min_count <= m_frame_size) ? min_count : 0;
813 
814  // if we were not able to fill a complete frame, we probably are at eof
815  // and have some space to pad with extra samples to compensate preskip
816  while ((n < m_frame_size) && m_extra_out) {
817  Q_ASSERT(src.eof());
818  for (unsigned int t = 0; t < m_encoder_channels; ++t) {
819  m_encoder_input[(n + t) * m_encoder_channels] = 0.0;
820  }
821  m_extra_out--;
822  n++;
823  }
824 
825  return n;
826 }
827 
828 /***************************************************************************/
830  QIODevice &dst)
831 {
832  long int eos = 0;
833  opus_int64 nb_encoded = 0;
834  opus_int64 nb_samples = -1;
835  opus_int64 total_bytes = 0;
836  opus_int64 total_samples = 0;
837  ogg_int64_t enc_granulepos = 0;
838  ogg_int64_t last_granulepos = 0;
839  ogg_int32_t packet_id = 1;
840  int last_segments = 0;
841  const int max_ogg_delay = 48000; /* 48kHz samples */
842 
843  Q_ASSERT(m_encoder);
844  Q_ASSERT(m_encoder_input);
845 
846  Q_UNUSED(dst);
847 
848  /* Main encoding loop (one frame per iteration) */
849  while (!m_op.e_o_s && !src.isCanceled()) {
850  int size_segments = 0;
851 
852  packet_id++;
853 
854  if (nb_samples < 0) {
855  nb_samples = fillInBuffer(src);
856  total_samples += nb_samples;
857  m_op.e_o_s = (nb_samples < m_frame_size) ? 1 : 0;
858  }
859  m_op.e_o_s |= eos; // eof from last pass
860 
861  // pad the rest of the frame with zeroes if necessary
862  if (nb_samples < m_frame_size ) {
863  const unsigned int pad_from =
864  Kwave::toUint(nb_samples * m_encoder_channels);
865  const unsigned int pad_to =
866  Kwave::toUint(m_frame_size * m_encoder_channels);
867  for (unsigned int pos = pad_from; pos < pad_to; pos++ )
868  m_encoder_input[pos] = 0;
869  }
870 
871  /* encode current frame */
872  int nbBytes = opus_multistream_encode_float(
873  m_encoder,
875  m_frame_size,
878  );
879  if (nbBytes < 0 ) {
880  qWarning("Opus encoder failed: '%s'",
881  DBG(Kwave::opus_error(nbBytes)));
882  return false;
883  }
884 
885  nb_encoded += m_frame_size;
886  enc_granulepos += m_frame_size * 48000 / m_coding_rate;
887  total_bytes += nbBytes;
888  size_segments = (nbBytes + 255) / 255;
889 
890  // flush early if adding this packet would make us end up with a
891  // continued page which we wouldn't have otherwise
892  while (( ((size_segments <= 255) &&
893  (last_segments + size_segments > 255)) ||
894  (enc_granulepos - last_granulepos > max_ogg_delay)) &&
895 #ifdef HAVE_OGG_STREAM_FLUSH_FILL
896  ogg_stream_flush_fill(&m_os, &m_og, 255 * 255))
897 #else /* HAVE_OGG_STREAM_FLUSH_FILL */
898  ogg_stream_flush(&m_os, &m_og))
899 #endif /* HAVE_OGG_STREAM_FLUSH_FILL */
900  {
901  if (ogg_page_packets(&m_og) != 0)
902  last_granulepos = ogg_page_granulepos(&m_og);
903 
904  last_segments -= m_og.header[26];
905 
906  if (!writeOggPage(dst)) {
907  qWarning("Opus encoder: I/O error");
908  return false;
909  }
910  }
911 
912  // the downside of early reading is if the input is an exact
913  // multiple of the frame_size you'll get an extra frame that needs
914  // to get cropped off. The downside of late reading is added delay.
915  // If your ogg_delay is 120ms or less we'll assume you want the
916  // low delay behavior.
917  if ((!m_op.e_o_s ) && (max_ogg_delay > 5760)) {
918  nb_samples = fillInBuffer(src);
919  total_samples += nb_samples;
920  if (nb_samples < m_frame_size) eos = 1;
921  if (nb_samples == 0) m_op.e_o_s = 1;
922  } else {
923  nb_samples = -1;
924  }
925 
926  m_op.packet = m_packet_buffer;
927  m_op.packetno = packet_id;
928  m_op.bytes = nbBytes;
929  m_op.b_o_s = 0;
930  m_op.granulepos = enc_granulepos;
931  if (m_op.e_o_s) {
932  // compute the final GP as ceil(len*48k/input_rate). When a
933  // resampling decoder does the matching floor(len*input/48k)
934  // conversion the length will be exactly the same as the input.
935  sample_index_t length = m_info.length();
936  double rate = m_info.rate();
937  m_op.granulepos = static_cast<ogg_int64_t>(
938  ceil((length * 48000.0) / rate) + m_opus_header.preskip);
939  }
940  ogg_stream_packetin(&m_os, &m_op);
941  last_segments += size_segments;
942 
943  // If the stream is over or we're sure that the delayed flush will
944  // fire, go ahead and flush now to avoid adding delay.
945  while ((m_op.e_o_s || (enc_granulepos +
946  ((m_frame_size * 48000) / m_coding_rate ) -
947  last_granulepos > max_ogg_delay) || (last_segments >= 255)) ?
948 #ifdef HAVE_OGG_STREAM_FLUSH_FILL
949  ogg_stream_flush_fill(&m_os, &m_og, 255 * 255) :
950  ogg_stream_pageout_fill(&m_os, &m_og, 255 * 255))
951 #else /* HAVE_OGG_STREAM_FLUSH_FILL */
952  /*Libogg > 1.2.2 allows us to achieve lower overhead by
953  producing larger pages. For 20ms frames this is only relevant
954  above ~32kbit/sec.*/
955  ogg_stream_flush(&m_os, &m_og) :
956  ogg_stream_pageout(&m_os, &m_og))
957 #endif /* HAVE_OGG_STREAM_FLUSH_FILL */
958  {
959  if (ogg_page_packets(&m_og) != 0)
960  last_granulepos = ogg_page_granulepos(&m_og);
961 
962  last_segments -= m_og.header[26];
963  if (!writeOggPage(dst)) {
964  qWarning("Opus encoder: I/O error");
965  return false;
966  }
967  }
968  }
969 
970  return true;
971 }
972 
973 /***************************************************************************/
975 {
976  if (m_channel_mixer) delete m_channel_mixer;
977  m_channel_mixer = Q_NULLPTR;
978 
980  m_rate_converter = Q_NULLPTR;
981 
982  if (m_buffer) delete m_buffer;
983  m_buffer = Q_NULLPTR;
984 
985  if (m_encoder) opus_multistream_encoder_destroy(m_encoder);
986  m_encoder = Q_NULLPTR;
987 
988  ogg_stream_clear(&m_os);
989 
990  if (m_packet_buffer) free(m_packet_buffer);
991  m_packet_buffer = Q_NULLPTR;
992 
993  if (m_encoder_input) free(m_encoder_input);
994  m_encoder_input = Q_NULLPTR;
995 
996  m_last_queue_element = Q_NULLPTR;
997 }
998 
999 /***************************************************************************/
1000 /***************************************************************************/
Kwave::opus_header_t m_opus_header
Definition: OpusEncoder.h:212
bool contains(const FileProperty property) const
Definition: FileInfo.cpp:354
int opus_next_sample_rate(int rate)
Definition: OpusCommon.cpp:30
virtual bool writeHeader(QIODevice &dst) Q_DECL_OVERRIDE
virtual const sample_t * get(unsigned int len)
unsigned int fillInBuffer(Kwave::MultiTrackReader &src)
Kwave::StreamObject * m_rate_converter
Definition: OpusEncoder.h:203
double rate() const
Definition: FileInfo.cpp:415
Kwave::FileInfo m_info
Definition: OpusEncoder.h:169
static void _writeInt(QBuffer &buffer, quint32 value)
bool writeOggPage(QIODevice &dst)
Kwave::VorbisCommentMap m_comments_map
Definition: OpusEncoder.h:166
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
static int sorry(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:85
bool writeOpusTags(QIODevice &dst)
quint64 sample_index_t
Definition: Sample.h:28
bool setupBitrate(QWidget *widget, unsigned int tracks)
float * m_encoder_input
Definition: OpusEncoder.h:224
bool connect(Kwave::StreamObject &source, const char *output, Kwave::StreamObject &sink, const char *input)
Definition: Connect.cpp:48
virtual void goOn() Q_DECL_OVERRIDE
#define BITRATE_MAX
Definition: OpusEncoder.cpp:84
unsigned int m_extra_out
Definition: OpusEncoder.h:209
virtual bool eof() const
Kwave::MultiTrackSink< Kwave::SampleBuffer, true > * m_buffer
Definition: OpusEncoder.h:234
virtual bool init()
unsigned int m_encoder_channels
Definition: OpusEncoder.h:197
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
bool writeOpusHeader(QIODevice &dst)
sample_index_t length() const
Definition: FileInfo.cpp:400
unsigned int m_max_frame_bytes
Definition: OpusEncoder.h:215
int toInt(T x)
Definition: Utils.h:127
Kwave::ChannelMixer * m_channel_mixer
Definition: OpusEncoder.h:200
virtual bool encode(Kwave::MultiTrackReader &src, QIODevice &dst) Q_DECL_OVERRIDE
bool setupEncoder(QWidget *widget, unsigned int tracks, double rate)
Kwave::StreamObject * m_last_queue_element
Definition: OpusEncoder.h:231
QString opus_error(int err)
Definition: OpusCommon.cpp:45
static float sample2float(const sample_t s)
Definition: Sample.h:65
static int warningContinueCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonContinue=QString(), const QString buttonCancel=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:115
unsigned int tracks() const
Definition: FileInfo.cpp:445
bool setupCodingRate(QWidget *widget, unsigned int tracks, double rate)
unsigned int m_frame_size
Definition: OpusEncoder.h:206
virtual void close() Q_DECL_OVERRIDE
#define _(m)
Definition: memcpy.c:66
ogg_stream_state m_os
Definition: OpusEncoder.h:172
#define DEFAULT_COMPLEXITY
Definition: OpusEncoder.cpp:93
#define SAMPLE_RATE_MIN
Definition: OpusEncoder.cpp:87
#define DBG(qs)
Definition: String.h:55
bool setupDownMix(QWidget *widget, unsigned int tracks, int bitrate)
#define SAMPLE_RATE_MAX
Definition: OpusEncoder.cpp:90
virtual unsigned int available() const
unsigned int toUint(T x)
Definition: Utils.h:109
unsigned char * m_packet_buffer
Definition: OpusEncoder.h:218
OpusMSEncoder * m_encoder
Definition: OpusEncoder.h:221
unsigned int bits() const
Definition: FileInfo.cpp:430
virtual bool open(QWidget *widget, const Kwave::FileInfo &info, Kwave::MultiTrackReader &src) Q_DECL_OVERRIDE
virtual ~OpusEncoder() Q_DECL_OVERRIDE
FileProperty
Definition: FileInfo.h:45
bool setupBitrateMode(QWidget *widget)
virtual SINK * at(unsigned int track) const
#define BITRATE_MIN
Definition: OpusEncoder.cpp:81
void setAttribute(const char *attribute, const QVariant &value)
qint32 sample_t
Definition: Sample.h:37
enum Kwave::OpusEncoder::@12 m_downmix