From 42995d7bf396933ee60c5f89c354ea89cf13df0d Mon Sep 17 00:00:00 2001 From: tpearson Date: Tue, 5 Jan 2010 00:01:18 +0000 Subject: Copy of aRts for Trinity modifications git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/dependencies/arts@1070145 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- flow/convert.cc | 418 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 418 insertions(+) create mode 100644 flow/convert.cc (limited to 'flow/convert.cc') diff --git a/flow/convert.cc b/flow/convert.cc new file mode 100644 index 0000000..d5ca2f8 --- /dev/null +++ b/flow/convert.cc @@ -0,0 +1,418 @@ + /* + + 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., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. + + */ + +#include "convert.h" +#include +#include +#include +#include + +#ifdef HAVE_X86_FLOAT_INT +static inline long QRound (float inval) +{ +#if (__GNUC__ == 3 && __GNUC_MINOR__ == 0) + volatile +#warning "workaround for gcc-3.0 bug c++/2733 enabled" +#endif + int ret; + __asm__ ("fistpl %0" : "=m" (ret) : "t" (inval) : "st"); + return ret; +} +#else +static inline long QRound (float inval) +{ + return (long)inval; +} +#endif + +/*---------------------------- new code begin -------------------------- */ + +#define compose_16le(ptr) \ + ((((*((ptr)+1)+128)&0xff) << 8)+*(ptr)) + +#define compose_16be(ptr) \ + ((((*(ptr)+128)&0xff) << 8)+*((ptr)+1)) + +#define conv_16_float(x) \ + ((float)((x)-32768)/32768.0) + +#define convert_16le_float(x) conv_16_float(compose_16le(&(x))) +#define convert_16be_float(x) conv_16_float(compose_16be(&(x))) + +#define conv_8_float(x) \ + ((float)((x)-128)/128.0) + +#define convert_8_float(x) \ + ((float)((x)-128)/128.0) + +#define convert_float_float(x) x + +/* + * 16le, 16be, 8, float + */ + +#define datatype_16le unsigned char +#define datasize_16le 2 + +#define datatype_16be unsigned char +#define datasize_16be 2 + +#define datatype_8 unsigned char +#define datasize_8 1 + +#define datatype_float float +#define datasize_float 1 + +#define mk_converter(from_format,to_format) \ +void Arts::convert_mono_ ## from_format ## _ ## to_format (unsigned long samples, \ + datatype_ ## from_format *from, \ + datatype_ ## to_format *to) \ +{ \ + datatype_ ## to_format *end = to+samples * (datasize_ ## to_format); \ + while(to 32767) syn = 32767; + + *to++ = syn & 0xff; + *to++ = (syn >> 8) & 0xff; + + syn = QRound((*right++)*32767); + + if(syn < -32768) syn = -32768; /* clipping */ + if(syn > 32767) syn = 32767; + + *to++ = syn & 0xff; + *to++ = (syn >> 8) & 0xff; + } +} + +void Arts::convert_mono_float_16le(unsigned long samples, float *from, unsigned char *to) +{ + float *end = from+samples; + + while(from < end) + { + long syn = QRound((*from++)*32767); + + if(syn < -32768) syn = -32768; /* clipping */ + if(syn > 32767) syn = 32767; + + *to++ = syn & 0xff; + *to++ = (syn >> 8) & 0xff; + } +} + +void Arts::convert_stereo_2float_i16be(unsigned long samples, float *left, float *right, unsigned char *to) +{ + float *end = left+samples; + long syn; + + while(left < end) + { + syn = QRound((*left++)*32767); + + if(syn < -32768) syn = -32768; /* clipping */ + if(syn > 32767) syn = 32767; + + *to++ = (syn >> 8) & 0xff; + *to++ = syn & 0xff; + + syn = QRound((*right++)*32767); + + if(syn < -32768) syn = -32768; /* clipping */ + if(syn > 32767) syn = 32767; + + *to++ = (syn >> 8) & 0xff; + *to++ = syn & 0xff; + } +} + +void Arts::convert_mono_float_16be(unsigned long samples, float *from, unsigned char *to) +{ + float *end = from+samples; + + while(from < end) + { + long syn = QRound((*from++)*32767); + + if(syn < -32768) syn = -32768; /* clipping */ + if(syn > 32767) syn = 32767; + + *to++ = (syn >> 8) & 0xff; + *to++ = syn & 0xff; + } +} + +void Arts::convert_stereo_2float_i8(unsigned long samples, float *left, float *right, unsigned char *to) +{ + float *end = left+samples; + long syn; + + while(left < end) + { + syn = (int)((*left++)*127+128); + + if(syn < 0) syn = 0; /* clipping */ + if(syn > 255) syn = 255; + + *to++ = syn; + + syn = (int)((*right++)*127+128); + + if(syn < 0) syn = 0; /* clipping */ + if(syn > 255) syn = 255; + + *to++ = syn; + } +} + +void Arts::convert_mono_float_8(unsigned long samples, float *from, unsigned char *to) +{ + float *end = from+samples; + + while(from < end) + { + long syn = (int)((*from++)*127+128); + + if(syn < 0) syn = 0; /* clipping */ + if(syn > 255) syn = 255; + + *to++ = syn; + } +} + +unsigned long Arts::uni_convert_stereo_2float( + unsigned long samples, // number of required samples + unsigned char *from, // buffer containing the samples + unsigned long fromLen, // length of the buffer + unsigned int fromChannels, // channels stored in the buffer + unsigned int fromBits, // number of bits per sample + float *left, float *right, // output buffers for left and right channel + double speed, // speed (2.0 means twice as fast) + double startposition // startposition + ) +{ + unsigned long doSamples = 0, sampleSize = fromBits/8; + + if(fromBits == uni_convert_float_ne) + sampleSize = sizeof(float); + + // how many samples does the from-buffer contain? + double allSamples = fromLen / (fromChannels * sampleSize); + + // how many samples are remaining? + // subtract one due to interpolation and another against rounding errors + double fHaveSamples = allSamples - startposition - 2.0; + fHaveSamples /= speed; + + // convert do "how many samples to do"? + if(fHaveSamples > 0) + { + doSamples = (int)fHaveSamples; + if(doSamples > samples) doSamples = samples; + } + + // do conversion + if(doSamples) + { + if(fromChannels == 1) + { + if(fromBits == uni_convert_float_ne) { + interpolate_mono_float_float(doSamples, + startposition,speed,(float *)from,left); + } + else if(fromBits == uni_convert_s16_be) { + interpolate_mono_16be_float(doSamples, + startposition,speed,from,left); + } + else if(fromBits == uni_convert_s16_le) { + interpolate_mono_16le_float(doSamples, + startposition,speed,from,left); + } + else { + interpolate_mono_8_float(doSamples, + startposition,speed,from,left); + } + memcpy(right,left,sizeof(float)*doSamples); + } + else if(fromChannels == 2) + { + if(fromBits == uni_convert_float_ne) { + interpolate_stereo_ifloat_2float(doSamples, + startposition,speed,(float *)from,left,right); + } + else if(fromBits == uni_convert_s16_be) { + interpolate_stereo_i16be_2float(doSamples, + startposition,speed,from,left,right); + } + else if(fromBits == uni_convert_s16_le) { + interpolate_stereo_i16le_2float(doSamples, + startposition,speed,from,left,right); + } + else { + interpolate_stereo_i8_2float(doSamples, + startposition,speed,from,left,right); + } + } else { + assert(false); + } + } + return doSamples; +} + +// undefine all that stuff (due to --enable-final) +#undef compose_16le +#undef compose_16be +#undef conv_16_float +#undef convert_16le_float +#undef convert_16be_float +#undef conv_8_float +#undef convert_8_float +#undef convert_float_float +#undef datatype_16le +#undef datasize_16le +#undef datatype_16be +#undef datasize_16be +#undef datatype_8 +#undef datasize_8 +#undef datatype_float +#undef datasize_float +#undef mk_converter -- cgit v1.2.3