// Copyright (C) 2000-2005 Open Source Telecom Corporation.
// Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
// Copyright (C) 2015 Cherokees of Idaho.
//
// This file is part of GNU ccAudio2.
//
// GNU ccAudio2 is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// GNU ccAuydio2 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with GNU ccAudio2. If not, see .
#include
#include
#include
#include
namespace ucommon {
AudioResample::AudioResample(Rate div, Rate mul)
{
bool common = true;
while(common) {
common = false;
while(!(mul & 0x01) && !(div & 0x01)) {
mul = (Rate)(mul >> 1);
div = (Rate)(div >> 1);
common = true;
}
while(!(mul % 3) && !(div % 3)) {
mul = (Rate)(mul / 3);
div = (Rate)(div / 3);
common = true;
}
while(!(mul % 5) && !(div %5)) {
mul = (Rate)(mul / 5);
div = (Rate)(div / 5);
common = true;
}
}
mfact = (unsigned)mul;
dfact = (unsigned)div;
max = mfact;
if(dfact > mfact)
max = dfact;
++max;
buffer = new Sample[max];
ppos = gpos = 0;
memset(buffer, 0, max * 2);
last = 0;
}
AudioResample::~AudioResample()
{
delete[] buffer;
}
size_t AudioResample::estimate(size_t count)
{
count *= mfact;
count += (mfact - 1);
return (count / dfact) + 1;
}
size_t AudioResample::process(Linear from, Linear dest, size_t count)
{
size_t saved = 0;
Sample diff, current;
unsigned pos;
unsigned dpos;
while(count--) {
current = *(from++);
diff = (current - last) / mfact;
pos = mfact;
while(pos--) {
last += diff;
buffer[ppos++] = current;
if(ppos >= max)
ppos = 0;
if(gpos < ppos)
dpos = ppos - gpos;
else
dpos = max - (gpos - ppos);
if(dpos >= dfact) {
*(dest++) = buffer[gpos];
++saved;
gpos += dfact;
if(gpos >= max)
gpos = gpos - max;
}
}
last = current;
}
return saved;
}
} // namespace ucommon