MythTV  master
flacencoder.cpp
Go to the documentation of this file.
1 // C++
2 #include <cstdlib>
3 #include <iostream>
4 #include <unistd.h>
5 
6 // Qt
7 #include <QString>
8 
9 // MythTV
10 #include <libmyth/mythcontext.h>
13 
14 // MythMusic
15 #include "flacencoder.h"
16 
17 #include <FLAC/stream_encoder.h>
18 #include <FLAC/assert.h>
19 
20 FlacEncoder::FlacEncoder(const QString &outfile, int qualitylevel,
21  MusicMetadata *metadata)
22  : Encoder(outfile, qualitylevel, metadata)
23 {
24  bool streamable_subset = true;
25  bool do_mid_side = true;
26  bool loose_mid_side = false;
27  int bits_per_sample = 16;
28  int sample_rate = 44100;
29  int blocksize = 4608;
30  int max_lpc_order = 8;
31  int qlp_coeff_precision = 0;
32  bool qlp_coeff_prec_search = false;
33  bool do_escape_coding = false;
34  bool do_exhaustive_model_search = false;
35  int min_residual_partition_order = 3;
36  int max_residual_partition_order = 3;
37  int rice_parameter_search_dist = 0;
38 
39  m_encoder = FLAC__stream_encoder_new();
40  FLAC__stream_encoder_set_streamable_subset(m_encoder, streamable_subset);
41  FLAC__stream_encoder_set_do_mid_side_stereo(m_encoder, do_mid_side);
42  FLAC__stream_encoder_set_loose_mid_side_stereo(m_encoder, loose_mid_side);
43  FLAC__stream_encoder_set_channels(m_encoder, NUM_CHANNELS);
44  FLAC__stream_encoder_set_bits_per_sample(m_encoder, bits_per_sample);
45  FLAC__stream_encoder_set_sample_rate(m_encoder, sample_rate);
46  FLAC__stream_encoder_set_blocksize(m_encoder, blocksize);
47  FLAC__stream_encoder_set_max_lpc_order(m_encoder, max_lpc_order);
48  FLAC__stream_encoder_set_qlp_coeff_precision(m_encoder, qlp_coeff_precision);
49  FLAC__stream_encoder_set_do_qlp_coeff_prec_search(m_encoder, qlp_coeff_prec_search);
50  FLAC__stream_encoder_set_do_escape_coding(m_encoder, do_escape_coding);
51  FLAC__stream_encoder_set_do_exhaustive_model_search(m_encoder, do_exhaustive_model_search);
52  FLAC__stream_encoder_set_min_residual_partition_order(m_encoder, min_residual_partition_order);
53  FLAC__stream_encoder_set_max_residual_partition_order(m_encoder, max_residual_partition_order);
54  FLAC__stream_encoder_set_rice_parameter_search_dist(m_encoder, rice_parameter_search_dist);
55 
56  QByteArray ofile = outfile.toLocal8Bit();
57  int ret = FLAC__stream_encoder_init_file(
58  m_encoder, ofile.constData(), nullptr, nullptr);
59  if (ret != FLAC__STREAM_ENCODER_INIT_STATUS_OK)
60  {
61  LOG(VB_GENERAL, LOG_ERR,
62  QString("Error initializing FLAC encoder. Got return code: %1")
63  .arg(ret));
64  }
65 
66  for (auto & chan : m_inputIn)
67  chan.fill(0);
68 
69  for (int i = 0; i < NUM_CHANNELS; i++)
70  m_input[i] = m_inputIn[i].data();
71 }
72 
74 {
75  FlacEncoder::addSamples(nullptr, 0); // flush buffer
76 
77  if (m_encoder)
78  {
79  FLAC__stream_encoder_finish(m_encoder);
80  FLAC__stream_encoder_delete(m_encoder);
81  }
82 
83  if (m_metadata)
85 }
86 
87 int FlacEncoder::addSamples(int16_t *bytes, unsigned int length)
88 {
89  unsigned int index = 0;
90 
91  length /= sizeof(int16_t);
92 
93  do {
94  while (bytes && index < length && m_sampleIndex < MAX_SAMPLES)
95  {
96  m_input[0][m_sampleIndex] = (FLAC__int32)(bytes[index++]);
97  m_input[1][m_sampleIndex] = (FLAC__int32)(bytes[index++]);
98  m_sampleIndex += 1;
99  }
100 
101  if(m_sampleIndex == MAX_SAMPLES || (length == 0 && m_sampleIndex > 0) )
102  {
103  if (!FLAC__stream_encoder_process(m_encoder,
104  (const FLAC__int32 * const *) m_input.data(),
105  m_sampleIndex))
106  {
107  LOG(VB_GENERAL, LOG_ERR,
108  QString("Failed to write flac data. Aborting."));
109  return EENCODEERROR;
110  }
111  m_sampleIndex = 0;
112  }
113  } while (index < length);
114 
115  return 0;
116 }
117 
FlacEncoder::m_input
std::array< FLAC__int32 *, NUM_CHANNELS > m_input
Definition: flacencoder.h:29
FlacEncoder::~FlacEncoder
~FlacEncoder() override
Definition: flacencoder.cpp:73
FlacEncoder::addSamples
int addSamples(int16_t *bytes, unsigned int len) override
Definition: flacencoder.cpp:87
MAX_SAMPLES
static constexpr size_t MAX_SAMPLES
Definition: flacencoder.h:11
flacencoder.h
Encoder
Definition: mythplugins/mythmusic/mythmusic/encoder.h:13
LOG
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
MusicMetadata
Definition: musicmetadata.h:80
metaioflacvorbis.h
EENCODEERROR
#define EENCODEERROR
Definition: mythplugins/mythmusic/mythmusic/encoder.h:7
MetaIOFLACVorbis::write
bool write(const QString &filename, MusicMetadata *mdata) override
Writes all metadata back to a file.
Definition: metaioflacvorbis.cpp:40
FlacEncoder::m_inputIn
std::array< std::array< FLAC__int32, MAX_SAMPLES >, NUM_CHANNELS > m_inputIn
Definition: flacencoder.h:28
NUM_CHANNELS
static constexpr int8_t NUM_CHANNELS
Definition: flacencoder.h:12
FlacEncoder::m_encoder
FLAC__StreamEncoder * m_encoder
Definition: flacencoder.h:25
Encoder::m_metadata
MusicMetadata * m_metadata
Definition: mythplugins/mythmusic/mythmusic/encoder.h:26
musicbrainzngs.compat.bytes
bytes
Definition: compat.py:49
FlacEncoder::FlacEncoder
FlacEncoder(const QString &outfile, int qualitylevel, MusicMetadata *metadata)
Definition: flacencoder.cpp:20
MetaIOFLACVorbis
Read and write Vorbis (Xiph) tags in a FLAC file.
Definition: metaioflacvorbis.h:21
mythcontext.h
Encoder::m_outfile
const QString m_outfile
Definition: mythplugins/mythmusic/mythmusic/encoder.h:23
FlacEncoder::m_sampleIndex
unsigned int m_sampleIndex
Definition: flacencoder.h:26
musicmetadata.h