diff options
author | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-02-24 16:00:54 +0100 |
---|---|---|
committer | Matthias P. Braendli <matthias.braendli@mpb.li> | 2017-02-24 16:00:54 +0100 |
commit | c2863cf4bee6459f1bb72c73bcf83596051cf96d (patch) | |
tree | b336b0894c21d620fbbf95294dddab831ce6b3cd /src/VLCInput.cpp | |
parent | 89715eaa5e02c852e26caaa1854902335cbba794 (diff) | |
download | ODR-AudioEnc-c2863cf4bee6459f1bb72c73bcf83596051cf96d.tar.gz ODR-AudioEnc-c2863cf4bee6459f1bb72c73bcf83596051cf96d.tar.bz2 ODR-AudioEnc-c2863cf4bee6459f1bb72c73bcf83596051cf96d.zip |
Improve VLC samplerate conversion by asking float samples
Asking floats from VLC instead of signed 16-bit samples allows
VLC to use the libsamplerate resampler instead of the ugly_resampler.
Otherwise it might convert to s16l first, and refuse to use
libsamplerate which is unable to work with that data format.
Diffstat (limited to 'src/VLCInput.cpp')
-rw-r--r-- | src/VLCInput.cpp | 46 |
1 files changed, 34 insertions, 12 deletions
diff --git a/src/VLCInput.cpp b/src/VLCInput.cpp index e7dfa21..302877b 100644 --- a/src/VLCInput.cpp +++ b/src/VLCInput.cpp @@ -20,7 +20,7 @@ #include <string> #include <cstring> #include <chrono> -#include <functional> +#include <algorithm> #include "VLCInput.h" @@ -28,6 +28,8 @@ #if HAVE_VLC +const size_t bytes_per_float_sample = sizeof(float); + #include <sys/time.h> int check_vlc_uses_size_t(); @@ -76,7 +78,7 @@ void handleStream_size_t( assert(channels == in->getChannels()); assert(rate == in->getRate()); - assert(bits_per_sample == 8*BYTES_PER_SAMPLE); + assert(bits_per_sample == 8*bytes_per_float_sample); // This assumes VLC always gives back the full // buffer it asked for. According to VLC code @@ -143,11 +145,11 @@ int VLCInput::prepare() // VLC options std::stringstream transcode_options_ss; - transcode_options_ss << "samplerate=" << m_rate; + transcode_options_ss << "acodec=fl32"; + transcode_options_ss << ",samplerate=" << m_rate; if (not m_gain.empty()) { transcode_options_ss << ",afilter=compressor"; } - transcode_options_ss << ",acodec=s16l"; string transcode_options = transcode_options_ss.str(); char smem_options[512]; @@ -250,8 +252,8 @@ void VLCInput::preRender_cb(uint8_t** pp_pcm_buffer, size_t size) std::lock_guard<std::mutex> lock(m_queue_mutex); if (m_queue.size() < max_length) { - m_current_buf.resize(size); - *pp_pcm_buffer = &m_current_buf[0]; + m_current_buf.resize(size / sizeof(float)); + *pp_pcm_buffer = reinterpret_cast<uint8_t*>(&m_current_buf[0]); return; } } @@ -304,12 +306,32 @@ ssize_t VLCInput::m_read(uint8_t* buf, size_t length) { std::lock_guard<std::mutex> lock(m_queue_mutex); - if (m_queue.size() >= length) { - std::copy(m_queue.begin(), m_queue.begin() + length, buf); - - m_queue.erase(m_queue.begin(), m_queue.begin() + length); - - return length; + assert((length % sizeof(int16_t)) == 0); + const size_t num_samples_requested = length / sizeof(int16_t); + + // The queue contains float samples. + // buf has to contain signed 16-bit samples. + if (m_queue.size() >= num_samples_requested) { + int16_t* buffer = reinterpret_cast<int16_t*>(buf); + + for (size_t i = 0; i < num_samples_requested; i++) { + const auto in = m_queue[i]; + if (in <= -1.0f) { + buffer[i] = INT16_MAX; + } + else if (in >= 1.0f) { + buffer[i] = INT16_MIN; + } + else { + buffer[i] = (int16_t)lrintf(in * 32768.0f); + } + } + + m_queue.erase( + m_queue.begin(), + m_queue.begin() + num_samples_requested); + + return num_samples_requested * sizeof(int16_t); } } std::this_thread::sleep_for(std::chrono::milliseconds(1)); |