/* * Copyright 2010-2014 Haiku, inc. * Distributed under the terms of the MIT Licence. * * Author: Adrien Destugues */ #include "Interpolate.h" #include #include #include "MixerDebug.h" /*! Resampling class doing linear interpolation. */ template static void kernel(Resampler* object, const void *_src, int32 srcSampleOffset, int32 srcSampleCount, void *_dest, int32 destSampleOffset, int32 destSampleCount, float _gain) { const char * src = (const char *)_src; char * dest = (char *)_dest; int32 count = destSampleCount; float gain = _gain * gnum / gden; if (srcSampleCount == destSampleCount) { // optimized case for no resampling while (count--) { float tmp = ((*(const inType*)src) - inMiddle) * gain + outMiddle; if (tmp <= min) *(outType *)dest = min; else if (tmp >= max) *(outType *)dest = max; else *(outType *)dest = (outType)tmp; src += srcSampleOffset; dest += destSampleOffset; } return; } float delta = float(srcSampleCount) / float(destSampleCount); float current = 0.0f; float oldSample = ((Interpolate*)object)->fOldSample; #define SRC *(const inType*)(src) while (count--) { float tmp = (gain * (oldSample + (SRC - oldSample) * current - inMiddle) + outMiddle); if (tmp <= min) *(outType *)dest = min; else if (tmp >= max) *(outType *)dest = max; else *(outType *)dest = (outType)tmp; dest += destSampleOffset; current += delta; if (current >= 1.0f) { double ipart; current = modf(current, &ipart); oldSample = SRC; src += srcSampleOffset * (int)ipart; } } ((Interpolate*)object)->fOldSample = oldSample; } Interpolate::Interpolate(uint32 src_format, uint32 dst_format) : Resampler(), fOldSample(0) { if (src_format == media_raw_audio_format::B_AUDIO_UCHAR) fOldSample = 128; if (dst_format == media_raw_audio_format::B_AUDIO_FLOAT) { switch (src_format) { case media_raw_audio_format::B_AUDIO_FLOAT: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_INT: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_SHORT: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_CHAR: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_UCHAR: fFunc = &kernel; return; default: ERROR("Resampler::Resampler: unknown source format 0x%x\n", src_format); return; } } if (src_format == media_raw_audio_format::B_AUDIO_FLOAT) { switch (dst_format) { // float=>float already handled above case media_raw_audio_format::B_AUDIO_INT: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_SHORT: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_CHAR: fFunc = &kernel; return; case media_raw_audio_format::B_AUDIO_UCHAR: fFunc = &kernel; return; default: ERROR("Resampler::Resampler: unknown destination format 0x%x\n", dst_format); return; } } ERROR("Resampler::Resampler: source or destination format must be " "B_AUDIO_FLOAT\n"); }