bool SND_Out_File::write(const vec &v) { if (!good()) return false; int i; bool switch_endian = !is_bigendian(); // if LITTLE_ENDIAN than switch switch (header.encoding) { case enc_linear8 : for (i = 0; i < v.size(); i++) write_endian<char>(file, double_to_char(v(i) * 128.0), switch_endian); break; case enc_linear16 : for (i = 0; i < v.size(); i++) write_endian<short>(file, double_to_short(v(i) * 32768.0), switch_endian); break; case enc_float : for (i = 0; i < v.size(); i++) write_endian<float>(file, static_cast<float>(v(i)), switch_endian); break; case enc_double : for (i = 0; i < v.size(); i++) write_endian<double>(file, static_cast<double>(v(i)), switch_endian); break; default : it_warning("SND_Out_File::write(): Unsupported encoding!"); return false; } return file.good(); }
double hyperg(double a, double b, double x) { double asum, psum, acanc, pcanc = 0, temp; /* See if a Kummer transformation will help */ temp = b - a; if (fabs(temp) < 0.001 * fabs(a)) return(exp(x) * hyperg(temp, b, -x)); psum = hy1f1p(a, b, x, &pcanc); if (pcanc < 1.0e-15) goto done; /* try asymptotic series */ asum = hy1f1a(a, b, x, &acanc); /* Pick the result with less estimated error */ if (acanc < pcanc) { pcanc = acanc; psum = asum; } done: if (pcanc > 1.0e-12) { it_warning("hyperg(): partial loss of precision"); } return(psum); }
bool SND_In_File::read(vec &v, int n) { if (!good()) return false; int i; bool switch_endian = !is_bigendian(); // if LITTLE_ENDIAN than switch v.set_size(n, false); switch (header.encoding) { case enc_linear8 : for (i = 0; i < n; i++) v(i) = read_endian<char>(file, switch_endian) / 128.0; break; case enc_linear16 : for (i = 0; i < n; i++) v(i) = read_endian<short>(file, switch_endian) / 32768.0; break; case enc_float : for (i = 0; i < n; i++) v(i) = read_endian<float>(file, switch_endian); break; case enc_double : for (i = 0; i < n; i++) v(i) = read_endian<double>(file, switch_endian); break; default : it_warning("SND_In_File::read(): Unsupported encoding!"); return false; } return file.good(); }
bool SND_Format::read_header(std::istream &f) { bool switch_endian = !is_bigendian(); // if LITTLE_ENDIAN than switch f.seekg(0); header.magic = read_endian<unsigned int>(f, switch_endian); header.hdr_size = read_endian<unsigned int>(f, switch_endian); header.data_size = read_endian<unsigned int>(f, switch_endian); header.encoding = read_endian<unsigned int>(f, switch_endian); header.sample_rate = read_endian<unsigned int>(f, switch_endian); header.channels = read_endian<unsigned int>(f, switch_endian); f.read(header.info, SND_INFO_LEN); if (!f || header.magic != SND_MAGIC) { std::cerr << header.magic << " != " << SND_MAGIC << std::endl; it_warning("SND_Format::read_header(): This is not a .snd file!"); return false; } f.seekg(header.hdr_size); return f.good(); }
double hyp2f0(double a, double b, double x, int type, double *err) { double a0, alast, t, tlast, maxt; double n, an, bn, u, sum, temp; an = a; bn = b; a0 = 1.0e0; alast = 1.0e0; sum = 0.0; n = 1.0e0; t = 1.0e0; tlast = 1.0e9; maxt = 0.0; do { if (an == 0) goto pdone; if (bn == 0) goto pdone; u = an * (bn * x / n); /* check for blowup */ temp = fabs(u); if ((temp > 1.0) && (maxt > (MAXNUM / temp))) goto error; a0 *= u; t = fabs(a0); /* terminating condition for asymptotic series */ if (t > tlast) goto ndone; tlast = t; sum += alast; /* the sum is one term behind */ alast = a0; if (n > 200) goto ndone; an += 1.0e0; bn += 1.0e0; n += 1.0e0; if (t > maxt) maxt = t; } while (t > MACHEP); pdone: /* series converged! */ /* estimate error due to roundoff and cancellation */ *err = fabs(MACHEP * (n + maxt)); alast = a0; goto done; ndone: /* series did not converge */ /* The following "Converging factors" are supposed to improve accuracy, * but do not actually seem to accomplish very much. */ n -= 1.0; x = 1.0 / x; switch (type) { /* "type" given as subroutine argument */ case 1: alast *= (0.5 + (0.125 + 0.25 * b - 0.5 * a + 0.25 * x - 0.25 * n) / x); break; case 2: alast *= 2.0 / 3.0 - b + 2.0 * a + x - n; break; default: ; } /* estimate error due to roundoff, cancellation, and nonconvergence */ *err = MACHEP * (n + maxt) + fabs(a0); done: sum += alast; return(sum); /* series blew up: */ error: *err = MAXNUM; it_warning("hy1f1a(): total loss of precision"); return(sum); }
/* Power series summation for confluent hypergeometric function */ static double hy1f1p(double a, double b, double x, double *err) { double n, a0, sum, t, u, temp; double an, bn, maxt, pcanc; /* set up for power series summation */ an = a; bn = b; a0 = 1.0; sum = 1.0; n = 1.0; t = 1.0; maxt = 0.0; while (t > MACHEP) { if (bn == 0) { /* check bn first since if both */ it_warning("hy1f1p(): function singularity"); return(MAXNUM); /* an and bn are zero it is */ } if (an == 0) /* a singularity */ return(sum); if (n > 200) goto pdone; u = x * (an / (bn * n)); /* check for blowup */ temp = fabs(u); if ((temp > 1.0) && (maxt > (MAXNUM / temp))) { pcanc = 1.0; /* estimate 100% error */ goto blowup; } a0 *= u; sum += a0; t = fabs(a0); if (t > maxt) maxt = t; /* if( (maxt/fabs(sum)) > 1.0e17 ) { pcanc = 1.0; goto blowup; } */ an += 1.0; bn += 1.0; n += 1.0; } pdone: /* estimate error due to roundoff and cancellation */ if (sum != 0.0) maxt /= fabs(sum); maxt *= MACHEP; /* this way avoids multiply overflow */ pcanc = fabs(MACHEP * n + maxt); blowup: *err = pcanc; return(sum); }
//Correlation void xcorr(const cvec &x, const cvec &y, cvec &out, const int max_lag, const std::string scaleopt, bool autoflag) { int N = std::max(x.length(), y.length()); //Compute the FFT size as the "next power of 2" of the input vector's length (max) int b = ceil_i(::log2(2.0 * N - 1)); int fftsize = pow2i(b); int end = fftsize - 1; cvec temp2; if (autoflag == true) { //Take FFT of input vector cvec X = fft(zero_pad(x, fftsize)); //Compute the abs(X).^2 and take the inverse FFT. temp2 = ifft(elem_mult(X, conj(X))); } else { //Take FFT of input vectors cvec X = fft(zero_pad(x, fftsize)); cvec Y = fft(zero_pad(y, fftsize)); //Compute the crosscorrelation temp2 = ifft(elem_mult(X, conj(Y))); } // Compute the total number of lags to keep. We truncate the maximum number of lags to N-1. int maxlag; if ((max_lag == -1) || (max_lag >= N)) maxlag = N - 1; else maxlag = max_lag; //Move negative lags to the beginning of the vector. Drop extra values from the FFT/IFFt if (maxlag == 0) { out.set_size(1, false); out = temp2(0); } else out = concat(temp2(end - maxlag + 1, end), temp2(0, maxlag)); //Scale data if (scaleopt == "biased") //out = out / static_cast<double_complex>(N); out = out / static_cast<std::complex<double> >(N); else if (scaleopt == "unbiased") { //Total lag vector vec lags = linspace(-maxlag, maxlag, 2 * maxlag + 1); cvec scale = to_cvec(static_cast<double>(N) - abs(lags)); out /= scale; } else if (scaleopt == "coeff") { if (autoflag == true) // Normalize by Rxx(0) out /= out(maxlag); else { //Normalize by sqrt(Rxx(0)*Ryy(0)) double rxx0 = sum(abs(elem_mult(x, x))); double ryy0 = sum(abs(elem_mult(y, y))); out /= std::sqrt(rxx0 * ryy0); } } else if (scaleopt == "none") {} else it_warning("Unknow scaling option in XCORR, defaulting to <none> "); }