mirror of
https://git.jami.net/savoirfairelinux/jami-daemon.git
synced 2025-08-12 22:09:25 +08:00

Rewrites the Resampler class to use MediaFilter. Adds a unit test for the new Resampler. Change-Id: I8ed78d2e1d82df81bbaf46a9719c682c825ee245
101 lines
3.2 KiB
C++
101 lines
3.2 KiB
C++
/*
|
|
* Copyright (C) 2004-2018 Savoir-faire Linux Inc.
|
|
*
|
|
* Author: Emmanuel Milou <emmanuel.milou@savoirfairelinux.com>
|
|
* Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
*/
|
|
|
|
#include "logger.h"
|
|
#include "media_filter.h"
|
|
#include "media_stream.h"
|
|
#include "resampler.h"
|
|
#include "ring_types.h"
|
|
|
|
namespace ring {
|
|
|
|
Resampler::Resampler(AudioFormat format)
|
|
: format_(format)
|
|
{
|
|
setFormat(format);
|
|
}
|
|
|
|
Resampler::Resampler(unsigned sample_rate, unsigned channels)
|
|
: format_(sample_rate, channels)
|
|
{
|
|
setFormat(format_);
|
|
}
|
|
|
|
Resampler::~Resampler() = default;
|
|
|
|
void
|
|
Resampler::reinitFilter(const MediaStream& inputParams)
|
|
{
|
|
filter_.reset(new MediaFilter());
|
|
std::stringstream aformat;
|
|
aformat << "aformat=sample_fmts=s16:channel_layouts="
|
|
<< av_get_default_channel_layout(format_.nb_channels)
|
|
<< ":sample_rates=" << format_.sample_rate;
|
|
if (filter_->initialize(aformat.str(), inputParams) < 0) {
|
|
RING_ERR() << "Failed to initialize resampler";
|
|
filter_.reset();
|
|
}
|
|
}
|
|
|
|
void
|
|
Resampler::setFormat(AudioFormat format)
|
|
{
|
|
format_ = format;
|
|
if (filter_)
|
|
reinitFilter(filter_->getInputParams());
|
|
}
|
|
|
|
void
|
|
Resampler::resample(const AudioBuffer& dataIn, AudioBuffer& dataOut)
|
|
{
|
|
auto input = dataIn.toAVFrame();
|
|
MediaStream currentParams("resampler", static_cast<AVSampleFormat>(input->format),
|
|
0, input->sample_rate, input->channels);
|
|
if (filter_) {
|
|
const auto& ms = filter_->getInputParams();
|
|
if (ms.sampleRate != input->sample_rate || ms.nbChannels != input->channels) {
|
|
RING_WARN() << "Resampler settings changed, reinitializing";
|
|
reinitFilter(currentParams);
|
|
}
|
|
} else {
|
|
reinitFilter(currentParams);
|
|
}
|
|
|
|
auto frame = filter_->apply(input);
|
|
av_frame_free(&input);
|
|
if (!frame) {
|
|
RING_ERR() << "Resampling failed, this may produce a glitch in the audio";
|
|
return;
|
|
}
|
|
|
|
dataOut.setFormat(format_);
|
|
dataOut.resize(frame->nb_samples);
|
|
if (static_cast<AVSampleFormat>(frame->format) == AV_SAMPLE_FMT_FLTP)
|
|
dataOut.convertFloatPlanarToSigned16(frame->extended_data,
|
|
frame->nb_samples, frame->channels);
|
|
else if (static_cast<AVSampleFormat>(frame->format) == AV_SAMPLE_FMT_S16)
|
|
dataOut.deinterleave(reinterpret_cast<const AudioSample*>(frame->extended_data[0]),
|
|
frame->nb_samples, frame->channels);
|
|
av_frame_free(&frame);
|
|
}
|
|
|
|
} // namespace ring
|