kwave  18.07.70
Kwave::VorbisEncoder Class Reference

#include <VorbisEncoder.h>

Inheritance diagram for Kwave::VorbisEncoder:
Inheritance graph
Collaboration diagram for Kwave::VorbisEncoder:
Collaboration graph

Public Member Functions

 VorbisEncoder ()
 
virtual ~VorbisEncoder () Q_DECL_OVERRIDE
 
virtual bool open (QWidget *widget, const Kwave::FileInfo &info, Kwave::MultiTrackReader &src) Q_DECL_OVERRIDE
 
virtual bool writeHeader (QIODevice &dst) Q_DECL_OVERRIDE
 
virtual bool encode (Kwave::MultiTrackReader &src, QIODevice &dst) Q_DECL_OVERRIDE
 
virtual void close () Q_DECL_OVERRIDE
 
- Public Member Functions inherited from Kwave::OggSubEncoder
virtual ~OggSubEncoder ()
 

Private Member Functions

void encodeProperties (const Kwave::FileInfo &info)
 

Private Attributes

Kwave::VorbisCommentMap m_comments_map
 
Kwave::FileInfo m_info
 
ogg_stream_state m_os
 
ogg_page m_og
 
ogg_packet m_op
 
vorbis_info m_vi
 
vorbis_comment m_vc
 
vorbis_dsp_state m_vd
 
vorbis_block m_vb
 

Detailed Description

Definition at line 39 of file VorbisEncoder.h.

Constructor & Destructor Documentation

◆ VorbisEncoder()

Kwave::VorbisEncoder::VorbisEncoder ( )

Constructor

Definition at line 43 of file VorbisEncoder.cpp.

References m_og, m_op, m_os, m_vb, m_vc, m_vd, and m_vi.

45 {
46  memset(&m_os, 0x00, sizeof(m_os));
47  memset(&m_og, 0x00, sizeof(m_og));
48  memset(&m_op, 0x00, sizeof(m_op));
49 
50  memset(&m_vb, 0x00, sizeof(m_vb));
51  memset(&m_vc, 0x00, sizeof(m_vc));
52  memset(&m_vd, 0x00, sizeof(m_vd));
53  memset(&m_vi, 0x00, sizeof(m_vi));
54 }
ogg_stream_state m_os
Definition: VorbisEncoder.h:97
Kwave::FileInfo m_info
Definition: VorbisEncoder.h:94
vorbis_comment m_vc
Kwave::VorbisCommentMap m_comments_map
Definition: VorbisEncoder.h:91
vorbis_dsp_state m_vd

◆ ~VorbisEncoder()

Kwave::VorbisEncoder::~VorbisEncoder ( )
virtual

Destructor

Definition at line 57 of file VorbisEncoder.cpp.

References close().

58 {
59  close();
60 }
virtual void close() Q_DECL_OVERRIDE
Here is the call graph for this function:

Member Function Documentation

◆ close()

void Kwave::VorbisEncoder::close ( )
virtual

finished the encoding, clean up

Implements Kwave::OggSubEncoder.

Definition at line 310 of file VorbisEncoder.cpp.

References m_os, m_vb, m_vc, m_vd, and m_vi.

Referenced by ~VorbisEncoder().

311 {
312  ogg_stream_clear(&m_os);
313 
314  vorbis_block_clear(&m_vb);
315  vorbis_dsp_clear(&m_vd);
316  vorbis_comment_clear(&m_vc);
317  vorbis_info_clear(&m_vi); // <- must be called last
318 }
ogg_stream_state m_os
Definition: VorbisEncoder.h:97
vorbis_comment m_vc
vorbis_dsp_state m_vd
Here is the caller graph for this function:

◆ encode()

bool Kwave::VorbisEncoder::encode ( Kwave::MultiTrackReader src,
QIODevice &  dst 
)
virtual

encode received ogg data

Parameters
srcMultiTrackReader used as source of the audio data
dsta QIODevice that receives the raw data
Returns
true if succeeded, false if failed

Implements Kwave::OggSubEncoder.

Definition at line 229 of file VorbisEncoder.cpp.

References BUFFER_SIZE, Kwave::SampleArray::constData(), Kwave::MultiTrackReader::eof(), Kwave::MultiTrackReader::isCanceled(), Kwave::FileInfo::length(), m_info, m_og, m_op, m_os, m_vb, m_vd, sample2float(), Kwave::toUint(), and Kwave::FileInfo::tracks().

231 {
232  bool eos = false;
233  const unsigned int tracks = m_info.tracks();
234  const sample_index_t length = m_info.length();
235 
236  sample_index_t rest = length;
237  while (!eos && !src.isCanceled()) {
238  if (src.eof()) {
239  // end of file. this can be done implicitly in the mainline,
240  // but it's easier to see here in non-clever fashion.
241  // Tell the library we're at end of stream so that it can handle
242  // the last frame and mark end of stream in the output properly
243  vorbis_analysis_wrote(&m_vd, 0);
244  } else {
245  // data to encode
246 
247  // expose the buffer to submit data
248  float **buffer = vorbis_analysis_buffer(&m_vd, BUFFER_SIZE);
249  unsigned int pos = 0;
250  unsigned int len = (rest > BUFFER_SIZE) ? BUFFER_SIZE :
251  Kwave::toUint(rest);
253  for (unsigned int track = 0; track < tracks; ++track) {
254  float *p = buffer[track];
255  unsigned int l = src[track]->read(samples, 0, len);
256  const sample_t *s = samples.constData();
257 
258  const unsigned int block = 8;
259  pos = 0;
260  while (pos + block < l) {
261  for (unsigned int i = 0; i < block; ++i, ++pos)
262  p[pos] = sample2float(s[pos]);
263  }
264  while (pos < l) {
265  p[pos] = sample2float(s[pos]);
266  pos++;
267  }
268  while (pos < len)
269  p[pos++] = 0;
270  }
271 
272  // tell the library how much we actually submitted
273  vorbis_analysis_wrote(&m_vd, pos);
274  }
275 
276  // vorbis does some data preanalysis, then divvies up blocks for
277  // more involved (potentially parallel) processing. Get a single
278  // block for encoding now
279  while (vorbis_analysis_blockout(&m_vd, &m_vb) == 1) {
280  // analysis, assume we want to use bitrate management
281  vorbis_analysis(&m_vb, Q_NULLPTR);
282  vorbis_bitrate_addblock(&m_vb);
283 
284  while (vorbis_bitrate_flushpacket(&m_vd, &m_op)) {
285  // weld the packet into the bitstream
286  ogg_stream_packetin(&m_os, &m_op);
287 
288  // write out pages (if any)
289  while (!eos) {
290  int result = ogg_stream_pageout(&m_os, &m_og);
291  if (!result) break;
292  dst.write(reinterpret_cast<char*>(m_og.header),
293  m_og.header_len);
294  dst.write(reinterpret_cast<char *>(m_og.body),
295  m_og.body_len);
296 
297  // this could be set above, but for illustrative
298  // purposes, I do it here (to show that vorbis
299  // does know where the stream ends)
300  if (ogg_page_eos(&m_og)) eos = true;
301  }
302  }
303  }
304  }
305 
306  return true;
307 }
ogg_stream_state m_os
Definition: VorbisEncoder.h:97
quint64 sample_index_t
Definition: Sample.h:28
Kwave::FileInfo m_info
Definition: VorbisEncoder.h:94
virtual bool eof() const
sample_index_t length() const
Definition: FileInfo.cpp:400
static float sample2float(const sample_t s)
Definition: Sample.h:65
unsigned int tracks() const
Definition: FileInfo.cpp:445
unsigned int toUint(T x)
Definition: Utils.h:109
#define BUFFER_SIZE
qint32 sample_t
Definition: Sample.h:37
vorbis_dsp_state m_vd
Here is the call graph for this function:

◆ encodeProperties()

void Kwave::VorbisEncoder::encodeProperties ( const Kwave::FileInfo info)
private

Encodes all file properties into a vorbis comment

Definition at line 63 of file VorbisEncoder.cpp.

References Kwave::FileInfo::contains(), Kwave::FileInfo::get(), m_comments_map, m_vc, and UTF8.

Referenced by open().

64 {
65  foreach (const QString &key, m_comments_map.keys()) {
66  Kwave::FileProperty property = m_comments_map[key];
67  if (!info.contains(property)) continue; // skip if not present
68 
69  // encode the property as string
70  vorbis_comment_add_tag(&m_vc,
71  UTF8(key),
72  UTF8(info.get(property).toString())
73  );
74  }
75 }
bool contains(const FileProperty property) const
Definition: FileInfo.cpp:354
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
vorbis_comment m_vc
Kwave::VorbisCommentMap m_comments_map
Definition: VorbisEncoder.h:91
FileProperty
Definition: FileInfo.h:45
#define UTF8(qs)
Definition: String.h:48
Here is the call graph for this function:
Here is the caller graph for this function:

◆ open()

bool Kwave::VorbisEncoder::open ( QWidget *  widget,
const Kwave::FileInfo info,
Kwave::MultiTrackReader src 
)
virtual

parse the header of the stream and initialize the decoder

Parameters
widgeta QWidget to be used as parent for error messages
inforeference to a FileInfo to fill
srcMultiTrackReader used as source of the audio data
Returns
true if succeeded, false if failed

Implements Kwave::OggSubEncoder.

Definition at line 78 of file VorbisEncoder.cpp.

References Kwave::FileInfo::contains(), DEFAULT_BITRATE, encodeProperties(), Kwave::FileInfo::get(), Kwave::INF_BITRATE_LOWER, Kwave::INF_BITRATE_NOMINAL, Kwave::INF_BITRATE_UPPER, Kwave::INF_VBR_QUALITY, m_info, m_os, m_vb, m_vc, m_vd, m_vi, Kwave::FileInfo::rate(), Kwave::MessageBox::sorry(), Kwave::toInt(), Kwave::FileInfo::tracks(), and Kwave::MessageBox::warningContinueCancel().

80 {
81  int ret = -1;
82 
83  Q_UNUSED(src);
84 
85  // get info: tracks, sample rate, bitrate(s)
86  m_info = info;
87  const unsigned int tracks = info.tracks();
88  const long int sample_rate = static_cast<const long int>(info.rate());
89 
90  if (tracks > 2) {
92  i18n("This codec supports only mono or stereo files, "
93  "%1 channels are not supported.", tracks));
94  return false;
95  }
96 
97  // ABR bitrates
98  int bitrate_nominal = info.contains(Kwave::INF_BITRATE_NOMINAL) ?
99  QVariant(info.get(Kwave::INF_BITRATE_NOMINAL)).toInt() : -1;
100  int bitrate_lower = info.contains(Kwave::INF_BITRATE_LOWER) ?
101  QVariant(info.get(Kwave::INF_BITRATE_LOWER)).toInt() : -1;
102  int bitrate_upper = info.contains(Kwave::INF_BITRATE_UPPER) ?
103  QVariant(info.get(Kwave::INF_BITRATE_UPPER)).toInt() : -1;
104 
105  // VBR quality
106  int vbr_quality = info.contains(Kwave::INF_VBR_QUALITY) ?
107  QVariant(info.get(Kwave::INF_VBR_QUALITY)).toInt() : -1;
108 
109  qDebug("OggEncoder: ABR=%d...%d...%d Bits/s, VBR=%d%%",
110  bitrate_lower,bitrate_nominal,bitrate_upper,vbr_quality);
111 
112  if ((vbr_quality < 0) && (bitrate_nominal <= 0)) {
113  // no quality and no bitrate given -> complain !
115  i18n("You have not selected any bitrate for the encoding. "
116  "Do you want to continue and encode with %1 kBit/s "
117  "or cancel and choose a different bitrate?",
118  DEFAULT_BITRATE / 1000)) != KMessageBox::Continue)
119  return false; // <- canceled
120 
121  bitrate_nominal = DEFAULT_BITRATE;
122  bitrate_lower = -1;
123  bitrate_upper = -1;
124  }
125 
126  // some checks first
127  Q_ASSERT(tracks < 255);
128  if (tracks > 255) return false;
129 
130  /********** Encode setup ************/
131  vorbis_info_init(&m_vi);
132 
133  if ((bitrate_lower > 0) || (bitrate_upper > 0)) {
134  // Encoding using ABR mode.
135  bitrate_nominal = (bitrate_upper + bitrate_lower) / 2;
136  ret = vorbis_encode_init(&m_vi, tracks, sample_rate,
137  bitrate_upper,
138  bitrate_nominal,
139  bitrate_lower);
140  qDebug("VorbisEncoder: ABR with %d...%d...%d Bits/s",
141  bitrate_lower, bitrate_nominal, bitrate_upper);
142  } else if ((vbr_quality < 0) && (bitrate_nominal > 0)) {
143  // Encoding using constant bitrate in ABR mode
144  ret = vorbis_encode_setup_managed(&m_vi, tracks, sample_rate,
145  -1, bitrate_nominal, -1);
146 
147  // If OV_ECTL_RATEMANAGE2_SET is not defined, then your
148  // libvorbis is just too old.
149  if (!ret) ret =
150  vorbis_encode_ctl(&m_vi, OV_ECTL_RATEMANAGE2_SET, Q_NULLPTR) ||
151  vorbis_encode_setup_init(&m_vi);
152 
153  qDebug("VorbisEncoder: CBR with %d Bits/s", bitrate_nominal);
154  } else if (vbr_quality >= 0) {
155  // Encoding using VBR mode.
156  ret = vorbis_encode_init_vbr(&m_vi, tracks, sample_rate,
157  static_cast<float>(vbr_quality) / 100.0f);
158  qDebug("OggEncoder: VBR with %d%%", vbr_quality);
159  } else {
160  // unknown setup !?
161  qWarning("unknown Ogg/Vorbis setup: VBR quality=%d%%, "
162  "ABR lower=%d, ABR highest=%d, ABR nominal=%d",
163  vbr_quality, bitrate_lower, bitrate_upper,
164  bitrate_nominal);
165  return false;
166  }
167 
168  /* do not continue if setup failed; this can happen if we ask for a
169  mode that libVorbis does not support (eg, too low a bitrate, etc,
170  will return 'OV_EIMPL') */
171  if (ret) {
172  Kwave::MessageBox::sorry(widget, i18n("One or more encoding "
173  "parameters are not supported. Please change the "
174  "settings and try again."));
175  return false;
176  }
177 
178  // add all supported properties as file comments
179  vorbis_comment_init(&m_vc);
180  encodeProperties(info);
181 
182  // set up the analysis state and auxiliary encoding storage
183  vorbis_analysis_init(&m_vd, &m_vi);
184  vorbis_block_init(&m_vd, &m_vb);
185 
186 
187  // set up our packet->stream encoder
188  // pick a random serial number; that way we can more likely build
189  // chained streams just by concatenation
190  qsrand(QTime::currentTime().msec() ^ qrand());
191  ogg_stream_init(&m_os, qrand());
192 
193  return true;
194 }
bool contains(const FileProperty property) const
Definition: FileInfo.cpp:354
double rate() const
Definition: FileInfo.cpp:415
void encodeProperties(const Kwave::FileInfo &info)
#define DEFAULT_BITRATE
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
static int sorry(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:85
ogg_stream_state m_os
Definition: VorbisEncoder.h:97
Kwave::FileInfo m_info
Definition: VorbisEncoder.h:94
int toInt(T x)
Definition: Utils.h:127
vorbis_comment m_vc
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
vorbis_dsp_state m_vd
Here is the call graph for this function:

◆ writeHeader()

bool Kwave::VorbisEncoder::writeHeader ( QIODevice &  dst)
virtual

write the header information

Parameters
dsta QIODevice that receives the raw data
Returns
true if succeeded, false if failed

Implements Kwave::OggSubEncoder.

Definition at line 197 of file VorbisEncoder.cpp.

References m_og, m_os, m_vc, and m_vd.

198 {
199  // Vorbis streams begin with three headers; the initial header (with
200  // most of the codec setup parameters) which is mandated by the Ogg
201  // bitstream spec. The second header holds any comment fields. The
202  // third header holds the bitstream codebook. We merely need to
203  // make the headers, then pass them to libvorbis one at a time;
204  // libvorbis handles the additional Ogg bitstream constraints
205  ogg_packet header;
206  ogg_packet header_comm;
207  ogg_packet header_code;
208 
209  vorbis_analysis_headerout(&m_vd, &m_vc, &header, &header_comm,
210  &header_code);
211  // automatically placed in its own page
212  ogg_stream_packetin(&m_os, &header);
213  ogg_stream_packetin(&m_os, &header_comm);
214  ogg_stream_packetin(&m_os, &header_code);
215 
216  // This ensures the actual audio data will start on a
217  // new page, as per spec
218  while (ogg_stream_flush(&m_os, &m_og)) {
219  dst.write(reinterpret_cast<char *>(m_og.header),
220  m_og.header_len);
221  dst.write(reinterpret_cast<char *>(m_og.body),
222  m_og.body_len);
223  }
224 
225  return true;
226 }
ogg_stream_state m_os
Definition: VorbisEncoder.h:97
vorbis_comment m_vc
vorbis_dsp_state m_vd

Member Data Documentation

◆ m_comments_map

Kwave::VorbisCommentMap Kwave::VorbisEncoder::m_comments_map
private

map for translating Vorbis comments to Kwave FileInfo

Definition at line 91 of file VorbisEncoder.h.

Referenced by encodeProperties().

◆ m_info

Kwave::FileInfo Kwave::VorbisEncoder::m_info
private

file info, set in open(...)

Definition at line 94 of file VorbisEncoder.h.

Referenced by encode(), and open().

◆ m_og

ogg_page Kwave::VorbisEncoder::m_og
private

one Ogg bitstream page. Vorbis packets are inside

Definition at line 100 of file VorbisEncoder.h.

Referenced by encode(), VorbisEncoder(), and writeHeader().

◆ m_op

ogg_packet Kwave::VorbisEncoder::m_op
private

one raw packet of data for decode

Definition at line 103 of file VorbisEncoder.h.

Referenced by encode(), and VorbisEncoder().

◆ m_os

ogg_stream_state Kwave::VorbisEncoder::m_os
private

take physical pages, weld into a logical stream of packets

Definition at line 97 of file VorbisEncoder.h.

Referenced by close(), encode(), open(), VorbisEncoder(), and writeHeader().

◆ m_vb

vorbis_block Kwave::VorbisEncoder::m_vb
private

local working space for packet->PCM decode

Definition at line 115 of file VorbisEncoder.h.

Referenced by close(), encode(), open(), and VorbisEncoder().

◆ m_vc

vorbis_comment Kwave::VorbisEncoder::m_vc
private

struct that stores all the user comments

Definition at line 109 of file VorbisEncoder.h.

Referenced by close(), encodeProperties(), open(), VorbisEncoder(), and writeHeader().

◆ m_vd

vorbis_dsp_state Kwave::VorbisEncoder::m_vd
private

central working state for the packet->PCM decoder

Definition at line 112 of file VorbisEncoder.h.

Referenced by close(), encode(), open(), VorbisEncoder(), and writeHeader().

◆ m_vi

vorbis_info Kwave::VorbisEncoder::m_vi
private

struct that stores all the static vorbis bitstream settings

Definition at line 106 of file VorbisEncoder.h.

Referenced by close(), open(), and VorbisEncoder().


The documentation for this class was generated from the following files: