diff -NurBb src/audio2.h patched_src/audio2.h --- ccaudio2-0.9.0/src/audio2.h 2006-04-06 10:25:17.000000000 +0200 +++ ccaudio2-0.9.0/patched_src/audio2.h 2006-04-22 14:13:25.000000000 +0200 @@ -82,6 +82,7 @@ #endif #include +#include "fixedPoint.H" namespace ost { @@ -760,7 +761,7 @@ Rate rate; unsigned samples; Linear frame; - double df1, df2, p1, p2; + FixedPoint df1, df2, p1, p2; Level m1, m2; bool silencer; diff -NurBb src/detect.cpp patched_src/detect.cpp --- ccaudio2-0.9.0/src/detect.cpp 2005-07-29 22:16:35.000000000 +0200 +++ ccaudio2-0.9.0/patched_src/detect.cpp 2006-04-22 14:13:26.000000000 +0200 @@ -78,6 +78,13 @@ static float dtmf_col[] = { 1209.0, 1336.0, 1477.0, 1633.0 }; static float fax_freq = 1100.0; + // fixed value for dtmf_detect_(row|col)[].fac for SAMPLE_RATE = 8000 + static float init[4][4]={ {1.70774,1.1641,0.916368,-0.644862}, + {1.64528,0.99637,0.70695,-1.00725}, + {1.56869,0.798618,0.460779,-1.36221}, + {1.4782,0.568533,0.185089,-1.67677} + }; + state = (dtmf_detect_state_t *)malloc(sizeof(dtmf_detect_state_t)); memset(state, 0, sizeof(state)); @@ -85,15 +92,19 @@ { theta = (float)(2.0 * M_PI * (dtmf_row[i] / SAMPLE_RATE)); dtmf_detect_row[i].fac = (float)(2.0 * cos(theta)); + dtmf_detect_row[i].fac = init[i][0]; theta = (float)(2.0 * M_PI * (dtmf_col[i] / SAMPLE_RATE)); dtmf_detect_col[i].fac = (float)(2.0 * cos(theta)); + dtmf_detect_col[i].fac = init[i][1]; theta = (float)(2.0 * M_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE)); dtmf_detect_row_2nd[i].fac = (float)(2.0 * cos(theta)); + dtmf_detect_row_2nd[i].fac = init[i][2]; theta = (float)(2.0 * M_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE)); dtmf_detect_col_2nd[i].fac = (float)(2.0 * cos(theta)); + dtmf_detect_col_2nd[i].fac = init[i][3]; goertzelInit(&state->row_out[i], &dtmf_detect_row[i]); goertzelInit(&state->col_out[i], &dtmf_detect_col[i]); @@ -196,30 +207,30 @@ state->row_out[0].v2 = state->row_out[0].v3; state->row_out[0].v3 = state->row_out[0].fac*state->row_out[0].v2 - v1 + famp; - v1 = state->col_out[0].v2; - state->col_out[0].v2 = state->col_out[0].v3; - state->col_out[0].v3 = state->col_out[0].fac*state->col_out[0].v2 - v1 + famp; - v1 = state->row_out[1].v2; state->row_out[1].v2 = state->row_out[1].v3; state->row_out[1].v3 = state->row_out[1].fac*state->row_out[1].v2 - v1 + famp; - v1 = state->col_out[1].v2; - state->col_out[1].v2 = state->col_out[1].v3; - state->col_out[1].v3 = state->col_out[1].fac*state->col_out[1].v2 - v1 + famp; - v1 = state->row_out[2].v2; state->row_out[2].v2 = state->row_out[2].v3; state->row_out[2].v3 = state->row_out[2].fac*state->row_out[2].v2 - v1 + famp; - v1 = state->col_out[2].v2; - state->col_out[2].v2 = state->col_out[2].v3; - state->col_out[2].v3 = state->col_out[2].fac*state->col_out[2].v2 - v1 + famp; - v1 = state->row_out[3].v2; state->row_out[3].v2 = state->row_out[3].v3; state->row_out[3].v3 = state->row_out[3].fac*state->row_out[3].v2 - v1 + famp; + v1 = state->col_out[0].v2; + state->col_out[0].v2 = state->col_out[0].v3; + state->col_out[0].v3 = state->col_out[0].fac*state->col_out[0].v2 - v1 + famp; + + v1 = state->col_out[1].v2; + state->col_out[1].v2 = state->col_out[1].v3; + state->col_out[1].v3 = state->col_out[1].fac*state->col_out[1].v2 - v1 + famp; + + v1 = state->col_out[2].v2; + state->col_out[2].v2 = state->col_out[2].v3; + state->col_out[2].v3 = state->col_out[2].fac*state->col_out[2].v2 - v1 + famp; + v1 = state->col_out[3].v2; state->col_out[3].v2 = state->col_out[3].v3; state->col_out[3].v3 = state->col_out[3].fac*state->col_out[3].v2 - v1 + famp; @@ -228,34 +239,34 @@ state->col_out2nd[0].v2 = state->col_out2nd[0].v3; state->col_out2nd[0].v3 = state->col_out2nd[0].fac*state->col_out2nd[0].v2 - v1 + famp; - v1 = state->row_out2nd[0].v2; - state->row_out2nd[0].v2 = state->row_out2nd[0].v3; - state->row_out2nd[0].v3 = state->row_out2nd[0].fac*state->row_out2nd[0].v2 - v1 + famp; - v1 = state->col_out2nd[1].v2; state->col_out2nd[1].v2 = state->col_out2nd[1].v3; state->col_out2nd[1].v3 = state->col_out2nd[1].fac*state->col_out2nd[1].v2 - v1 + famp; - v1 = state->row_out2nd[1].v2; - state->row_out2nd[1].v2 = state->row_out2nd[1].v3; - state->row_out2nd[1].v3 = state->row_out2nd[1].fac*state->row_out2nd[1].v2 - v1 + famp; - v1 = state->col_out2nd[2].v2; state->col_out2nd[2].v2 = state->col_out2nd[2].v3; state->col_out2nd[2].v3 = state->col_out2nd[2].fac*state->col_out2nd[2].v2 - v1 + famp; - v1 = state->row_out2nd[2].v2; - state->row_out2nd[2].v2 = state->row_out2nd[2].v3; - state->row_out2nd[2].v3 = state->row_out2nd[2].fac*state->row_out2nd[2].v2 - v1 + famp; - v1 = state->col_out2nd[3].v2; state->col_out2nd[3].v2 = state->col_out2nd[3].v3; state->col_out2nd[3].v3 = state->col_out2nd[3].fac*state->col_out2nd[3].v2 - v1 + famp; + v1 = state->row_out2nd[0].v2; + state->row_out2nd[0].v2 = state->row_out2nd[0].v3; + state->row_out2nd[0].v3 = state->row_out2nd[0].fac*state->row_out2nd[0].v2 - v1 + famp; + + v1 = state->row_out2nd[1].v2; + state->row_out2nd[1].v2 = state->row_out2nd[1].v3; + state->row_out2nd[1].v3 = state->row_out2nd[1].fac*state->row_out2nd[1].v2 - v1 + famp; + + v1 = state->row_out2nd[2].v2; + state->row_out2nd[2].v2 = state->row_out2nd[2].v3; + state->row_out2nd[2].v3 = state->row_out2nd[2].fac*state->row_out2nd[2].v2 - v1 + famp; + v1 = state->row_out2nd[3].v2; state->row_out2nd[3].v2 = state->row_out2nd[3].v3; state->row_out2nd[3].v3 = state->row_out2nd[3].fac*state->row_out2nd[3].v2 - v1 + famp; - +#ifdef FAXDETECT v1 = state->fax_tone.v2; state->fax_tone.v2 = state->fax_tone.v3; state->fax_tone.v3 = state->fax_tone.fac*state->fax_tone.v2 - v1 + famp; @@ -263,13 +274,15 @@ v1 = state->fax_tone.v2; state->fax_tone2nd.v2 = state->fax_tone2nd.v3; state->fax_tone2nd.v3 = state->fax_tone2nd.fac*state->fax_tone2nd.v2 - v1 + famp; +#endif } state->current_sample += (limit - sample); if(state->current_sample < 102) continue; +#ifdef FAXDETECT fax_energy = goertzelResult(&state->fax_tone); - +#endif // We are at the end of a DTMF detection block // Find the peak row and the peak column row_energy[0] = goertzelResult (&state->row_out[0]); @@ -332,6 +345,7 @@ } } +#ifdef FAXDETECT if (!hit && (fax_energy >= FAX_THRESHOLD) && (fax_energy > state->energy * 21.0)) { fax_energy_2nd = goertzelResult(&state->fax_tone2nd); @@ -356,6 +370,7 @@ } state->fax_hits = 0; } +#endif state->hit1 = state->hit2; state->hit2 = state->hit3; state->hit3 = hit; diff -NurBb src/fixedPoint.C patched_src/fixedPoint.C --- ccaudio2-0.9.0/src/fixedPoint.C 1970-01-01 01:00:00.000000000 +0100 +++ ccaudio2-0.9.0/patched_src/fixedPoint.C 2006-04-22 14:13:26.000000000 +0200 @@ -0,0 +1,145 @@ +#include "fixedPoint.H" + +#include + +#define TABLESIZE (1<(q))); +} + +static FixedPoint cosGenerator(int x) { + FixedPoint q(2 * x * 3.14156); + q /= NUMPOINTS; + return FixedPoint(cos(static_cast(q))); +} + +static FixedPoint sinGeneratorSmall(int x) { + FixedPoint q(2 * x * 3.14156); + q /= NUMPOINTS * NUMPOINTS; + return FixedPoint(sin(static_cast(q))); +} + +void FixedPoint::generateTables() { + int i; + std::cout << "unsigned short sinL[] = { 0"; + for (i=1; i(v) >> RES_BITS) & 3; + + // handle sin(alpha) as sin(large+small) with large+small=alpha + // large is here 0-NUMPOINTS, small is (alpha-large) scaled to NUMPOINTS + int large = static_cast(v) & (TABLESIZE-1); + int small = v.getNKS()>>(FixedPoint::decimalPlaces - RES_BITS); + + // calculate sin for first quadrant + FixedPoint r; + // assuming coshelper2(small) == 1 + if ( q&1 ) { + r = coshelper(large)-sinhelper(large)*sinhelperSmall(small); + } else { + r = sinhelper(large)+sinhelperSmall(small)*coshelper(large); + } + + if ( q>1 ) + r.negate(); + + return r; +} + +FixedPoint +cos(const FixedPoint& v) { + // scaled to use NUMPOINTS==(1<(v) >> RES_BITS) & 3; + + // handle sin(alpha) as sin(large+small) with large+small=alpha + // large is here 0-NUMPOINTS, small is (alpha-large) scaled to NUMPOINTS + int large = static_cast(v) & (TABLESIZE-1); + int small = v.getNKS()>>(FixedPoint::decimalPlaces - RES_BITS); + + // calculate sin for first quadrant + FixedPoint r; + // assuming coshelper2(small) == 1 + if ( q&1 ) { + r = sinhelper(large)+sinhelperSmall(small)*coshelper(large); + } else { + r = coshelper(large)-sinhelper(large)*sinhelperSmall(small); + } + + if ( q==1 || q==2 ) + r.negate(); + + return r; +} diff -NurBb src/fixedPoint.H patched_src/fixedPoint.H --- ccaudio2-0.9.0/src/fixedPoint.H 1970-01-01 01:00:00.000000000 +0100 +++ ccaudio2-0.9.0/patched_src/fixedPoint.H 2006-04-22 14:13:26.000000000 +0200 @@ -0,0 +1,239 @@ +#ifndef FIXEDPOINT__H__ +#define FIXEDPOINT__H__ + +#include + +#define longlong + +const int RES_BITS = 7; +const int NUMPOINTS = (1<<(RES_BITS+2)); + +const int FP_PI_TRIG = (1<<(RES_BITS+1)); // use this as pi in trig functions + +class FixedPoint; +static inline int prepareMultiply(FixedPoint& r, FixedPoint&f); +static inline void check_overflow(const FixedPoint&a, const FixedPoint&b); + +class FixedPoint { +public: +#ifdef longlong + typedef long long _fp; +#else + typedef long _fp; +#endif + + FixedPoint() { value=0; } + FixedPoint(int v) { value = static_cast<_fp>(v) << decimalPlaces; } + FixedPoint(unsigned int v) { value = static_cast<_fp>(v) << decimalPlaces; } + FixedPoint(double v) { value = static_cast<_fp>(v * (1 << decimalPlaces)); } + FixedPoint(float v) { value = static_cast<_fp>(v * (1 << decimalPlaces)); } + FixedPoint(const FixedPoint& a) { value = a.value; } + FixedPoint(int ganz, int komma) { value = (static_cast<_fp>(ganz)<> decimalPlaces; } + operator int() const { return value >> decimalPlaces; } // this conversion can overflow!! + operator double() const { return (double)value / (1<>= shift; + + return r; + } + + void operator*=(const FixedPoint& b) + { + FixedPoint f(b); + + // shift r.value and f.value so, that no overrun occurs + int shift = prepareMultiply(*this, f); + check_overflow(*this, f); + + value *= f.value; + + // shift away nks + value >>= shift; + } + +#endif + friend FixedPoint operator*(const FixedPoint& a, int v) + { FixedPoint r(a); r.value *= v; return r; } + friend FixedPoint operator*(int v, const FixedPoint& b) + { FixedPoint r(b); r.value *= v; return r; } + void operator*=(int v) + { value *= v; } + +#ifdef longlong + friend FixedPoint operator/(const FixedPoint& a, const FixedPoint& b) + { FixedPoint r(a); r.value<<=decimalPlaces; r.value /= b.value; return r; } + void operator/=(const FixedPoint& a) + { value<<=decimalPlaces; value /= a.value; } +#else + friend FixedPoint operator/(const FixedPoint& a, const FixedPoint& b) + { + FixedPoint r; + long long v = a.value; + v <<= decimalPlaces; + v /= b.value; + r.value = v; + return r; + } + void operator/=(const FixedPoint& a) + { + long long v = value; + v <<= decimalPlaces; + v /= a.value; + value = v; + } +#endif + friend FixedPoint operator/(const FixedPoint& a, int v) + { FixedPoint r(a); r.value /= v; return r; } + void operator/=(int v) + { value /= v; } + + friend FixedPoint operator+(const FixedPoint& a, const FixedPoint& b) + { FixedPoint r(a); r.value += b.value; return r; } + friend FixedPoint operator+(const FixedPoint& a, int v) + { FixedPoint r(a); r.value += v<(const FixedPoint& a, const FixedPoint& b) + { return a.value > b.value; } + friend bool operator>(const FixedPoint& a, int v) + { return a.value > (v << decimalPlaces) ; } + friend bool operator>(int v, const FixedPoint& b) + { return (v << decimalPlaces )> b.value; } + + friend bool operator>=(const FixedPoint& a, const FixedPoint& b) + { return a.value >= b.value; } + friend bool operator<=(const FixedPoint& a, const FixedPoint& b) + { return a.value <= b.value; } + friend bool operator>=(const FixedPoint& a, int v) + { return a.value >= ( v << decimalPlaces ); } + friend bool operator>=(int v, const FixedPoint& b) + { return ( v << decimalPlaces ) >= b.value; } + friend bool operator<=(const FixedPoint& a, int v) + { return a.value <= ( v << decimalPlaces ); } + friend bool operator<=(int v, const FixedPoint& b) + { return ( v << decimalPlaces ) <= b.value; } + + friend std::ostream& operator<<(std::ostream& os, FixedPoint f) + { + return os << (double)f << " [" << std::hex << (_fp)f << "#" << f.getNKS() << std::dec << "]"; + } + + friend FixedPoint sin(const FixedPoint& v); + friend FixedPoint cos(const FixedPoint& v); + + unsigned int getNKS() const { return value & ((1<>=1; + } + } else { + first=0x4000000000000000LL; + while ( shift>=1; + } + } + if ( f.value < 0 ) { + first=0x4000000000000000LL; + while ( shift>=1; + } + } else { + first=0x4000000000000000LL; + while ( shift>=1; + } + } + + if ( shift>= donow/2; + f.value >>= donow-(donow/2); + } + return shift; +} + +void check_overflow(const FixedPoint&a, const FixedPoint&b) { + if ( a<0 && b<0 || (a>0 && b>0) ) { + if ( a.value * b.value < 0 ) + std::cerr << " overflow1: " << a << " * " << b << "=" << a.value*b.value << std::endl; + } else if ( a.value * b.value > 0 ) + std::cerr << " overflow2: " << a << " * " << b << "=" << a.value*b.value << std::endl; +} + +#endif /* FIXEDPOINT__H__ */ diff -NurBb src/Makefile.am patched_src/Makefile.am --- ccaudio2-0.9.0/src/Makefile.am 2006-03-01 17:43:29.000000000 +0100 +++ ccaudio2-0.9.0/patched_src/Makefile.am 2006-04-22 14:13:25.000000000 +0200 @@ -14,12 +14,13 @@ RELEASE = -version-info @LT_VERSION@ -release @LT_RELEASE@ ccxxincludedir=$(includedir)/cc++ ccxxinclude_HEADERS = audio2.h +AM_CXXFLAGS=-msoft-float lib_LTLIBRARIES = libccaudio2.la libccaudio2_la_SOURCES = audiofile.cpp friends.cpp codec.cpp tone.cpp \ fileio.cpp buffer.cpp stream.cpp oss.cpp w32.cpp osx.cpp \ - mapper.cpp dialers.cpp teltones.cpp detect.cpp audiobase.cpp + mapper.cpp dialers.cpp teltones.cpp detect.cpp audiobase.cpp fixedPoint.C libccaudio2_la_LDFLAGS = $(DYN_LOADER) $(AUDIO_LIBS) -lm $(RELEASE) diff -NurBb src/tone.cpp patched_src/tone.cpp --- ccaudio2-0.9.0/src/tone.cpp 2006-03-01 16:51:13.000000000 +0100 +++ ccaudio2-0.9.0/patched_src/tone.cpp 2006-04-22 14:13:25.000000000 +0200 @@ -37,12 +37,15 @@ #include "private.h" #include "audio2.h" -#include +#include "fixedPoint.H" #ifndef M_PI #define M_PI 3.14159265358979323846 #endif +#undef M_PI +#define M_PI FP_PI_TRIG + using namespace ost; AudioTone::AudioTone(timeout_t duration, Rate r) @@ -59,8 +62,8 @@ AudioTone::AudioTone(unsigned freq, Level l, timeout_t duration, Rate r) { rate = r; - df1 = (freq * M_PI * 2) / (long)rate; - df2 = (freq * M_PI * 2) / (long)rate; + df1 = FixedPoint(freq * M_PI * 2) / (int)rate; + df2 = FixedPoint(freq * M_PI * 2) / (int)rate; p1 = 0, p2 = 0; samples = (duration * (long)rate) / 1000; m1 = l / 2; @@ -73,8 +76,8 @@ AudioTone::AudioTone(unsigned f1, unsigned f2, Level l1, Level l2, timeout_t duration, Rate r) { rate = r; - df1 = (f1 * M_PI * 2) / (long)r; - df2 = (f2 * M_PI * 2) / (long)r; + df1 = FixedPoint(f1 * M_PI * 2) / (int)r; + df2 = FixedPoint(f2 * M_PI * 2) / (int)r; p1 = 0, p2 = 0; samples = (duration * (long)r) / 1000; m1 = l1 / 2; @@ -124,8 +127,8 @@ void AudioTone::single(unsigned freq, Level l) { - df1 = (freq * M_PI * 2) / (long)rate; - df2 = (freq * M_PI * 2) / (long)rate; + df1 = FixedPoint(freq * M_PI * 2) / (int)rate; + df2 = FixedPoint(freq * M_PI * 2) / (int)rate; m1 = l / 2; m2 = l / 2; silencer = false; @@ -133,8 +136,8 @@ void AudioTone::dual(unsigned f1, unsigned f2, Level l1, Level l2) { - df1 = (f1 * M_PI * 2) / (long)rate; - df2 = (f2 * M_PI * 2) / (long)rate; + df1 = FixedPoint(f1 * M_PI * 2) / (int)rate; + df2 = FixedPoint(f2 * M_PI * 2) / (int)rate; m1 = l1 / 2; m2 = l2 / 2; silencer = false; @@ -188,8 +191,8 @@ continue; } - *(data++) = (Level)(sin(p1) * (double)m1) + - (Level)(sin(p2) * (double)m2); + *(data++) = (Level)(int)(sin(p1) * m1) + + (Level)(int)(sin(p2) * m2); p1 += df1; p2 += df2; @@ -199,8 +202,8 @@ { while(count--) { - *(data++) = (Level)(sin(p1) * (double)m1) + - (Level)(sin(p2) * (double)m2); + *(data++) = (Level)(int)(sin(p1) * m1) + + (Level)(int)(sin(p2) * m2); p1 += df1; p2 += df2;