kwave  18.07.70
Kwave::WavEncoder Class Reference

#include <WavEncoder.h>

Inheritance diagram for Kwave::WavEncoder:
Inheritance graph
Collaboration diagram for Kwave::WavEncoder:
Collaboration graph

Public Member Functions

 WavEncoder ()
 
virtual ~WavEncoder () Q_DECL_OVERRIDE
 
virtual Encoderinstance () Q_DECL_OVERRIDE
 
virtual bool encode (QWidget *widget, Kwave::MultiTrackReader &src, QIODevice &dst, const Kwave::MetaDataList &meta_data) Q_DECL_OVERRIDE
 
virtual QList< Kwave::FilePropertysupportedProperties () Q_DECL_OVERRIDE
 
- Public Member Functions inherited from Kwave::Encoder
 Encoder ()
 
virtual ~Encoder ()
 
virtual QList< Kwave::FilePropertyunsupportedProperties (const QList< Kwave::FileProperty > &properties_to_check)
 
- Public Member Functions inherited from Kwave::CodecBase
 CodecBase ()
 
virtual ~CodecBase ()
 
virtual bool supports (const QMimeType &mimetype)
 
virtual bool supports (const QString &mimetype_name)
 
virtual QStringList extensions (const QString &mimetype_name) const
 
virtual const QList< CodecBase::MimeTypemimeTypes ()
 
virtual const QList< Kwave::Compression::TypecompressionTypes ()
 
virtual void addMimeType (const char *name, const QString &description, const char *patterns)
 
virtual void addCompression (Kwave::Compression::Type compression)
 
virtual QString mimeTypeOf (const QUrl &url)
 

Private Member Functions

void writeInfoChunk (QIODevice &dst, Kwave::FileInfo &info)
 
void writeLabels (QIODevice &dst, const Kwave::LabelList &labels)
 
void fixAudiofileBrokenHeaderBug (QIODevice &dst, Kwave::FileInfo &info, unsigned int frame_size)
 

Private Attributes

Kwave::WavPropertyMap m_property_map
 

Detailed Description

Definition at line 37 of file WavEncoder.h.

Constructor & Destructor Documentation

◆ WavEncoder()

Kwave::WavEncoder::WavEncoder ( )

Constructor

Definition at line 44 of file WavEncoder.cpp.

References REGISTER_COMPRESSION_TYPES, and REGISTER_MIME_TYPES.

46 {
49 }
Kwave::WavPropertyMap m_property_map
Definition: WavEncoder.h:101
#define REGISTER_MIME_TYPES
#define REGISTER_COMPRESSION_TYPES

◆ ~WavEncoder()

Kwave::WavEncoder::~WavEncoder ( )
virtual

Destructor

Definition at line 52 of file WavEncoder.cpp.

53 {
54 }

Member Function Documentation

◆ encode()

bool Kwave::WavEncoder::encode ( QWidget *  widget,
Kwave::MultiTrackReader src,
QIODevice &  dst,
const Kwave::MetaDataList meta_data 
)
virtual

Encodes a signal into a stream of bytes.

Parameters
widgeta widget that can be used for displaying message boxes or dialogs
srcMultiTrackReader used as source of the audio data
dstfile or other source to receive a stream of bytes
meta_datameta data of the file to save
Returns
true if succeeded, false on errors

Implements Kwave::Encoder.

Definition at line 307 of file WavEncoder.cpp.

References Kwave::SampleFormat::assign(), Kwave::FileInfo::bits(), Kwave::VirtualAudioFile::close(), Kwave::FileInfo::contains(), Kwave::SampleFormat::Double, Kwave::SampleReader::eof(), Kwave::MessageBox::error(), fixAudiofileBrokenHeaderBug(), Kwave::SampleFormat::Float, Kwave::SampleFormat::fromInt(), Kwave::Compression::fromInt(), Kwave::Compression::G711_ALAW, Kwave::Compression::G711_ULAW, Kwave::FileInfo::get(), Kwave::VirtualAudioFile::handle(), Kwave::INF_COMPRESSION, Kwave::INF_SAMPLE_FORMAT, Kwave::MultiTrackReader::isCanceled(), Kwave::VirtualAudioFile::lastError(), Kwave::FileInfo::length(), Kwave::Compression::NONE, Kwave::VirtualAudioFile::open(), Kwave::FileInfo::rate(), SAMPLE_BITS, SAMPLE_STORAGE_BITS, Kwave::FileInfo::set(), Kwave::FileInfo::setBits(), Kwave::SampleFormat::Signed, Kwave::Compression::toAudiofile(), Kwave::SampleFormat::toInt(), Kwave::toInt(), Kwave::toUint(), Kwave::MultiTrackSource< SOURCE, INITIALIZE >::tracks(), Kwave::FileInfo::tracks(), Kwave::SampleFormat::Unsigned, Kwave::MessageBox::warningYesNoCancel(), writeInfoChunk(), and writeLabels().

310 {
311  Kwave::FileInfo info(meta_data);
312 
313  /* first get and check some header information */
314  const unsigned int tracks = info.tracks();
315  const sample_index_t length = info.length();
316  unsigned int bits = info.bits();
317  const double rate = info.rate();
318 
320  if (info.contains(Kwave::INF_SAMPLE_FORMAT))
321  format.fromInt(info.get(Kwave::INF_SAMPLE_FORMAT).toInt());
322 
323  Kwave::Compression::Type compression =
324  info.contains(Kwave::INF_COMPRESSION) ?
327 
328  // use default bit resolution if missing
329  Q_ASSERT(bits);
330  if (!bits) bits = 16;
331 
332  // check for a valid source
333  if ((!tracks) || (!length)) return false;
334  Q_ASSERT(src.tracks() == tracks);
335  if (src.tracks() != tracks) return false;
336 
337  // check if the chosen compression mode is supported for saving
338  if ((compression != Kwave::Compression::NONE) &&
339  (compression != Kwave::Compression::G711_ULAW) &&
340  (compression != Kwave::Compression::G711_ALAW))
341  {
342  qWarning("compression mode %d not supported!",
343  Kwave::Compression(compression).toInt());
344  int what_now = Kwave::MessageBox::warningYesNoCancel(widget,
345  i18n("Sorry, the currently selected compression type cannot "
346  "be used for saving. Do you want to use "
347  "G711 ULAW compression instead?"), QString(),
348  i18n("&Yes, use G711"),
349  i18n("&No, store uncompressed")
350  );
351  switch (what_now) {
352  case (KMessageBox::Yes):
353  info.set(Kwave::INF_COMPRESSION,
355  compression = Kwave::Compression::G711_ULAW;
356  break;
357  case (KMessageBox::No):
358  info.set(Kwave::INF_COMPRESSION,
360  compression = Kwave::Compression::NONE;
361  break;
362  default:
363  return false; // bye bye, save later...
364  }
365  }
366 
367  // check for unsupported compression/bits/sample format combinations
368  // G.711 and MSADPCM support only 16 bit signed as input format!
369  if ((compression == Kwave::Compression::G711_ULAW) ||
370  (compression == Kwave::Compression::G711_ALAW))
371  {
372  if ((format != Kwave::SampleFormat::Signed) || (bits != 16)) {
373  format.assign(Kwave::SampleFormat::Signed);
374  bits = 16;
375  info.set(Kwave::INF_SAMPLE_FORMAT, QVariant(format.toInt()));
376  info.setBits(16);
377  qDebug("auto-switching to 16 bit signed format");
378  }
379  } else if ((bits <= 8) && (format != Kwave::SampleFormat::Unsigned)) {
380  format.assign(Kwave::SampleFormat::Unsigned);
381  info.set(Kwave::INF_SAMPLE_FORMAT, QVariant(format.toInt()));
382  qDebug("auto-switching to unsigned format");
383  } else if ((bits > 8) && (format != Kwave::SampleFormat::Signed)) {
384  format.assign(Kwave::SampleFormat::Signed);
385  info.set(Kwave::INF_SAMPLE_FORMAT, QVariant(format.toInt()));
386  qDebug("auto-switching to signed format");
387  }
388 
389  // open the output device
390  if (!dst.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
392  i18n("Unable to open the file for saving!"));
393  return false;
394  }
395 
396  // check for proper size: WAV supports only 32bit addressing
397  if (length * ((bits + 7) / 8) >= UINT_MAX) {
398  Kwave::MessageBox::error(widget, i18n("File or selection too large"));
399  return false;
400  }
401 
402  int af_sample_format = AF_SAMPFMT_TWOSCOMP;
403  Kwave::SampleFormat fmt(format);
404  switch (fmt)
405  {
407  af_sample_format = AF_SAMPFMT_UNSIGNED;
408  break;
410  af_sample_format = AF_SAMPFMT_FLOAT;
411  break;
413  af_sample_format = AF_SAMPFMT_DOUBLE;
414  break;
415  case Kwave::SampleFormat::Signed: /* FALLTHROUGH */
416  default:
417  af_sample_format = AF_SAMPFMT_TWOSCOMP;
418  break;
419  }
420 
421  AFfilesetup setup;
422  setup = afNewFileSetup();
423  afInitFileFormat(setup, AF_FILE_WAVE);
424  afInitChannels(setup, AF_DEFAULT_TRACK, tracks);
425  afInitSampleFormat(setup, AF_DEFAULT_TRACK, af_sample_format, bits);
426  afInitCompression(setup, AF_DEFAULT_TRACK,
427  Kwave::Compression::toAudiofile(compression));
428  afInitRate(setup, AF_DEFAULT_TRACK, rate);
429 
430  Kwave::VirtualAudioFile outfile(dst);
431  outfile.open(&outfile, setup);
432 
433  AFfilehandle fh = outfile.handle();
434  if (!fh || (outfile.lastError() >= 0)) {
435  QString reason;
436 
437  switch (outfile.lastError()) {
438  case AF_BAD_NOT_IMPLEMENTED:
439  reason = i18n("Format or function is not implemented") /*+
440  "\n("+format_name+")"*/;
441  break;
442  case AF_BAD_MALLOC:
443  reason = i18n("Out of memory");
444  break;
445  case AF_BAD_HEADER:
446  reason = i18n("File header is damaged");
447  break;
448  case AF_BAD_CODEC_TYPE:
449  reason = i18n("Invalid codec type")/* +
450  "\n("+format_name+")"*/;
451  break;
452  case AF_BAD_OPEN:
453  reason = i18n("Opening the file failed");
454  break;
455  case AF_BAD_READ:
456  reason = i18n("Read access failed");
457  break;
458  case AF_BAD_SAMPFMT:
459  reason = i18n("Invalid sample format");
460  break;
461  default:
462  reason = reason.number(outfile.lastError());
463  }
464 
465  QString text= i18n("An error occurred while opening the "\
466  "file:\n'%1'", reason);
467  Kwave::MessageBox::error(widget, text);
468 
469  return false;
470  }
471 
472  // set up libaudiofile to produce Kwave's internal sample format
473 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
474  afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_BIGENDIAN);
475 #else
476  afSetVirtualByteOrder(fh, AF_DEFAULT_TRACK, AF_BYTEORDER_LITTLEENDIAN);
477 #endif
478  afSetVirtualSampleFormat(fh, AF_DEFAULT_TRACK,
479  AF_SAMPFMT_TWOSCOMP, SAMPLE_STORAGE_BITS);
480 
481  // allocate a buffer for input data
482  const unsigned int virtual_frame_size = Kwave::toUint(
483  afGetVirtualFrameSize(fh, AF_DEFAULT_TRACK, 1));
484  const unsigned int buffer_frames = (8 * 1024);
485  sample_storage_t *buffer = static_cast<sample_storage_t *>(
486  malloc(buffer_frames * virtual_frame_size));
487  if (!buffer) return false;
488 
489  // read in from the sample readers
490  sample_index_t rest = length;
491  while (rest) {
492  // merge the tracks into the sample buffer
493  sample_storage_t *p = buffer;
494  unsigned int count = buffer_frames;
495  if (rest < count) count = Kwave::toUint(rest);
496 
497  for (unsigned int pos = 0; pos < count; pos++) {
498  for (unsigned int track = 0; track < tracks; track++) {
499  Kwave::SampleReader *stream = src[track];
500  sample_t sample = 0;
501  if (!stream->eof()) (*stream) >> sample;
502 
503  // the following cast is only necessary if
504  // sample_t is not equal to sample_storage_t
505  sample_storage_t act = static_cast<sample_storage_t>(sample);
506  act *= (1 << (SAMPLE_STORAGE_BITS - SAMPLE_BITS));
507  *p = act;
508  p++;
509  }
510  }
511 
512  // write out through libaudiofile
513  count = afWriteFrames(fh, AF_DEFAULT_TRACK, buffer, count);
514 
515  // break if eof reached or disk full
516  Q_ASSERT(count);
517  if (!count) break;
518 
519  Q_ASSERT(rest >= count);
520  rest -= count;
521 
522  // abort if the user pressed cancel
523  // --> this would leave a corrupted file !!!
524  if (src.isCanceled()) break;
525  }
526 
527  // close the audiofile stuff, we need control over the
528  // fixed-up file on our own
529  outfile.close();
530 
531  // clean up the sample buffer
532  free(buffer);
533  afFreeFileSetup(setup);
534 
535  // due to a buggy implementation of libaudiofile
536  // we have to fix up the length of the "data" and the "RIFF" chunk
537  fixAudiofileBrokenHeaderBug(dst, info, (bits * tracks) >> 3);
538 
539  // put the properties into the INFO chunk
540  writeInfoChunk(dst, info);
541 
542  // write the labels list
543  writeLabels(dst, Kwave::LabelList(meta_data));
544 
545  return true;
546 }
void writeLabels(QIODevice &dst, const Kwave::LabelList &labels)
Definition: WavEncoder.cpp:185
virtual unsigned int tracks() const Q_DECL_OVERRIDE
void fixAudiofileBrokenHeaderBug(QIODevice &dst, Kwave::FileInfo &info, unsigned int frame_size)
Definition: WavEncoder.cpp:69
static Kwave::Compression::Type fromInt(int i)
Definition: Compression.cpp:78
quint64 sample_index_t
Definition: Sample.h:28
bool eof() const
Definition: SampleReader.h:66
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
int toInt(T x)
Definition: Utils.h:127
void writeInfoChunk(QIODevice &dst, Kwave::FileInfo &info)
Definition: WavEncoder.cpp:120
qint32 sample_storage_t
Definition: Sample.h:40
static int warningYesNoCancel(QWidget *widget, QString message, QString caption=QString(), const QString buttonYes=QString(), const QString buttonNo=QString(), const QString &dontAskAgainName=QString())
Definition: MessageBox.cpp:104
static int toAudiofile(Kwave::Compression::Type compression)
#define SAMPLE_STORAGE_BITS
Definition: Sample.h:46
unsigned int toUint(T x)
Definition: Utils.h:109
#define SAMPLE_BITS
Definition: Sample.h:43
qint32 sample_t
Definition: Sample.h:37
Here is the call graph for this function:

◆ fixAudiofileBrokenHeaderBug()

void Kwave::WavEncoder::fixAudiofileBrokenHeaderBug ( QIODevice &  dst,
Kwave::FileInfo info,
unsigned int  frame_size 
)
private

Fix the size of the "data" and the "RIFF" chunk, as libaudiofile is sometimes really buggy due to internal calculations done with "float" as data type. This can lead to broken files as the data and also the RIFF chunk sizes are too small.

Parameters
dstfile or other source to receive a stream of bytes
infoinformation about the file to be saved
frame_sizenumber of bytes per sample

Definition at line 69 of file WavEncoder.cpp.

References Kwave::FileInfo::contains(), Kwave::FileInfo::get(), Kwave::INF_COMPRESSION, Kwave::FileInfo::length(), Kwave::Compression::NONE, and Kwave::toUint().

Referenced by encode().

72 {
73  const unsigned int length = Kwave::toUint(info.length());
74  quint32 correct_size = length * frame_size;
75  const int compression = info.contains(Kwave::INF_COMPRESSION) ?
76  info.get(Kwave::INF_COMPRESSION).toInt() :
78  if (compression != Kwave::Compression::NONE) {
79  qWarning("WARNING: libaudiofile might have produced a broken header!");
80  return;
81  }
82 
83  // just to be sure: at offset 36 we expect the chunk name "data"
84  dst.seek(36);
85  char chunk_name[5];
86  memset(chunk_name, 0x00, sizeof(chunk_name));
87  dst.read(&chunk_name[0], 4);
88  if (strncmp("data", chunk_name, sizeof(chunk_name))) {
89  qWarning("WARNING: unexpected wav header format, check disabled");
90  return;
91  }
92 
93  // read the data chunk size that libaudiofile has written
94  quint32 data_size;
95  dst.seek(40);
96  dst.read(reinterpret_cast<char *>(&data_size), 4);
97  data_size = qFromLittleEndian<quint32>(data_size);
98  if (data_size == length * frame_size) {
99 // qDebug("(data size written by libaudiofile is correct)");
100  return;
101  }
102 
103  qWarning("WARNING: libaudiofile wrote a wrong 'data' chunk size!");
104  qWarning(" current=%u, correct=%u", data_size, correct_size);
105 
106  // write the fixed size of the "data" chunk
107  dst.seek(40);
108  data_size = qToLittleEndian<quint32>(correct_size);
109  dst.write(reinterpret_cast<char *>(&data_size), 4);
110 
111  // also fix the "RIFF" size
112  dst.seek(4);
113  quint32 riff_size = static_cast<quint32>(dst.size()) - 4 - 4;
114  riff_size = qToLittleEndian<quint32>(riff_size);
115  dst.write(reinterpret_cast<char *>(&riff_size), 4);
116 
117 }
bool contains(const FileProperty property) const
Definition: FileInfo.cpp:354
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
sample_index_t length() const
Definition: FileInfo.cpp:400
unsigned int toUint(T x)
Definition: Utils.h:109
Here is the call graph for this function:
Here is the caller graph for this function:

◆ instance()

Kwave::Encoder * Kwave::WavEncoder::instance ( )
virtual

Returns a new instance of the encoder

Implements Kwave::Encoder.

Definition at line 57 of file WavEncoder.cpp.

58 {
59  return new Kwave::WavEncoder();
60 }

◆ supportedProperties()

QList< Kwave::FileProperty > Kwave::WavEncoder::supportedProperties ( )
virtual

Returns a list of supported file properties

Reimplemented from Kwave::Encoder.

Definition at line 63 of file WavEncoder.cpp.

References m_property_map, and Kwave::WavPropertyMap::properties().

64 {
65  return m_property_map.properties();
66 }
Kwave::WavPropertyMap m_property_map
Definition: WavEncoder.h:101
QList< Kwave::FileProperty > properties() const
Here is the call graph for this function:

◆ writeInfoChunk()

void Kwave::WavEncoder::writeInfoChunk ( QIODevice &  dst,
Kwave::FileInfo info 
)
private

write the INFO chunk with all known file properties

Parameters
dstfile or other source to receive a stream of bytes
infoinformation about the file to be saved

Definition at line 120 of file WavEncoder.cpp.

References Kwave::WavPropertyMap::containsProperty(), Kwave::WavPropertyMap::findProperty(), m_property_map, name, Kwave::FileInfo::properties(), and zero().

Referenced by encode().

121 {
122  // create a list of chunk names and properties for the INFO chunk
123  QMap<Kwave::FileProperty, QVariant> properties(info.properties());
124  QMap<QByteArray, QByteArray> info_chunks;
125  unsigned int info_size = 0;
126 
127  for (QMap<Kwave::FileProperty, QVariant>::Iterator it = properties.begin();
128  it != properties.end(); ++it)
129  {
130  Kwave::FileProperty property = it.key();
131  if (!m_property_map.containsProperty(property)) continue;
132 
133  QByteArray chunk_id = m_property_map.findProperty(property);
134  if (info_chunks.contains(chunk_id)) continue; // already encoded
135 
136  QByteArray value = QVariant(properties[property]).toString().toUtf8();
137  info_chunks.insert(chunk_id, value);
138  info_size += 4 + 4 + value.length();
139  if (value.length() & 0x01) info_size++;
140  }
141 
142  // if there are properties to save, create a LIST chunk
143  if (!info_chunks.isEmpty()) {
144  quint32 size;
145 
146  // enlarge the main RIFF chunk by the size of the LIST chunk
147  info_size += 4 + 4 + 4; // add the size of LIST(INFO)
148  dst.seek(4);
149  dst.read(reinterpret_cast<char *>(&size), 4);
150  size = qToLittleEndian<quint32>(
151  qFromLittleEndian<quint32>(size) + info_size);
152  dst.seek(4);
153  dst.write(reinterpret_cast<char *>(&size), 4);
154 
155  // add the LIST(INFO) chunk itself
156  dst.seek(dst.size());
157  if (dst.pos() & 1) dst.write("\000", 1); // padding
158  dst.write("LIST", 4);
159  size = qToLittleEndian<quint32>(info_size - 8);
160  dst.write(reinterpret_cast<char *>(&size), 4);
161  dst.write("INFO", 4);
162 
163  // append the chunks to the end of the file
164  for (QMap<QByteArray, QByteArray>::Iterator it = info_chunks.begin();
165  it != info_chunks.end(); ++it)
166  {
167  QByteArray name = it.key();
168  QByteArray value = it.value();
169 
170  dst.write(name.data(), 4); // chunk name
171  size = value.length(); // length of the chunk
172  if (size & 0x01) size++;
173  size = qToLittleEndian<quint32>(size);
174  dst.write(reinterpret_cast<char *>(&size), 4);
175  dst.write(value.data(), value.length());
176  if (value.length() & 0x01) {
177  const char zero = 0;
178  dst.write(&zero, 1);
179  }
180  }
181  }
182 }
QByteArray findProperty(const Kwave::FileProperty property) const
Kwave::WavPropertyMap m_property_map
Definition: WavEncoder.h:101
bool containsProperty(const Kwave::FileProperty property) const
const char name[16]
Definition: memcpy.c:510
const QMap< FileProperty, QVariant > properties() const
Definition: FileInfo.cpp:389
FileProperty
Definition: FileInfo.h:45
static double zero(double)
Definition: Functions.cpp:83
Here is the call graph for this function:
Here is the caller graph for this function:

◆ writeLabels()

void Kwave::WavEncoder::writeLabels ( QIODevice &  dst,
const Kwave::LabelList labels 
)
private

write the 'cue list' and the label names (if any)

Parameters
dstfile or other source to receive a stream of bytes
labelsa list of labels

Definition at line 185 of file WavEncoder.cpp.

References Kwave::MetaData::isNull(), Kwave::Label::name(), name, Kwave::Label::pos(), and Kwave::toUint().

Referenced by encode().

187 {
188  const unsigned int labels_count = labels.count();
189  quint32 size, additional_size = 0, index, data;
190 
191  // shortcut: nothing to do if no labels present
192  if (!labels_count) return;
193 
194  // easy things first: size of the cue list (has fixed record size)
195  // without chunk name and chunk size
196  const unsigned int size_of_cue_list =
197  4 + /* number of entries */
198  labels_count * (6 * 4); /* cue list entry: 6 x 32 bit */
199 
200  // now the size of the labels
201  unsigned int size_of_labels = 0;
202  foreach (const Kwave::Label &label, labels) {
203  if (label.isNull()) continue;
204  unsigned int name_len = label.name().toUtf8().size();
205  if (!name_len) continue; // skip zero-length names
206  size_of_labels += (3 * 4); // 3 * 4 byte
207  size_of_labels += name_len;
208  // padding if size is unaligned
209  if (size_of_labels & 1) size_of_labels++;
210  }
211  if (size_of_labels) {
212  size_of_labels += 4; /* header entry: 'adtl' */
213  // enlarge the main RIFF chunk by the size of the LIST chunk
214  additional_size += 4 + 4 + size_of_labels; // add size of LIST(adtl)
215  }
216 
217  // enlarge the main RIFF chunk by the size of the cue chunks
218  additional_size += 4 + 4 + size_of_cue_list; // add size of 'cue '
219 
220  dst.seek(4);
221  dst.read(reinterpret_cast<char *>(&size), 4);
222  size = qToLittleEndian<quint32>(
223  qFromLittleEndian<quint32>(size) + additional_size);
224  dst.seek(4);
225  dst.write(reinterpret_cast<char *>(&size), 4);
226 
227  // seek to the end of the file
228  dst.seek(dst.size());
229  if (dst.pos() & 1) dst.write("\000", 1); // padding
230 
231  // add the 'cue ' list
232  dst.write("cue ", 4);
233  size = qToLittleEndian<quint32>(size_of_cue_list);
234  dst.write(reinterpret_cast<char *>(&size), 4);
235 
236  // number of entries
237  size = qToLittleEndian<quint32>(labels_count);
238  dst.write(reinterpret_cast<char *>(&size), 4);
239 
240  index = 0;
241  foreach (const Kwave::Label &label, labels) {
242  if (label.isNull()) continue;
243  /*
244  * typedef struct {
245  * quint32 dwIdentifier; <- index
246  * quint32 dwPosition; <- 0
247  * quint32 fccChunk; <- 'data'
248  * quint32 dwChunkStart; <- 0
249  * quint32 dwBlockStart; <- 0
250  * quint32 dwSampleOffset; <- label.pos()
251  * } cue_list_entry_t;
252  */
253  data = qToLittleEndian<quint32>(index);
254  dst.write(reinterpret_cast<char *>(&data), 4); // dwIdentifier
255  data = 0;
256  dst.write(reinterpret_cast<char *>(&data), 4); // dwPosition
257  dst.write("data", 4); // fccChunk
258  dst.write(reinterpret_cast<char *>(&data), 4); // dwChunkStart
259  dst.write(reinterpret_cast<char *>(&data), 4); // dwBlockStart
260  data = qToLittleEndian<quint32>(Kwave::toUint(label.pos()));
261  dst.write(reinterpret_cast<char *>(&data), 4); // dwSampleOffset
262  index++;
263  }
264 
265  // add the LIST(adtl) chunk
266  if (size_of_labels) {
267  dst.write("LIST", 4);
268  size = qToLittleEndian<quint32>(size_of_labels);
269  dst.write(reinterpret_cast<char *>(&size), 4);
270  dst.write("adtl", 4);
271  index = 0;
272  foreach (const Kwave::Label &label, labels) {
273  if (label.isNull()) continue;
274  QByteArray name = label.name().toUtf8();
275 
276  /*
277  * typedef struct {
278  * quint32 dwChunkID; <- 'labl'
279  * quint32 dwChunkSize; (without padding !)
280  * quint32 dwIdentifier; <- index
281  * char dwText[]; <- label->name()
282  * } label_list_entry_t;
283  */
284  if (name.size()) {
285  dst.write("labl", 4); // dwChunkID
286  data = qToLittleEndian<quint32>(name.size() + 4);
287 
288  // dwChunkSize
289  dst.write(reinterpret_cast<char *>(&data), 4);
290  data = qToLittleEndian<quint32>(index);
291 
292  // dwIdentifier
293  dst.write(reinterpret_cast<char *>(&data), 4);
294  dst.write(name.data(), name.size()); // dwText
295  if (name.size() & 1) {
296  // padding if necessary
297  data = 0;
298  dst.write(reinterpret_cast<char *>(&data), 1);
299  }
300  }
301  index++;
302  }
303  }
304 }
virtual sample_index_t pos() const
Definition: Label.cpp:56
const char name[16]
Definition: memcpy.c:510
virtual bool isNull() const
Definition: MetaData.cpp:69
virtual QString name() const
Definition: Label.cpp:74
unsigned int toUint(T x)
Definition: Utils.h:109
Here is the call graph for this function:
Here is the caller graph for this function:

Member Data Documentation

◆ m_property_map

Kwave::WavPropertyMap Kwave::WavEncoder::m_property_map
private

map for translating chunk names to FileInfo properties

Definition at line 101 of file WavEncoder.h.

Referenced by supportedProperties(), and writeInfoChunk().


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