aboutsummaryrefslogtreecommitdiffstats
path: root/src/odr-audioenc.cpp
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2017-01-27 11:14:34 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2017-01-27 11:14:34 +0100
commit19d4f31fc08f9d7eda7bb02ba2981b8510391c54 (patch)
treef8586a83309b9abbff50dd717985fd29a608d3bc /src/odr-audioenc.cpp
parent1b2384c5e21490542d93a22928d30ca3cca1ae44 (diff)
downloadODR-AudioEnc-19d4f31fc08f9d7eda7bb02ba2981b8510391c54.tar.gz
ODR-AudioEnc-19d4f31fc08f9d7eda7bb02ba2981b8510391c54.tar.bz2
ODR-AudioEnc-19d4f31fc08f9d7eda7bb02ba2981b8510391c54.zip
Improve drift compensation quality
Diffstat (limited to 'src/odr-audioenc.cpp')
-rw-r--r--src/odr-audioenc.cpp53
1 files changed, 47 insertions, 6 deletions
diff --git a/src/odr-audioenc.cpp b/src/odr-audioenc.cpp
index b009b37..b960633 100644
--- a/src/odr-audioenc.cpp
+++ b/src/odr-audioenc.cpp
@@ -1,6 +1,6 @@
/* ------------------------------------------------------------------
* Copyright (C) 2011 Martin Storsjo
- * Copyright (C) 2016 Matthias P. Braendli
+ * Copyright (C) 2017 Matthias P. Braendli
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -88,7 +88,7 @@ extern "C" {
#include "libtoolame-dab/toolame.h"
}
-
+using vec_u8 = std::vector<uint8_t>;
//! Enumeration of encoders we can use
enum class encoder_selection_t {
@@ -297,10 +297,49 @@ int prepare_aac_encoder(
chrono::steady_clock::time_point timepoint_last_compensation;
+/*! Do drift compensation by distributing the missing samples over
+ * the whole input buffer instead of having a bunch of missing samples
+ * at the end only.
+ *
+ * This expands (in time) the received samples over the whole duration
+ * of the buffer.
+ */
+static void expand_missing_samples(vec_u8& buf, int channels, size_t valid_bytes)
+{
+ const size_t bytes_per_sample = BYTES_PER_SAMPLE * channels;
+ assert(buf.size() % bytes_per_sample == 0);
+ assert(buf.size() > valid_bytes);
+ const size_t valid_samples = valid_bytes / bytes_per_sample;
+ const size_t missing_samples =
+ (buf.size() / bytes_per_sample) - valid_samples;
+
+ // We only fix up to 10% missing samples
+ if (missing_samples * bytes_per_sample > buf.size() / 10) {
+ for (size_t i = valid_samples * bytes_per_sample; i < buf.size(); i++) {
+ buf[i] = 0;
+ }
+ }
+
+ const vec_u8 source_buf(buf);
+ size_t source_ix = 0;
+
+ for (size_t i = 0; i < buf.size() / bytes_per_sample; i++) {
+ for (size_t j = 0; j < bytes_per_sample; j++) {
+ buf.at(bytes_per_sample*i + j) = source_buf.at(source_ix + j);
+ }
+
+ // Do not advance the source index if the sample index is
+ // at the spots where we want to duplicate the source sample
+ if (not (i > 0 and (i % (valid_samples / missing_samples) == 0))) {
+ source_ix += bytes_per_sample;
+ }
+ }
+}
+
/*! Wait the proper amount of time to throttle down to nominal encoding
* rate, if drift compensation is enabled.
*/
-void drift_compensation_delay(int sample_rate, int channels, size_t bytes)
+static void drift_compensation_delay(int sample_rate, int channels, size_t bytes)
{
const size_t bytes_per_second = sample_rate * BYTES_PER_SAMPLE * channels;
@@ -684,7 +723,7 @@ int main(int argc, char *argv[])
}
- std::vector<uint8_t> input_buf;
+ vec_u8 input_buf;
HANDLE_AACENCODER encoder;
@@ -843,8 +882,8 @@ int main(int argc, char *argv[])
#endif
int outbuf_size;
- std::vector<uint8_t> zmqframebuf;
- std::vector<uint8_t> outbuf;
+ vec_u8 zmqframebuf;
+ vec_u8 outbuf;
if (selected_encoder == encoder_selection_t::fdk_dabplus) {
outbuf_size = bitrate/8*120;
outbuf.resize(24*120);
@@ -950,6 +989,7 @@ int main(int argc, char *argv[])
if (drift_compensation) {
size_t overruns;
size_t bytes_from_queue = queue.pop(&input_buf[0], input_buf.size(), &overruns); // returns bytes
+ expand_missing_samples(input_buf, channels, bytes_from_queue);
read_bytes = input_buf.size();
drift_compensation_delay(sample_rate, channels, read_bytes);
@@ -994,6 +1034,7 @@ int main(int argc, char *argv[])
size_t overruns;
size_t bytes_from_queue = queue.pop(&input_buf[0], input_buf.size(), &overruns); // returns bytes
+ expand_missing_samples(input_buf, channels, bytes_from_queue);
read_bytes = input_buf.size();
drift_compensation_delay(sample_rate, channels, read_bytes);