Commit c16beb43 authored by Adrien Béraud's avatar Adrien Béraud Committed by Philippe Gorley

audioframe: implement mix

Change-Id: I8d8d6bd852d76040eb967dda76dcd8c85118e235
Reviewed-by: Philippe Gorley's avatarPhilippe Gorley <philippe.gorley@savoirfairelinux.com>
parent 97786ec0
......@@ -99,9 +99,44 @@ AudioFrame::reserve(size_t nb_samples)
}
void
AudioFrame::mix(const AudioFrame&)
AudioFrame::mix(const AudioFrame& frame)
{
RING_ERR("AudioFrame::mix not implemented yet");
auto& f = *pointer();
auto& fIn = *frame.pointer();
if (f.channels != fIn.channels || f.format != fIn.format || f.sample_rate != fIn.sample_rate) {
throw std::invalid_argument("Can't mix frames with different formats");
}
if (f.nb_samples == 0) {
reserve(fIn.nb_samples);
} else if (f.nb_samples != fIn.nb_samples) {
throw std::invalid_argument("Can't mix frames with different length");
}
AVSampleFormat fmt = (AVSampleFormat)f.format;
bool isPlanar = av_sample_fmt_is_planar(fmt);
unsigned samplesPerChannel = isPlanar ? f.nb_samples : f.nb_samples * f.channels;
unsigned channels = isPlanar ? f.channels : 1;
if (fmt == AV_SAMPLE_FMT_S16 || fmt == AV_SAMPLE_FMT_S16P) {
for (unsigned i=0; i < channels; i++) {
auto c = (int16_t*)f.extended_data[i];
auto cIn = (int16_t*)fIn.extended_data[i];
for (unsigned s=0; s < samplesPerChannel; s++) {
int32_t n = (int32_t)c[s] + (int32_t)cIn[s];
n = std::min<int32_t>(n, std::numeric_limits<int16_t>::max());
n = std::max<int32_t>(n, std::numeric_limits<int16_t>::min());
c[s] = n;
}
}
} else if (fmt == AV_SAMPLE_FMT_FLT || fmt == AV_SAMPLE_FMT_FLTP) {
for (unsigned i=0; i < channels; i++) {
auto c = (float*)f.extended_data[i];
auto cIn = (float*)fIn.extended_data[i];
for (unsigned s=0; s < samplesPerChannel; s++) {
c[s] += cIn[s];
}
}
} else {
throw std::invalid_argument(std::string("Unsupported format for mixing: ") + av_get_sample_fmt_name(fmt));
}
}
VideoFrame::~VideoFrame()
......
......@@ -27,6 +27,7 @@ extern "C" {
#include <libavutil/pixfmt.h>
}
#include "audio/audiobuffer.h"
#include "dring.h"
#include "videomanager_interface.h"
......@@ -43,9 +44,11 @@ public:
private:
void testCopy();
void testMix();
CPPUNIT_TEST_SUITE(MediaFrameTest);
CPPUNIT_TEST(testCopy);
CPPUNIT_TEST(testMix);
CPPUNIT_TEST_SUITE_END();
};
......@@ -84,6 +87,39 @@ MediaFrameTest::testCopy()
CPPUNIT_ASSERT(v2.pointer()->data[0][0] == 42);
}
void
MediaFrameTest::testMix()
{
const AudioFormat& format = AudioFormat::STEREO();
const int nbSamples = format.sample_rate / 50;
auto a1 = std::make_unique<DRing::AudioFrame>(format, nbSamples);
auto d1 = reinterpret_cast<AudioSample*>(a1->pointer()->extended_data[0]);
d1[0] = 0;
d1[1] = 1;
d1[2] = 3;
d1[3] = -2;
d1[4] = 5;
d1[5] = std::numeric_limits<AudioSample>::min();
d1[6] = std::numeric_limits<AudioSample>::max();
auto a2 = std::make_unique<DRing::AudioFrame>(format, nbSamples);
auto d2 = reinterpret_cast<AudioSample*>(a2->pointer()->extended_data[0]);
d2[0] = 0;
d2[1] = 3;
d2[2] = -1;
d2[3] = 3;
d2[4] = -6;
d2[5] = -101;
d2[6] = 101;
a2->mix(*a1);
CPPUNIT_ASSERT(d2[0] == 0);
CPPUNIT_ASSERT(d2[1] == 4);
CPPUNIT_ASSERT(d2[2] == 2);
CPPUNIT_ASSERT(d2[3] == 1);
CPPUNIT_ASSERT(d2[4] == -1);
CPPUNIT_ASSERT(d2[5] == std::numeric_limits<AudioSample>::min());
CPPUNIT_ASSERT(d2[6] == std::numeric_limits<AudioSample>::max());
}
}} // namespace ring::test
RING_TEST_RUNNER(ring::test::MediaFrameTest::name());
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment