From 247750abcbf6760bbc52aa5d64fc375d6fbee8a3 Mon Sep 17 00:00:00 2001 From: Michele Calgaro Date: Sun, 6 Dec 2020 19:28:06 +0900 Subject: Renaming of files in preparation for code style tools. Signed-off-by: Michele Calgaro (cherry picked from commit 00d4f92b717fbcbed6f9eee361975d6ee5380d59) --- flow/resample.cpp | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 305 insertions(+) create mode 100644 flow/resample.cpp (limited to 'flow/resample.cpp') diff --git a/flow/resample.cpp b/flow/resample.cpp new file mode 100644 index 0000000..1c9e408 --- /dev/null +++ b/flow/resample.cpp @@ -0,0 +1,305 @@ + /* + + Copyright (C) 2000 Stefan Westerfeld + stefan@space.twc.de + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Library General Public + License as published by the Free Software Foundation; either + version 2 of the License, or (at your option) any later version. + + This library 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 + Library General Public License for more details. + + You should have received a copy of the GNU Library General Public License + along with this library; see the file COPYING.LIB. If not, write to + the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + Boston, MA 02110-1301, USA. + + */ + +#include "resample.h" +#include "debug.h" +#include +#include +#include + +#define compose_16le(first,second) \ + (((((second)+128)&0xff) << 8)+(first)) + +#define compose_16be(first,second) \ + (((((first)+128)&0xff) << 8)+(second)) + +#define conv_16_float(x) \ + ((float)((x)-32768)/32768.0) + +#define conv_8_float(x) \ + ((float)((x)-128)/128.0) + +using namespace Arts; + +class Arts::ResamplerPrivate { +public: + bool underrun; + Resampler::Endianness endianness; +}; + +const unsigned int Resampler::bufferSize; +const unsigned int Resampler::bufferWrap; + +Resampler::Resampler(Refiller *refiller) : + dropBytes(0), refiller(refiller), pos(0.0), step(1.0), channels(2), + bits(16), + block(0), haveBlock(-1) +{ + d = new ResamplerPrivate(); + d->underrun = false; + d->endianness = littleEndian; + updateSampleSize(); +} + +Resampler::~Resampler() +{ + delete d; +} + +void Resampler::updateSampleSize() +{ + sampleSize = channels * bits / 8; + bufferSamples = bufferSize / sampleSize; +} + +void Resampler::setStep(double newStep) +{ + arts_return_if_fail(newStep > 0); + + step = newStep; +} + +void Resampler::setChannels(int newChannels) +{ + arts_return_if_fail(newChannels == 1 || newChannels == 2); + + channels = newChannels; + updateSampleSize(); +} + +void Resampler::setBits(int newBits) +{ + arts_return_if_fail(newBits == 8 || newBits == 16); + + bits = newBits; + updateSampleSize(); +} + +void Resampler::setEndianness(Endianness newEndianness) +{ + arts_return_if_fail(newEndianness == bigEndian || newEndianness == littleEndian); + + d->endianness = newEndianness; +} + +bool Resampler::underrun() +{ + return d->underrun; +} + +void Resampler::ensureRefill() +{ + if(haveBlock == block) return; + + unsigned long missing; + if(block == 0) + { + missing = bufferSize+sampleSize + - refiller->read(buffer,bufferSize+sampleSize); + + d->underrun = (missing == bufferSize+sampleSize); + } + else + { + /* + * try to drop away "half-sample" reads from the last refill + */ + if(dropBytes > 0) + dropBytes -= refiller->read(buffer,dropBytes); + + /* + * only if this worked there is hope that we can read sane data + */ + if(dropBytes == 0) + { + missing = bufferSize + - refiller->read(&buffer[sampleSize], bufferSize); + + d->underrun = (missing == bufferSize); + } + else + { + missing = bufferSize; + d->underrun = true; + } + } + haveBlock++; + assert(haveBlock == block); + + /* + * If we don't have enough input to fill the block fully, it might be + * that the input stall occurred in the middle of a sample. For instance, + * if samples are 4 bytes long, it might be that we would have needed + * 13 more bytes to do a full refill. + * + * In this situation, there are four samples and one byte missing to + * refill the buffer - the one byte is what we need to care about here: + * on the next read, we'll have one byte too much (if we simply ignore + * the fact, we end up with misaligned reading, causing noise, or + * swapped stereo channels or similar). + * + * So we set dropBytes here, which is a variable which indicates how + * many bytes to drop away upon next refill. + */ + if(missing & (sampleSize - 1)) + dropBytes = missing & (sampleSize - 1); + + unsigned int i = 0, wrap = (block == 0)?0:sampleSize; + if(bits == 16) + { + // wrap the last part of the buffer back to the beginning (history) + while(iendianness == littleEndian) + { + while(i= bufferSamples) \ + { \ + pos -= bufferSamples; \ + block++; \ + ensureRefill(); \ + } + +void Resampler::run(float *left, float *right, unsigned long samples) +{ + ensureRefill(); + unsigned long i = 0; + double delta = step - floor(step); + bool interpolate = fabs(delta) > 0.001; + + if(channels == 2 && interpolate) + { + while(i < samples) + { + double error = pos - floor(pos); + unsigned long offset = 2*(unsigned long)pos; + + left[i] = fbuffer[offset+0]*(1.0-error)+fbuffer[offset+2]*error; + right[i] = fbuffer[offset+1]*(1.0-error)+fbuffer[offset+3]*error; + RESAMPLER_STEP(); + } + } + else if(channels == 1 && interpolate) + { + while(i < samples) + { + double error = pos - floor(pos); + unsigned long offset = (unsigned long)pos; + + left[i] = right[i] = fbuffer[offset]*(1.0-error) + + fbuffer[offset+1]*error; + RESAMPLER_STEP(); + } + } + else if(channels == 2) + { + while(i < samples) + { + unsigned long offset = 2*(unsigned long)pos; + + left[i] = fbuffer[offset+0]; + right[i] = fbuffer[offset+1]; + RESAMPLER_STEP(); + } + } + else if(channels == 1) + { + while(i < samples) + { + unsigned long offset = (unsigned long)pos; + + left[i] = right[i] = fbuffer[offset]; + RESAMPLER_STEP(); + } + } + else + { + assert(false); + } +} + +Refiller::~Refiller() +{ +} + +#undef RESAMPLER_STEP +#undef compose_16le +#undef compose_16be +#undef conv_16_float +#undef conv_8_float -- cgit v1.2.3