kwave  18.07.70
Kwave::FlacEncoder Class Reference

#include <FlacEncoder.h>

Inheritance diagram for Kwave::FlacEncoder:
Inheritance graph
Collaboration diagram for Kwave::FlacEncoder:
Collaboration graph

Classes

class  VorbisCommentContainer
 

Public Member Functions

 FlacEncoder ()
 
virtual ~FlacEncoder () Q_DECL_OVERRIDE
 
virtual Kwave::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)
 

Protected Member Functions

virtual ::FLAC__StreamEncoderWriteStatus write_callback (const FLAC__byte buffer[], size_t bytes, unsigned samples, unsigned current_frame) Q_DECL_OVERRIDE
 
virtual void metadata_callback (const ::FLAC__StreamMetadata *metadata) Q_DECL_OVERRIDE
 
virtual void encodeMetaData (const Kwave::FileInfo &info, QVector< FLAC__StreamMetadata *> &flac_metadata)
 

Private Attributes

Kwave::VorbisCommentMap m_vorbis_comment_map
 
QIODevice * m_dst
 

Detailed Description

Definition at line 43 of file FlacEncoder.h.

Constructor & Destructor Documentation

◆ FlacEncoder()

Kwave::FlacEncoder::FlacEncoder ( )

Constructor

Definition at line 46 of file FlacEncoder.cpp.

References REGISTER_COMPRESSION_TYPES, and REGISTER_MIME_TYPES.

47  :Kwave::Encoder(), FLAC::Encoder::Stream(),
48  m_vorbis_comment_map(), m_dst(Q_NULLPTR)
49 {
52 }
QIODevice * m_dst
Definition: FlacEncoder.h:140
Kwave::VorbisCommentMap m_vorbis_comment_map
Definition: FlacEncoder.h:137
#define REGISTER_MIME_TYPES
#define REGISTER_COMPRESSION_TYPES

◆ ~FlacEncoder()

Kwave::FlacEncoder::~FlacEncoder ( )
virtual

Destructor

Definition at line 55 of file FlacEncoder.cpp.

56 {
57 }

Member Function Documentation

◆ encode()

bool Kwave::FlacEncoder::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 167 of file FlacEncoder.cpp.

References Kwave::FileInfo::bits(), Kwave::StreamObject::blockSize(), Kwave::SampleArray::data(), encodeMetaData(), Kwave::MessageBox::error(), Kwave::MultiTrackReader::isCanceled(), Kwave::FileInfo::length(), m_dst, Kwave::FileInfo::rate(), Kwave::SampleArray::resize(), SAMPLE_BITS, Kwave::SampleArray::size(), Kwave::toUint(), and Kwave::FileInfo::tracks().

171 {
172  bool result = true;
173 
174  qDebug("FlacEncoder::encode()");
175  const Kwave::FileInfo info(meta_data);
176  m_dst = &dst;
177 
178  // get info: tracks, sample rate
179  int tracks = info.tracks();
180  unsigned int bits = info.bits();
181  sample_index_t length = info.length();
182 
183  set_compression_level(5); // @todo make the FLAC compression configurable
184  set_channels(static_cast<unsigned>(tracks));
185  set_bits_per_sample(static_cast<unsigned>(bits));
186  set_sample_rate(static_cast<unsigned>(info.rate()));
187  set_total_samples_estimate(static_cast<FLAC__uint64>(length));
188  set_verify(false); // <- set to "true" for debugging
189 
190  // use mid-side stereo encoding if we have two channels
191  set_do_mid_side_stereo(tracks == 2);
192  set_loose_mid_side_stereo(tracks == 2);
193 
194  // encode meta data, most of them as vorbis comments
195  QVector<FLAC__StreamMetadata *> flac_metadata;
196  encodeMetaData(info, flac_metadata);
197 
198  // convert container to a list of pointers
199  unsigned int meta_count = flac_metadata.size();
200  if (meta_count) {
201  // WARNING: this only stores the pointer, it does not copy!
202  if (!set_metadata(flac_metadata.data(), meta_count)) {
203  qWarning("FlacEncoder: setting meta data failed !?");
204  }
205  }
206 
207  QVector<FLAC__int32 *> flac_buffer;
208  do {
209  // open the output device
210  if (!dst.open(QIODevice::ReadWrite | QIODevice::Truncate)) {
212  i18n("Unable to open the file for saving."));
213  result = false;
214  break;
215  }
216 
217  // initialize the FLAC stream, this already writes some meta info
218  FLAC__StreamEncoderInitStatus init_state = init();
219  if (init_state != FLAC__STREAM_ENCODER_INIT_STATUS_OK) {
220  qWarning("state = %d", static_cast<int>(init_state));
222  i18n("Unable to open the FLAC encoder."));
223  result = false;
224  break;
225  }
226 
227  // allocate output buffers, with FLAC 32 bit format
228  unsigned int len = src.blockSize(); // samples
229  for (int track=0; track < tracks; track++)
230  {
231  FLAC__int32 *buffer =
232  static_cast<FLAC__int32 *>(malloc(sizeof(FLAC__int32) * len));
233  Q_ASSERT(buffer);
234  if (!buffer) break;
235  flac_buffer.append(buffer);
236  }
237 
238  // allocate input buffer, with Kwave's sample_t
239  Kwave::SampleArray in_buffer(len);
240  Q_ASSERT(in_buffer.size() == len);
241  Q_ASSERT(flac_buffer.size() == tracks);
242 
243  if ((in_buffer.size() < len) || (flac_buffer.size() < tracks))
244  {
245  Kwave::MessageBox::error(widget, i18n("Out of memory"));
246  result = false;
247  break;
248  }
249 
250  // calculate divisor for reaching the proper resolution
251  int shift = SAMPLE_BITS - bits;
252  if (shift < 0) shift = 0;
253  FLAC__int32 div = (1 << shift);
254  if (div == 1) div = 0;
255  const FLAC__int32 clip_min = -(1 << bits);
256  const FLAC__int32 clip_max = (1 << bits) - 1;
257 
258  sample_index_t rest = length;
259  while (rest && len && !src.isCanceled() && result) {
260  // limit to rest of signal
261  if (len > rest) len = Kwave::toUint(rest);
262  if (!in_buffer.resize(len)) {
263  Kwave::MessageBox::error(widget, i18n("Out of memory"));
264  result = false;
265  break;
266  }
267 
268  // add all samples to one single buffer
269  for (int track = 0; track < tracks; track++) {
270  Kwave::SampleReader *reader = src[track];
271  Q_ASSERT(reader);
272  if (!reader) break;
273 
274  (*reader) >> in_buffer; // read samples into in_buffer
275  unsigned int l = in_buffer.size();// in_buffer might be empty!
276  if (l < len) {
277  if (!in_buffer.resize(len)) {
278  Kwave::MessageBox::error(widget, i18n("Out of memory"));
279  result = false;
280  break;
281  }
282  while (l < len) in_buffer[l++] = 0;
283  }
284 
285  FLAC__int32 *buf = flac_buffer.at(track);
286  Q_ASSERT(buf);
287  if (!buf) break;
288 
289  const Kwave::SampleArray &in = in_buffer;
290  for (unsigned int in_pos = 0; in_pos < len; in_pos++) {
291  FLAC__int32 s = in[in_pos];
292  if (div) s /= div;
293  if (s > clip_max) s = clip_max;
294  if (s < clip_min) s = clip_min;
295  *buf = s;
296  buf++;
297  }
298  }
299  if (!result) break; // error occurred?
300 
301  // process all collected samples
302  FLAC__int32 **buffer = flac_buffer.data();
303  bool processed = process(buffer, static_cast<unsigned>(len));
304  if (!processed) {
305  result = false;
306  break;
307  }
308 
309  rest -= len;
310  }
311 
312  } while (false);
313 
314  // close the output device and the FLAC stream
315  finish();
316 
317  // clean up all FLAC metadata
318  while (!flac_metadata.isEmpty()) {
319  FLAC__StreamMetadata *m = flac_metadata[0];
320  if (m) FLAC__metadata_object_delete(m);
321  flac_metadata.remove(0);
322  }
323 
324  m_dst = Q_NULLPTR;
325  dst.close();
326 
327  while (!flac_buffer.isEmpty()) {
328  FLAC__int32 *buf = flac_buffer.first();
329  if (buf) free(buf);
330  flac_buffer.remove(0);
331  }
332 
333  return result;
334 }
QIODevice * m_dst
Definition: FlacEncoder.h:140
quint64 sample_index_t
Definition: Sample.h:28
virtual void encodeMetaData(const Kwave::FileInfo &info, QVector< FLAC__StreamMetadata *> &flac_metadata)
static int error(QWidget *widget, QString message, QString caption=QString())
Definition: MessageBox.cpp:126
virtual unsigned int blockSize() const
unsigned int toUint(T x)
Definition: Utils.h:109
sample_t * data()
Definition: SampleArray.h:62
#define SAMPLE_BITS
Definition: Sample.h:43
Here is the call graph for this function:

◆ encodeMetaData()

void Kwave::FlacEncoder::encodeMetaData ( const Kwave::FileInfo info,
QVector< FLAC__StreamMetadata *> &  flac_metadata 
)
protectedvirtual

Encode all Kwave file info into FLAC meta data

Parameters
infoinformation about the file to be saved
flac_metadataQList with collects the FLAC metadata

Definition at line 145 of file FlacEncoder.cpp.

References Kwave::FlacEncoder::VorbisCommentContainer::add(), Kwave::FileInfo::contains(), Kwave::FlacEncoder::VorbisCommentContainer::data(), Kwave::FileInfo::get(), and m_vorbis_comment_map.

Referenced by encode().

147 {
148  // encode all Vorbis comments
149  VorbisCommentMap::ConstIterator it;
150  VorbisCommentContainer vc;
151  for (it = m_vorbis_comment_map.constBegin();
152  it != m_vorbis_comment_map.constEnd();
153  ++it)
154  {
155  if (!info.contains(it.value())) continue; // not present -> skip
156 
157  QString value = info.get(it.value()).toString();
158  vc.add(it.key(), value);
159  }
160  flac_metadata.append(vc.data());
161 
162  // todo: add cue sheet etc here...
163 
164 }
bool contains(const FileProperty property) const
Definition: FileInfo.cpp:354
QVariant get(FileProperty key) const
Definition: FileInfo.cpp:372
Kwave::VorbisCommentMap m_vorbis_comment_map
Definition: FlacEncoder.h:137
Here is the call graph for this function:
Here is the caller graph for this function:

◆ instance()

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

Returns a new instance of the encoder

Implements Kwave::Encoder.

Definition at line 60 of file FlacEncoder.cpp.

61 {
62  return new Kwave::FlacEncoder();
63 }

◆ metadata_callback()

void Kwave::FlacEncoder::metadata_callback ( const ::FLAC__StreamMetadata *  metadata)
protectedvirtual

Callback for encoding meta data

Parameters
metadatapointer to a FLAC metadata structure that will be filled

Definition at line 90 of file FlacEncoder.cpp.

91 {
92  /* we are not interested in the FLAC metadata */
93 }

◆ supportedProperties()

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

Returns a list of supported file properties

Reimplemented from Kwave::Encoder.

Definition at line 66 of file FlacEncoder.cpp.

References m_vorbis_comment_map.

67 {
68  return m_vorbis_comment_map.values();
69 }
Kwave::VorbisCommentMap m_vorbis_comment_map
Definition: FlacEncoder.h:137

◆ write_callback()

FLAC__StreamEncoderWriteStatus Kwave::FlacEncoder::write_callback ( const FLAC__byte  buffer[],
size_t  bytes,
unsigned  samples,
unsigned  current_frame 
)
protected

Callback for writing data to the FLAC layer

Parameters
bufferarray with samples
byteslength of the buffer in bytes
samplesthe number of samples
current_frameindex of the current frame
Returns
FLAC stream encoder write status

Definition at line 72 of file FlacEncoder.cpp.

References m_dst.

75 {
76  Q_ASSERT(m_dst);
77  if (!m_dst) return FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
78 
79  qint64 written = m_dst->write(
80  reinterpret_cast<const char *>(&(buffer[0])),
81  static_cast<qint64>(bytes)
82  );
83 
84  return (written == static_cast<qint64>(bytes)) ?
85  FLAC__STREAM_ENCODER_WRITE_STATUS_OK :
86  FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
87 }
QIODevice * m_dst
Definition: FlacEncoder.h:140

Member Data Documentation

◆ m_dst

QIODevice* Kwave::FlacEncoder::m_dst
private

pointer to the QIODevice for storing, used while encoding

Definition at line 140 of file FlacEncoder.h.

Referenced by encode(), and write_callback().

◆ m_vorbis_comment_map

Kwave::VorbisCommentMap Kwave::FlacEncoder::m_vorbis_comment_map
private

map for translating vorbis comments to FileInfo properties

Definition at line 137 of file FlacEncoder.h.

Referenced by encodeMetaData(), and supportedProperties().


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