Online · Live + on demand
February 9-11, 2027
Price goes up Nov 1: register now to lock in today's rate
Register Now →
Circular Convolution Matrix
function HC = convmtx_circ(h, N);
% CONVMTX_CIRC Circular Convolution Matrix.
% CONVMTX_CIRC(h,N) returns the circular convolution matrix for vector h.
% h must be a column vector. If X is a column vector of length N,
% then CONVMTX_CIRC(h,N)*X is the same as the circular convolution h * X.
%
% by Danilo Zanatta - 01.02.2011
h = h(:);
Nh = length(h);
Nc = N + Nh - 1;
if N < Nh,
error('The circular convolution matrix size must be greater or equal the channel length');
end
H = convmtx(h,N);
HC = H(1:N, 1:N);
HC(1:(Nh-1), 1:N) = HC(1:(Nh-1), 1:N) + H((N+1):Nc, 1:N);
return2D FFT
function [a2] = fft2d(a)
//a = any real or complex 2D matrix
//a2 = 2D-DFT of 2D matrix 'a'
m=size(a,1)
n=size(a,2)
// fourier transform along the rows
for i=1:n
a1(:,i)=exp(-2*%i*%pi*(0:m-1)'.*.(0:m-1)/m)*a(:,i)
end
// fourier transform along the columns
for j=1:m
a2temp=exp(-2*%i*%pi*(0:n-1)'.*.(0:n-1)/n)*(a1(j,:)).'
a2(j,:)=a2temp.'
end
for i = 1:m
for j = 1:n
if((abs(real(a2(i,j)))<0.0001)&(abs(imag(a2(i,j)))<0.0001))
a2(i,j)=0;
elseif(abs(real(a2(i,j)))<0.0001)
a2(i,j)= 0+%i*imag(a2(i,j));
elseif(abs(imag(a2(i,j)))<0.0001)
a2(i,j)= real(a2(i,j))+0;
end
end
endBiquad bandpass filter bank
// Efficient implementation of biquad bandpass filter bank.
// This is the core computation for musical physical models ("modal models").
//
// This code takes 1.5 instructions to compute each floating-point bandpass filter;
// for a SHARC running at 3ns instruction cycle this is 4.5ns / biquad.
//
// Written by Lippold Haken of Haken Audio, 2010, using ADSP-21364 and VisualDSP++ C.
//
// dmXmod - pointer to DM data memory
// pmXmod - pointer to PM data memory
// bfbXComputePairs - optimized computation of a bank of bandpass filters
// bfbXCoef - coefficient computation for the bandpass filters
// CFDSP hardware-specific definitions.
#include "cfdsp21364.h"
// === Start of definitions for .h file
// The following structure definitions are shared by this code and by the calling code,
// so they should be moved to a common .h file.
// Data in dm.
typedef struct
{
#define bfb4FilterSections 64 // number of modes (number of bandpass filter sections)
float bfb_Y[2][bfb4FilterSections]; // save state: y[n-1] and y[n-2]
} DmX_bfb;
// Data in pm.
typedef struct
{
// The bfb_C[] contains 3 coefficients for each biquad, with a pair of biquad's coefficients
// interleaved so that biquads can be processed in pairs by the optimized SIMD assembly loop.
float bfb_C[ 3 * bfb4FilterSections ]; // bfb filter coefficients, see comment above
} PmX_bfb;
// Pointers to data, and a samples counter.
DmX_bfb *dmXmod;
PmX_bfb *pmXmod;
int sampInFrame; // sample counter
#define sr 48000 // sample rate in Hz
#define Pi (3.14159265)
#define ABS(x) ( ((x)>(0)) ? (x) : -(x) )
void sinCos( float fRadians, float *fSin, float *fCos ); // see Lippold Haken's sinCos code snippet
// === End of definitions for .h file
// Parameter arrays for Biquad Filter Bank (modal physical modelling) synthesis.
//
// If P is the biquad pair number, and R=0/R=1 distinguishes the two biquads within the pair:
// x[n] coefficient for biquad k is at pmXmod->bfb_C[ 6*P + R + 0 ]; this is also -x[n-2] coefficient.
// y[n-1] coefficient for biquad k is at pmXmod->bfb_C[ 6*P + R + 2 ]; this is scaled by 0.5 to avoid overflow
// y[n-2] coefficient for biquad k is at pmXmod->bfb_C[ 6*P + R + 4 ]
// The first index to dmXmod->bfb_Y[] is based on lsbs of sample counter.
// The second index to dmXmod->bfb_Y[] is 2P+R.
// Note: R=0 always for even voices, R=1 always for odd voices.
#define bfb_Ynm1(P) &(dmXmod->bfb_Y[sampInFrame & 1][2*(P)]) // start in y[n-1][] array
#define bfb_Ynm2(P) &(dmXmod->bfb_Y[1-(sampInFrame & 1)][2*(P)]) // start in y[n-2][] array
void bfbXComputePairs(int biquadP, int pairs,
float inDiff0, // x[n]-x[n-2] for even biquads
float inDiff1, // x[n]-x[n-2] for odd biquads
float *fSum0, // output for even biquad sum
float *fSum1) // output for odd biquad sum
// Sum the output of a sequence of at least 2 biquad pairs.
// For each of the sequence of pairs, the first (even) biquad in each pair has a common input "input0",
// and the second (odd) biquad of each pair has a (possibly different) common input "input1".
{
// Assmebly-coded bfb filter loop using floating-point math.
// The core loop takes 3 instructions for 2 biquads, or 4.5ns per biquad.
// We use the even-numbered biquads for one voice, the odd-numbered biquads for a second voice.
asm(
"#include <def21364.h> \n"
"BIT SET MODE1 SIMD; \n"
// For each biquad k: (k=6*biquadP for R=0)
// y[k](n) = C0[k] * (x[k](n) - x[k](n-2))
// + C1[k] * 2 * y[k](n-1)
// + C2[k] * y[k](n-2)
//
// Register usage for biquad k (R==0):
// F0 = C0[k], C1[k], and C2[k]
// F4 = input0-old_input0 aka x[k](n)-x[k](n-2)
// F6 = y[k](n-1), y[k](n-2)
// F8 = scratch for computing y[k](n)
// F10 = sum of even biquad's y[](n) in each biquad pair
// F12 = scratch for computing y[k](n)
// F13 = final value of y[k-2](n)
// DM(I4) = C0[k], C1[k], and C2[k]
// PM(I10) = read y[k](n-2) write to y[k-2](n)
// PM(I12) = read y[k](n-1)
// Register usage for biquad k+1 (R==1):
// SF0 = C0[k+1], C1[k+1], and C2[k+1]
// SF4 = input1-old_input1 aka x[k+1](n)-x[k+1](n-2)
// SF6 = y[k+1](n-1), y[k+1](n-2)
// SF8 = scratch for computing y[k+1](n)
// SF10 = sum of odd biquad's y[](n) in each biquad pair
// SF12 = scratch for computing y[k+1](n)
// SF13 = final value of y[k-1](n)
// DM(I4+1) = C0[k+1], C1[k+1], and C2[k+1]
// PM(I10+1)= read y[k+1](n-2) write y[k-1](n)
// PM(I12+1)= read y[k+1](n-1)
// Register usage for even and odd biquads:
// M4=M12=2
// M10=+4
// M11=-2
//
// The three instruction loop below computes two biquads simultaneously, for k and k+1,
// in each SIMD loop execution. The comments are written just for biquad k;
// the biquad k+1 code and comments are implied by SIMD mode.
// Set pointer increments.
" M4=2;M10=4;M11=-2;M12=2; \n"
// Loop priming, with k=0 (and SIMD k=1).
// Initialize F10=SF10=0 fetch C0[k]
" R10=R10-R10, F0=DM(I4,M4); \n"
// C0[k]*(x(n)-x(n-2)) fetch C1[k] fetch y[k](n-1)
" F8=F0*F4, F0=DM(I4,M4), F6=PM(I12,M12); \n"
// C1[k] * y[k](n-1) fetch C2[k] fetch y[k](n-2)
" F12=F0*F6, F0=DM(I4,M4), F6=PM(I10,M12); \n"
// C2[k] * y[k](n-2) biquad k sum fetch C0[k+2]
" F12=F0*F6, F8=F8+F12, F0=DM(I4,M4); \n"
// Main loop, for k = 2..K-2 by 2 (and SIMD for k = 1..K-1 by 2).
"DO (PC, endx) UNTIL LCE; \n"
// C0[k]*(x(n)-x(n-2)) F13 is y[k-2](n) fetch C1[k] fetch y[k](n-1)
" F8=F0*F4, F13=F8+F12, F0=DM(I4,M4), F6=PM(I12,M12); \n"
// C1[k] * y[k](n-1) output sum fetch C2[k] fetch y[k](n-2)
" F12=F0*F6, F10=F10+F13, F0=DM(I4,M4), F6=PM(I10,M11); \n"
// C2[k] * y[k](n-2) biquad k sum fetch C0[k+2] save y[k-2](n)
"endx: F12=F0*F6, F8=F8+F12, F0=DM(I4,M4), PM(I10,M10)=F13; \n"
// F13 is y[k-2](n)
" F13=F8+F12, modify(I10,M11); \n"
// output sum save y[k-2](n)
" F10=F10+F13, PM(I10,M10)=F13; \n"
"BIT CLR MODE1 SIMD; \n" // disable SIMD
" NOP; \n" // wait for SIMD disable
// Output register list, each element: "=rN" (varName)
: "=R10" (*fSum0), // F10 has floating sum of even & odd biquads
"=S10" (*fSum1) // SF10 has floating sum of even & odd biquads
// Input register list, each element: "rN" (varName)
: "lcntr" (pairs-1),
"R4" (inDiff0), // x[n]-x[n-2] for even biquads
"S4" (inDiff1), // x[n]-x[n-2] for odd biquads
"I4" (&pmXmod->bfb_C[6 * biquadP]), // coefficients for all biquads
"I10" (bfb_Ynm2(biquadP)), // y[n-2] for all biquads, updated to y[n]
"I12" (bfb_Ynm1(biquadP)) // y[n-1] for all biquads
// Clobbered register list:
// We must avoid "do not use" regs, Compiler and Library Manual p.1-245.
// We try to use mostly scratch regs, Compiler and Library Manual p.1-248.
: "r0", "r4", "r6", "r8", "r10", "r12", "r13",
"i4", "i10", "i12",
"m4", "m10", "m11", "m12" );
}
void bfbXCoef(int biquadP, int biquadR, float freq, float amp, float bw)
// Compute coefficients for a biquad filter section of the floating-point Biquad Filter Bank routine.
{
int startingIndex = 6 * biquadP + biquadR; // 6 * biquad pair number (+1 if second in pair)
float *pC = &pmXmod->bfb_C[ startingIndex ]; // index biquad filter coefficients array
float *y0 = &dmXmod->bfb_Y[0][2*biquadP+biquadR]; // filter memory for biquad
float *y1 = &dmXmod->bfb_Y[1][2*biquadP+biquadR]; // filter memory for biquad
// Is center frequency is below aliasing-cutoff limit?
if (freq != 0.0 && freq < 0.5 * sr)
{
// Compute sin and cos of the mode frequency.
float phase = freq * 2. * Pi / sr;
float fSin, fCos;
sinCos(phase, &fSin, &fCos); // efficient sine and cosine; see Lippold Haken's DSPrelated code snippet.
// These formulas are adapted from Robert Bristow-Johnson BLT biquad web posting.
// I use the BPF with "constant skirt gain, peak gain = Q", with amplitude scaling of input coefficients.
// Compute intermediate parameters, alpha and beta.
// alpha = sin(w0)/(2*Q)
// beta = 1/(1+alpha)
// y[n] = (beta * sin(w0)/2 ) * (x[n] - x[n-2])
// + (beta * 2*cos(w0) ) * y[n-1]
// + (beta * (alpha - 1) ) * y[n-2]
// In addition, the input x-coefficients are scaled by the amplitude of the biquad --
// I use **twice** the amplitude value.
float alpha = fSin * bw / 2.0; // this is sin/(2*q)
float beta = 1.0 / (1.0 + alpha);
pC[0] = amp * beta * fSin; // x[n] coefficient, and -x[n-2] coefficient
pC[2] = beta * 2. * fCos; // y[n-1] coefficient
pC[4] = beta * (alpha - 1.0); // y[n-2] coefficient
}
else
{
// Frequency of bfb filter is beyond aliasing frequency,
// or if we are about to start a new note.
// Zero bfb filter coefficients and zero out the filter memory.
pC[0] = pC[2] = pC[4] = 0;
*y0 = *y1 = 0;
}
}double2cfloat.m - TMX Filter formatting for C compilers
% UPIITA IPN 2010
% José David Valencia Pesqueira
% This program is useful to convert numbers in MATLAB's Double
% format to a text file in float format for C compilers
% You should copy the resulting text to a file and save it with .h
% extension
% THIS PROGRAM RECEIVES AN UNIDIMENTIONAL VECTOR OF DOUBLE NUMBERS
% close all; clear all; clc;
function double2cfloat(x , namex, y, namey, sinc_factor)
[m,n] = size(x);
fprintf('// Begin of file\n\n');
fprintf('#define sinc %d // Sincronization factor\n',sinc_factor);
fprintf('#define N %d // Filter length\n',n);
if m~=0
fprintf('#define M %d // Number of filters(branches)\n\n',m);
fprintf('float %s[M][N]=',namex);
else
fprintf('float %s[N]=',namex);
end
disp('');
disp('{');
for i=0:m-1 %Rows
if m~=1
disp('{');
end
for j=0:n-1 %columns
fprintf('%1.4e,\n',x(i+1,j+1));
end
if m~=1
fprintf('},\n');
end
end
disp('};');
fprintf('\n\n');
if m~=0
fprintf('float %s[M][N]=',namey);
else
fprintf('float %s[N]=',namey);
end
disp('');
disp('{');
for i=0:m-1 %Rows
if m~=1
disp('{');
end
for j=0:n-1 %columns
fprintf('%1.4e,\n',y(i+1,j+1));
end
if m~=1
fprintf('},\n');
end
end
disp('};');
fprintf('\n// EOF\n\n');db2_2stages.h - TMX Filter data in C
// Beginning of file
#define sinc 3 // sincronization factor
#define N 11 // Filter length
#define M 4 // Number of filters(branches)
float h[M][N]={
{
0.0000e+000,
1.6747e-002,
2.9006e-002,
-7.9247e-002,
1.1274e-001,
-2.9575e-001,
-7.9247e-002,
7.6226e-001,
-2.9575e-001,
-4.0401e-001,
2.3325e-001,
},
{
0.0000e+000,
-6.2500e-002,
-1.0825e-001,
2.9575e-001,
-4.2075e-001,
6.7075e-001,
-4.5425e-001,
2.0425e-001,
-7.9247e-002,
-1.0825e-001,
6.2500e-002,
},
{
0.0000e+000,
-6.2500e-002,
-1.0825e-001,
-1.3726e-001,
-1.7075e-001,
3.5377e-001,
7.2877e-001,
-4.5753e-002,
-5.1226e-001,
-1.0825e-001,
6.2500e-002,
},
{
0.0000e+000,
2.3325e-001,
4.0401e-001,
5.1226e-001,
6.3726e-001,
2.9575e-001,
7.9247e-002,
-1.2260e-002,
-1.3726e-001,
-2.9006e-002,
1.6747e-002,
},
};
float g[M][N]={
{
0.0000e+000,
2.3325e-001,
-4.0401e-001,
-2.9575e-001,
7.6226e-001,
-7.9247e-002,
-2.9575e-001,
1.1274e-001,
-7.9247e-002,
2.9006e-002,
1.6747e-002,
},
{
0.0000e+000,
6.2500e-002,
-1.0825e-001,
-7.9247e-002,
2.0425e-001,
-4.5425e-001,
6.7075e-001,
-4.2075e-001,
2.9575e-001,
-1.0825e-001,
-6.2500e-002,
},
{
0.0000e+000,
6.2500e-002,
-1.0825e-001,
-5.1226e-001,
-4.5753e-002,
7.2877e-001,
3.5377e-001,
-1.7075e-001,
-1.3726e-001,
-1.0825e-001,
-6.2500e-002,
},
{
0.0000e+000,
1.6747e-002,
-2.9006e-002,
-1.3726e-001,
-1.2260e-002,
7.9247e-002,
2.9575e-001,
6.3726e-001,
5.1226e-001,
4.0401e-001,
2.3325e-001,
},
};
// EOFTMX formafiltrosdwpt.m - Integrated version
function [hx] = formafiltrosdwpt(n_stages,branch,h0,h1)
p = branch;
% Integrated version for DWPT/TMX filter generation
hx = 0;
hx(1) = 1;
switch n_stages
case 1
if mod(branch,2) ~= 0
hx = h0;
else
hx = h1;
end
case 2
switch branch
case 1
hx = conv(h0,upsample(h0,2));
case 2
hx = conv(h0,upsample(h1,2));
case 3
hx = conv(h1,upsample(h0,2));
case 4
hx = conv(h1,upsample(h1,2));
otherwise
beep;
fprintf('\nERROR');
end
otherwise
for i=0:n_stages-2
q = floor(p /(2^(n_stages-1-i)));
if (q == 1)
hx = conv(hx,upsample(h1,2^i));
else
hx = conv(hx,upsample(h0,2^i));
end
p = mod(p,2^(n_stages-1-i)); %For DWPT and TMX
end
t = mod(branch,2);
if(t == 1)
hx = conv(hx,upsample(h0,2^(n_stages-1)));
else
hx = conv(hx,upsample(h1,2^(n_stages-1)));
end
endDiscrete Fourier Tranform Matrix generation
function [D] = dft_mtx(n)
f = 2*%pi/n; // Angular increment.
w = (0:f:2*%pi-f/2).' *%i; //Column.
//disp(w)
x = 0:n-1; // Row.
D = exp(-w*x); // Exponent of outer product.
for i = 1:n
for j = 1:n
if((abs(real(D(i,j)))<0.0001)&(abs(imag(D(i,j)))<0.0001))
D(i,j)=0;
elseif(abs(real(D(i,j)))<0.0001)
D(i,j)= 0+%i*imag(D(i,j));
elseif(abs(imag(D(i,j)))<0.0001)
D(i,j)= real(D(i,j))+0;
end
end
end
endfunctionlinear convolution in scilab
//Program for Linear Convolution
clc;
clear all;
close ;
x = input('enter x seq');
h = input('enter h seq');
m = length(x);
n = length(h);
//Method : Using Direct Convolution Sum Formula
for i = 1:n+m-1
conv_sum = 0;
for j = 1:i
if (((i-j+1) <= n)&(j <= m))
conv_sum = conv_sum + x(j)*h(i-j+1);
end;
y(i) = conv_sum;
end;
end;
disp(y,'y=')CTFS coefficients of a periodic square waveform
//CTFS coefficients of a periodic square waveform
//x(t) = 1, |t|<T1, and 0, T1<|t|<T/2
clear;
close;
clc;
T =4;
T1 = T/4;
t = -T1:T1/100:T1;
Wo = 2*%pi/T;
xt =ones(1,length(t)); //Square Wave Generation
//Finding the Fourier Series Coefficients
for k =0:5
C(k+1,:) = exp(-sqrt(-1)*Wo*t.*k);
a(k+1) = xt*C(k+1,:)'/length(t);
if(abs(a(k+1))<=0.1)
a(k+1)=0;
end
end
a =a';
a_conj = real(a(:))-sqrt(-1)*imag(a(:));
ak = [a_conj($:-1:1)',a(2:$)];
k = 0:5;
k = [-k($:-1:1),k(2:$)];
Spectrum_ak = (1/2)*real(ak);
//Plotting the Continuous Time Signal
figure
a = gca();
a.y_location = "origin";
a.x_location = "origin";
a.data_bounds=[-2,0;2,2];
plot2d2(t,xt,5)
poly1 = a.children(1).children(1);
poly1.thickness = 3;
title('x(t)')
xlabel(' t')
//Plotting the Spectral coefficients of CT Signal
figure
a = gca();
a.y_location = "origin";
a.x_location = "origin";
plot2d3('gnn',k,Spectrum_ak,5)
poly1 = a.children(1).children(1);
poly1.thickness = 3;
title('abs(ak)')
xlabel(' k')
//Result
//Spectrum_ak =
//0.0633127 0. -0.1055559 0. 0.3167197 0.5 0.3167197 0. -0.1055559 0. 0.0633127Continuous Time Fourier Transform of a Square Waveform
// Continuous Time Fourier Transform and Frequency Response of a Square Waveform
// x(t)= A, from -T1 to T1
clear;
clc;
close;
// CTS Signal
A =1; //Amplitude
Dt = 0.005;
T1 = 4; //Time in seconds
t = -T1:Dt:T1;
for i = 1:length(t)
xt(i) = A;
end
//
// Continuous-time Fourier Transform
Wmax = 2*%pi*1; //Analog Frequency = 1Hz
K = 4;
k = 0:(K/1000):K;
W = k*Wmax/K;
xt = xt';
XW = xt* exp(-sqrt(-1)*t'*W) * Dt;
XW_Mag = real(XW);
W = [-mtlb_fliplr(W), W(2:1001)]; // Omega from -Wmax to Wmax
XW_Mag = [mtlb_fliplr(XW_Mag), XW_Mag(2:1001)];
//
subplot(2,1,1);
a = gca();
a.data_bounds=[-4,0;4,2];
a.y_location ="origin";
plot2d2(t,xt);
xlabel('t in msec.');
title('Continuous Time Signal x(t)')
subplot(2,1,2);
a = gca();
a.y_location ="origin";
a.x_location ="origin";
plot(W,XW_Mag);
xlabel('Frequency in Radians/Seconds');
title('Continuous-time Fourier Transform X(jW)')Goertzel Filterbank to the Implementation of a Nonuniform DFT
% VectorGoertzel Goertzel's Algorithm filter bank.
% Realization of the Goertzel's Algorithm to compute the Nonuniform DFT
% of a signal(a column vector named signalw) of length Nw with sampling
% frecuency fs at the desired frecuencies contained in vector f. The
% function returns the NDFT magnitude in a vector with the same length of f.
function xk=Gfilterbank(signalw,f,fs,Nw)
% Inititialization of the different variables
n=2;
signalw=signalw(1:Nw);
cost=cos(2*pi*f/fs);
sint=sin(2*pi*f/fs);
L=length(cost);
y1(1:L)=0;
y2(1:L)=0;
signalw=[0 0 signalw]; %Signal is delayed by two samples
% Goertzel Feedback Algorithm
while((n-2) < Nw)
n=n+1;
xnew(1:L)=signalw(n);
y=xnew+2*cost.*y1-y2;
y2=y1;
y1=y;
end
% Goertzel Forward Algorithm
rey=y1-y2.*cost;
imy=y2.*sint;
% Magnitude Calculation
xk=abs(rey+imy*j)';Discrete Fourier Transform
#include<iostream>
#include<iomanip>
#include<cmath>
using namespace std;
#define pi 3.14159265
// class complex
class complex
{
public:
//This class member function set the values of the class members real and imag
void setvals(double r, double i)
{
real=r;
imag=i;
}
//This function get the values (by reference) of the class members real and imag
void getvals(double &r, double &i)
{
r=real;
i=imag;
}
private:
/* The class members real and imag represents the real and imaginary parts
of a complex number, respectively.*/
double real;
double imag;
}; // end of class complex
//**********************************************************************************************
/* function dft receives two parameters x and N. x is the input sequence containing
the discrete-time samples and N is the number of DFT points. The complex type paramater
xk receives a sequence of N-points frequency samples (this is the DFT of the input sequence*/
void dft(double x[], int N, complex xk[])
{
double r,i;
for(int k=0;k<N;k++) //k is the index of the N-point frequency sequence
{
xk[k].setvals(0,0); //initialize the values of the counters to zero
for(int n=0;n<N;n++) //n is the index of the discrete-time sequence
{
xk[k].getvals(r,i); // get the values of real and imag
/*This is the computation of the real and imaginary parts of the DFT.
The class member function setvals is used to update the value of the accumulators
contaning the real and imaginary parts of the DFT samples*/
xk[k].setvals(r + x[n]*cos(2*pi*k/N*n),i + x[n]*sin(2*pi*k/N*n));
} //end inner for-loop
} //end outer for-loop
}//end dft function
//************************************************************************************************
//Declaration of the main() function
int main()
{
int size; // The number of DFT samples
double r,i; // r = real part of the DFT; i = imaginary part of the DFT
cout<<"Enter the desired number of DFT samples: ";
cin>>size;
double *x = new double[size]; //dynamic array x represent the discrete-time samples
complex *xk = new complex[size]; // dynamic array xk represent the DFT samples
cout<<"\nEnter the sequence x[n]: ";
for(int h=0;h<size;h++)
{
cin>>x[h];
}
//Computation of the DFT of x
dft(x, size, xk);
system("CLS"); //clear screen
cout<<"Discrete Fourier Transform: "<<endl<<endl;
for(int h=0;h<size;h++)
{
cout.precision(3); // display three (3) decimal places
xk[h].getvals(r,i); //get the DFT samples values
cout<<"xk["<<h<<"] = "<<fixed<< r <<" + "<<fixed<< i <<"j"<<endl; // print the DFT samples
}
cout<<endl;
return 0;
}// end main functionDiscrete Wavelet Transform - Chain processing (Linear Convolution)
% ----------------------------------------------------
% Title: Discrete Wavelet Transform
% Author: David Valencia
% UPIITA IPN 2010
%
% Posted in DSPrelated.com
% http://www.dsprelated.com/showcode/47.php
%
% Computes the Discrete Wavelet Transform of
% n levels (and its branches) from a n sample input.
% Base filters can be of any lenght.
%
% Generalized DWT filter bank computed via the
% chain processing method (linear convolution)
%
% Dependencies:
% formfilters.m - http://www.dsprelated.com/showcode/44.php
% formfiltersdwt.m - http://www.dsprelated.com/showcode/45.php
% upsample2.m - http://www.dsprelated.com/showcode/10.php
% recorreder.m - http://www.dsprelated.com/showcode/43.php
% getsincdwt.m - http://www.dsprelated.com/showcode/46.php
%
% Revisions:
% v1.0a Commented and translated in English
% ----------------------------------------------------
close all; clear all; clc;
% ######################################
disp('== CHAIN PROCESSING DWT ==')
% Filter parameters
typeofbasis = 'o';
typbior = 'bior2.2';
typor = 'db2';
if(typeofbasis == 'b')
[Rf,Df] = biorwavf(typbior);
[h0,h1,g0,g1] = biorfilt(Df,Rf);
elseif (typeofbasis == 'o')
[h0,h1,g0,g1] = wfilters(typor);
end;
% Input values, change as needed
N = 16;
x = (1:N);
L = length(h0);
figure(1);
subplot(2,1,1);
stem(x);
xlabel('Original signal');
% Filter bank parameters, change as needed
n_stages = 3; %Of the low-pass part
% Checked for the minimal case: DWT = DWPT n_stages = 1
n_branches = n_stages + 1; %Of the low-pass part
niter = 300; %Number of iterations
% Define input buffer dimensions
hx = formfilters(n_stages, 1, h0, h1);
lhx = length(hx);
% Input buffer vector
inputbuffer = zeros(lhx,1);
% Synthesis input buffer
sbuffer = zeros(n_branches,lhx);
% This vector will store the length of each branch filter
Lfiltros = zeros(n_branches, 1);
% This vector will store the decimate factor for each branch
dec_factors = zeros(n_branches, 1);
% This vector will store the synchronization factor for each branch
sinc_factors = zeros(n_branches, 1);
% Cycle to get the synchronization factors
for j = 0:n_branches-1
try
sinc_factors(j+1) = getsincdwt(n_stages, j+1, L);
catch error
disp('ERROR: Error, experimentation is needed for this case');
disp('The results may not be correct');
% return;
end
end
%% Filter matrices formation
% This matrix will store each of the branch filters as vectors
H = zeros(n_branches, lhx); %Malloc
G = zeros(n_branches, lhx); %Malloc
for i = 0:n_stages
if i >= n_stages-1
dec_factors(i+1) = 2^n_stages;
else
dec_factors(i+1) = 2^(i+1);
end
hx = fliplr(formfiltersdwt(n_stages,n_stages+1-i,h0,h1));
gx = fliplr(formfiltersdwt(n_stages,n_stages+1-i,g0,g1));
lhx = length(hx);
lgx = length(gx);
Lfiltros(i+1) = lhx;
H(i+1,1:lhx) = hx;
G(i+1,1:lhx) = gx;
end
% Debug code
disp('Dimensiones de los filtros')
Lfiltros
disp('Factores de diezmado')
dec_factors
disp('Matriz de filtros análisis: ');
H
disp('Matriz de filtros síntesis: ');
G
chanbufftestigo = zeros(n_branches,1);
outputbuffer = zeros(1,niter);
%% MAIN CYCLE
for i = 1:niter %General FOR (for iterations)
i % Print iteration number
% Shifting of input buffer (sequentially)
inputbuffer = recorreder(inputbuffer,1);
if i<=N
inputbuffer(1)=x(i);
else
inputbuffer(1)=0;
end
inputbuffer %Print buffer (debug)
%% Analyisis stage (h0 and h1)
% The following cycle will select each of the branches for processing
% If the iteration counter is a multiply of the decimation factor,
% the convolution is calculated, otherwise, zeros are sent to the
% channel
y = zeros(n_branches,1); %Clear the output buffer
for j = 0:n_branches-1
fprintf('\nBranch: %d, Decimating factor: %d\n',j+1,dec_factors(j+1));
fprintf('\nFilter length: %d\n',Lfiltros(j+1));
if mod(i,dec_factors(j+1)) == 1
fprintf('i = %d is a multiply of the factor: %d\n',i,dec_factors(j+1));
tempfilt = H(j+1,1:Lfiltros(j+1));
% If the current iteration (clock cycle) is a multiply of the
% factor, the convolution is computed
for k=1:Lfiltros(j+1) %convolution
y(j+1,1) = y(j+1,1) + inputbuffer(k)*tempfilt(k);
end;
end
disp('Results in the channel');
chanbuff(:,1) = y %Debug printing
end
%% Synthesis stage (g0 and g1)
% Shifting and interpolation of the synthesis buffer
for j = 1:n_branches
sbuffer(j,:) = recorreder(sbuffer(j,:),1);
% Interpolation of the synthesis stage inputs
if mod(i,dec_factors(j)) == 1
fprintf('Inserting sample to the synthesis branch %d with dec_factor %d\n',j,dec_factors(j));
sbuffer(j,1) = chanbuff(j,1);
else
fprintf('Inserting a zero to the synthesis branch %d with dec_factor %d\n',j,dec_factors(j));
sbuffer(j,1) = 0;
end
end
disp('Synthesis buffer matrix');
sbuffer
xnbuff = zeros(n_branches,1);
for j=0:n_branches-1
fprintf('Branch: %d , dec_factor = %d',j+1,dec_factors(j+1));
% === BRANCH SYNCHRONIZATION ===
% The branches (except the two last ones down the bank filter)
% will only take a part of the vector that corresponds with their
% channel, taking 'Lx' elements, being Lx the number of coefficient
% that their filter has. An offset is applied
if j < n_branches - 2
[m,n] = size(sbuffer);
tempsinth = sbuffer(j+1,n-Lfiltros(j+1)+1:n) %TESTING
else % The lowest branches take the whole vector
tempsinth = sbuffer(j+1,1+sinc_factors(j+1):Lfiltros(j+1)+sinc_factors(j+1))
end
for k = 1 : Lfiltros(j+1) %Convolution
xnbuff(j+1,1) = xnbuff(j+1,1) + tempsinth(k)*G(j+1,k);
end
end
xnbuff
outputbuffer(i) = sum(xnbuff);
disp('Output buffer: ');
if i > N
disp(outputbuffer(1,i-N+1:i))
figure(1);
subplot(2,1,2);
stem(outputbuffer(1,i-N+1:i));
xlabel('Recovered signal');
else
disp(outputbuffer(1,1:N))
figure(1);
subplot(2,1,2);
stem(outputbuffer(1,1:N));
xlabel('Recovered signal');
end
pause;
end
% END OF PROGRAM >>>getsincdwt.m - Get DWT synchronization for chain-processing
% UPIITA IPN 2010
% Valencia Pesqueira José David
% Function used to obtain the synchronization factor for each
% branch in the DWT chain-processing program
function [x] = getsincdwt(n_etapas, rama, Lfiltrobase)
switch(n_etapas)
case 1 %One stage, two-branches. DWPT equivalent
x = 0;
case 2 %2 stages, 3 branches
switch(rama)
case 1 % High-pass branch
x = (Lfiltrobase-1)*2;
otherwise
x = 0;
end
case 3 %3 branches, 4 stages
switch(rama)
case 1 % High-pass branch
x = (Lfiltrobase-1)*2;
case 2
x = 10;
otherwise
x = 0;
end
end
% Experimental ANALISIS
% 2 etapas
% lfiltro - sinc_factor experimental
%
% 4 - 6 (4-1)*2 = 6
% 6 - 10 (6-1)*2 = 10
% 8 - 14 (8-1)*2 = 7formfiltersdwt.m DWT filter generator adaptor
% By David Valencia
% As posted in DSPRelated.com
% at http://www.dsprelated.com/showcode/45.php
% Used for the DWT chain processing program
function [hx] = formfiltersdwt(n_stages,branch,h0,h1)
if(branch==1)
hx=formfilters(n_stages,branch,h0,h1);
elseif(branch==2)
hx=formfilters(n_stages,2,h0,h1);
else
hx=formfilters(n_stages-branch+2,2,h0,h1);
end
% The code line that is changed in formfilters.m for DWT is:
%p = mod(2^(n_stages-1-i),p);DWT filter generator - formfilters.m (for chain processing)
% Created by José David Valencia Pesqueira
% UPIITA-IPN 2010
% For the DWT chain-processing example
% as posted in DSPrelated.com
% http://www.dsprelated.com/showcode/44.php
%
function [hx] = formfilters(n_stages,branch,h0,h1)
p = branch;
% Seed vector
hx = 0;
hx(1) = 1;
switch n_stages
case 1
if mod(branch,2) ~= 0
hx = h0;
else
hx = h1;
end
case 2
switch branch
case 1
hx = conv(h0,upsample2(h0,2));
case 2
hx = conv(h0,upsample2(h1,2));
case 3
hx = conv(h1,upsample2(h0,2));
case 4
hx = conv(h1,upsample2(h1,2));
otherwise
beep;
fprintf('\nFor a 2-stage bank there cannot be a fifth branch');
end
otherwise
for i=0:n_stages-2
q = floor(p /(2^(n_stages-1-i)));
if (q == 1)
hx = conv(hx,upsample2(h1,2^i));
else
hx = conv(hx,upsample2(h0,2^i));
end
% p = mod(p,2^(n_stages-1-i)); %For DWPT
p = mod(2^(n_stages-1-i),p); %For DWT
end
t = mod(branch,2);
if(t == 1)
hx = conv(hx,upsample2(h0,2^(n_stages-1)));
else
hx = conv(hx,upsample2(h1,2^(n_stages-1)));
end
endrecorreder.m - Vector shifting made simple
function [xd] = recorreder(x,N)
% This function shifts a vector by N positions to the right
% As posted in DSPrelated.com
% http://www.dsprelated.com/showcode/43.php
%
lx = length(x);
if N>lx
fprintf('N has to be smaller than the vector length');
return;
else
xd(N+1:lx) = x(1:lx-N);
end;Fixed Point FIR Filter
#include <stdio.h>
#include <stdint.h>
//////////////////////////////////////////////////////////////
// Filter Code Definitions
//////////////////////////////////////////////////////////////
// maximum number of inputs that can be handled
// in one function call
#define MAX_INPUT_LEN 80
// maximum length of filter than can be handled
#define MAX_FLT_LEN 63
// buffer to hold all of the input samples
#define BUFFER_LEN (MAX_FLT_LEN - 1 + MAX_INPUT_LEN)
// array to hold input samples
static int16_t insamp[ BUFFER_LEN ];
// FIR init
void firFixedInit( void )
{
memset( insamp, 0, sizeof( insamp ) );
}
// store new input samples
int16_t *firStoreNewSamples( int16_t *inp, int length )
{
// put the new samples at the high end of the buffer
memcpy( &insamp[MAX_FLT_LEN - 1], inp,
length * sizeof(int16_t) );
// return the location at which to apply the filtering
return &insamp[MAX_FLT_LEN - 1];
}
// move processed samples
void firMoveProcSamples( int length )
{
// shift input samples back in time for next time
memmove( &insamp[0], &insamp[length],
(MAX_FLT_LEN - 1) * sizeof(int16_t) );
}
// the FIR filter function
void firFixed( int16_t *coeffs, int16_t *input, int16_t *output,
int length, int filterLength )
{
int32_t acc; // accumulator for MACs
int16_t *coeffp; // pointer to coefficients
int16_t *inputp; // pointer to input samples
int n;
int k;
// apply the filter to each input sample
for ( n = 0; n < length; n++ ) {
// calculate output n
coeffp = coeffs;
inputp = &input[n];
// load rounding constant
acc = 1 << 14;
// perform the multiply-accumulate
for ( k = 0; k < filterLength; k++ ) {
acc += (int32_t)(*coeffp++) * (int32_t)(*inputp--);
}
// saturate the result
if ( acc > 0x3fffffff ) {
acc = 0x3fffffff;
} else if ( acc < -0x40000000 ) {
acc = -0x40000000;
}
// convert from Q30 to Q15
output[n] = (int16_t)(acc >> 15);
}
}
//////////////////////////////////////////////////////////////
// Test program
//////////////////////////////////////////////////////////////
// bandpass filter centred around 1000 Hz
// sampling rate = 8000 Hz
// gain at 1000 Hz is about 1.13
#define FILTER_LEN 63
int16_t coeffs[ FILTER_LEN ] =
{
-1468, 1058, 594, 287, 186, 284, 485, 613,
495, 90, -435, -762, -615, 21, 821, 1269,
982, 9, -1132, -1721, -1296, 1, 1445, 2136,
1570, 0, -1666, -2413, -1735, -2, 1770, 2512,
1770, -2, -1735, -2413, -1666, 0, 1570, 2136,
1445, 1, -1296, -1721, -1132, 9, 982, 1269,
821, 21, -615, -762, -435, 90, 495, 613,
485, 284, 186, 287, 594, 1058, -1468
};
// Moving average (lowpass) filter of length 8
// There is a null in the spectrum at 1000 Hz
#define FILTER_LEN_MA 8
int16_t coeffsMa[ FILTER_LEN_MA ] =
{
32768/8, 32768/8, 32768/8, 32768/8,
32768/8, 32768/8, 32768/8, 32768/8
};
// number of samples to read per loop
#define SAMPLES 80
int main( void )
{
int size;
int16_t input[SAMPLES];
int16_t output[SAMPLES];
int16_t *inp;
FILE *in_fid;
FILE *out_fid;
FILE *out_fid2;
// open the input waveform file
in_fid = fopen( "input.pcm", "rb" );
if ( in_fid == 0 ) {
printf("couldn't open input.pcm");
return;
}
// open the output waveform files
out_fid = fopen( "outputFixed.pcm", "wb" );
if ( out_fid == 0 ) {
printf("couldn't open outputFixed.pcm");
return;
}
out_fid2 = fopen( "outputFixedMa.pcm", "wb" );
if ( out_fid == 0 ) {
printf("couldn't open outputFixedMa.pcm");
return;
}
// initialize the filter
firFixedInit();
// process all of the samples
do {
// read samples from file
size = fread( input, sizeof(int16_t), SAMPLES, in_fid );
// store new samples in working array
inp = firStoreNewSamples( input, size );
// apply each filter
firFixed( coeffs, inp, output, size, FILTER_LEN );
fwrite( output, sizeof(int16_t), size, out_fid );
firFixed( coeffsMa, inp, output, size, FILTER_LEN_MA );
fwrite( output, sizeof(int16_t), size, out_fid2 );
// move processed samples
firMoveProcSamples( size );
} while ( size != 0 );
fclose( in_fid );
fclose( out_fid );
fclose( out_fid2 );
return 0;
}Echo Filter
% function echo_filter:
% 1) computes and returns the impulse response h of the LTI system (echo filter)
% 2) Filter the input signal. The output signal is yecho.
%
% INPUTS:
% signal = input signal
% times = vector containing the time delays (in seconds) of the repetitions(echoes)
% attenuations = vector containing the respective attenuations of the echoes
% fs = sampling frequency of the input signal.
%
% OUTPUTS:
% yecho = output signal (passed through the echo filter)
% h = impulse response of the echo filter.
function [yecho, h] = echo_filter(signal, times, attenuations, fs)
h(1)=1; % This is the first coefficient of the echo filter
% Computing the impulse response h
for i=1:length(times),
samples(i) = times(i)*fs; % Calculating the sample-times (N = t*fs)
h(floor(samples(i))) = attenuations(i); % Impulse response coeficients
end
% #########################################################################
% You may use the following implementation instead of the illustrated
% above:
% samples = times*fs;
% h(floor(samples)) = attenuations;
% In this case, the implementation is done without a for-loop.
% #########################################################################
yecho = filter(h,1,signal(:,1)); % filtering of the input signal results in a signal with echoes
% You may test the filter using the Matlab signal "splat" (write load splat
% in the Matlab command window). Use function sound() in order to
% listening both, the input and the output, signals.Fixed-point Math Library
/* **********************************************************************
*
* Fixed Point Math Library
*
* **********************************************************************
*
* qmath.h
*
* Alex Forencich
* alex@alexelectronics.com
*
* Jordan Rhee
* rhee.jordan@gmail.com
*
* IEEE UCSD
* http://ieee.ucsd.edu
*
* **********************************************************************/
#ifndef _QMATH_H_
#define _QMATH_H_
#ifdef __cplusplus
extern "C" {
#endif
#ifndef INLINE
#ifdef _MSC_VER
#define INLINE __inline
#else
#define INLINE inline
#endif /* _MSC_VER */
#endif /* INLINE */
/*
* Default fractional bits. This precision is used in the routines
* and macros without a leading underscore.
* For example, if you are mostly working with values that come from
* a 10-bit A/D converter, you may want to choose 21. This leaves 11
* bits for the whole part, which will help avoid overflow in addition.
* On ARM, bit shifts require a single cycle, so all fracbits
* require the same amount of time to compute and there is no advantage
* to selecting fracbits that are a multiple of 8.
*/
#define FIXED_FRACBITS 24
#define FIXED_RESOLUTION (1 << FIXED_FRACBITS)
#define FIXED_INT_MASK (0xffffffffL << FIXED_FRACBITS)
#define FIXED_FRAC_MASK (~FIXED_INT_MASK)
// square roots
#define FIXED_SQRT_ERR 1 << (FIXED_FRACBITS - 10)
// fixedp2a
#define FIXED_DECIMALDIGITS 6
typedef long fixedp;
// conversions for arbitrary fracbits
#define _short2q(x, fb) ((fixedp)((x) << (fb)))
#define _int2q(x, fb) ((fixedp)((x) << (fb)))
#define _long2q(x, fb) ((fixedp)((x) << (fb)))
#define _float2q(x, fb) ((fixedp)((x) * (1 << (fb))))
#define _double2q(x, fb) ((fixedp)((x) * (1 << (fb))))
// conversions for default fracbits
#define short2q(x) _short2q(x, FIXED_FRACBITS)
#define int2q(x) _int2q(x, FIXED_FRACBITS)
#define long2q(x) _long2q(x, FIXED_FRACBITS)
#define float2q(x) _float2q(x, FIXED_FRACBITS)
#define double2q(x) _double2q(x, FIXED_FRACBITS)
// conversions for arbitrary fracbits
#define _q2short(x, fb) ((short)((x) >> (fb)))
#define _q2int(x, fb) ((int)((x) >> (fb)))
#define _q2long(x, fb) ((long)((x) >> (fb)))
#define _q2float(x, fb) ((float)(x) / (1 << (fb)))
#define _q2double(x, fb) ((double)(x) / (1 << (fb)))
// conversions for default fracbits
#define q2short(x) _q2short(x, FIXED_FRACBITS)
#define q2int(x) _q2int(x, FIXED_FRACBITS)
#define q2long(x) _q2long(x, FIXED_FRACBITS)
#define q2float(x) _q2float(x, FIXED_FRACBITS)
#define q2double(x) _q2double(x, FIXED_FRACBITS)
// evaluates to the whole (integer) part of x
#define qipart(x) q2long(x)
// evaluates to the fractional part of x
#define qfpart(x) ((x) & FIXED_FRAC_MASK)
/*
* Constants
*/
#define _QPI 3.1415926535897932384626433832795
#define QPI double2q(_QPI)
#define _Q2PI 6.283185307179586476925286766559
#define Q2PI double2q(_Q2PI)
#define _QPIO2 1.5707963267948966192313216916398
#define QPIO2 double2q(_QPIO2)
#define _QPIO4 0.78539816339744830961566084581988
#define QPIO4 double2q(_QPIO4)
#define _QLN_E 2.71828182845904523536
#define QLN_E double2q(_QLN_E)
#define _QLN_10 2.30258509299404568402
#define QLN_10 double2q(_QLN_10)
#define _Q1OLN_10 0.43429448190325182765
#define Q1OLN_10 double2q(_Q1OLN_10)
// Both operands in addition and subtraction must have the same fracbits.
// If you need to add or subtract fixed point numbers with different
// fracbits, then use q2q to convert each operand beforehand.
#define qadd(a, b) ((a) + (b))
#define qsub(a, b) ((a) - (b))
/**
* q2q - convert one fixed point type to another
* x - the fixed point number to convert
* xFb - source fracbits
* yFb - destination fracbits
*/
static INLINE fixedp q2q(fixedp x, int xFb, int yFb)
{
if(xFb == yFb) {
return x;
} else if(xFb < yFb) {
return x << (yFb - xFb);
} else {
return x >> (xFb - yFb);
}
}
/**
* Multiply two fixed point numbers with arbitrary fracbits
* x - left operand
* y - right operand
* xFb - number of fracbits for X
* yFb - number of fracbits for Y
* resFb - number of fracbits for the result
*
*/
#define _qmul(x, y, xFb, yFb, resFb) ((fixedp)(((long long)(x) * (long long)(y)) >> ((xFb) + (yFb) - (resFb))))
/**
* Fixed point multiply for default fracbits.
*/
#define qmul(x, y) _qmul(x, y, FIXED_FRACBITS, FIXED_FRACBITS, FIXED_FRACBITS)
/**
* divide
* shift into 64 bits and divide, then truncate
*/
#define _qdiv(x, y, xFb, yFb, resFb) ((fixedp)((((long long)x) << ((xFb) + (yFb) - (resFb))) / y))
/**
* Fixed point divide for default fracbbits.
*/
#define qdiv(x, y) _qdiv(x, y, FIXED_FRACBITS, FIXED_FRACBITS, FIXED_FRACBITS)
/**
* Invert a number (x^-1) for arbitrary fracbits
*/
#define _qinv(x, xFb, resFb) ((fixedp)((((long long)1) << (xFb + resFb)) / x))
/**
* Invert a number with default fracbits.
*/
#define qinv(x) _qinv(x, FIXED_FRACBITS, FIXED_FRACBITS);
/**
* Modulus. Modulus is only defined for two numbers of the same fracbits
*/
#define qmod(x, y) ((x) % (y))
/**
* Absolute value. Works for any fracbits.
*/
#define qabs(x) (((x) < 0) ? (-x) : (x))
/**
* Floor for arbitrary fracbits
*/
#define _qfloor(x, fb) ((x) & (0xffffffff << (fb)))
/**
* Floor for default fracbits
*/
#define qfloor(x) _qfloor(x, FIXED_FRACBITS)
/**
* ceil for arbitrary fracbits.
*/
static INLINE fixedp _qceil(fixedp x, int fb)
{
// masks off fraction bits and adds one if there were some fractional bits
fixedp f = _qfloor(x, fb);
if (f != x) return qadd(f, _int2q(1, fb));
return x;
}
/**
* ceil for default fracbits
*/
#define qceil(x) _qceil(x, FIXED_FRACBITS)
/**
* square root for default fracbits
*/
fixedp qsqrt(fixedp p_Square);
/**
* log (base e) for default fracbits
*/
fixedp qlog( fixedp p_Base );
/**
* log base 10 for default fracbits
*/
fixedp qlog10( fixedp p_Base );
/**
* exp (e to the x) for default fracbits
*/
fixedp qexp(fixedp p_Base);
/**
* pow for default fracbits
*/
fixedp qpow( fixedp p_Base, fixedp p_Power );
/**
* sine for default fracbits
*/
fixedp qsin(fixedp theta);
/**
* cosine for default fracbits
*/
fixedp qcos(fixedp theta);
/**
* tangent for default fracbits
*/
fixedp qtan(fixedp theta);
/**
* fixedp2a - converts a fixed point number with default fracbits to a string
*/
char *q2a(char *buf, fixedp n);
#ifdef __cplusplus
} // extern C
#endif
#endif /* _QMATH_H_ */
/* **********************************************************************
*
* Fixed Point Math Library
*
* **********************************************************************
*
* qmath.c
*
* Alex Forencich
* alex@alexelectronics.com
*
* Jordan Rhee
* rhee.jordan@gmail.com
*
* IEEE UCSD
* http://ieee.ucsd.edu
*
* **********************************************************************/
#include "qmath.h"
/**
* square root
*/
fixedp qsqrt(fixedp p_Square)
{
fixedp res;
fixedp delta;
fixedp maxError;
if ( p_Square <= 0 )
return 0;
/* start at half */
res = (p_Square >> 1);
/* determine allowable error */
maxError = qmul(p_Square, FIXED_SQRT_ERR);
do
{
delta = (qmul( res, res ) - p_Square);
res -= qdiv(delta, ( res << 1 ));
}
while ( delta > maxError || delta < -maxError );
return res;
}
/**
* log (base e)
*/
fixedp qlog( fixedp p_Base )
{
fixedp w = 0;
fixedp y = 0;
fixedp z = 0;
fixedp num = int2q(1);
fixedp dec = 0;
if ( p_Base == int2q(1) )
return 0;
if ( p_Base == 0 )
return 0xffffffff;
for ( dec=0 ; qabs( p_Base ) >= int2q(2) ; dec += int2q(1) )
p_Base = qdiv(p_Base, QLN_E);
p_Base -= int2q(1);
z = p_Base;
y = p_Base;
w = int2q(1);
while ( y != y + w )
{
z = 0 - qmul( z , p_Base );
num += int2q(1);
w = qdiv( z , num );
y += w;
}
return y + dec;
}
/**
* log base 10
*/
fixedp qlog10( fixedp p_Base )
{
// ln(p_Base)/ln(10)
// more accurately, ln(p_Base) * (1/ln(10))
return qmul(qlog(p_Base), Q1OLN_10);
}
/**
* exp (e to the x)
*/
fixedp qexp(fixedp p_Base)
{
fixedp w;
fixedp y;
fixedp num;
for ( w=int2q(1), y=int2q(1), num=int2q(1) ; y != y+w ; num += int2q(1) )
{
w = qmul(w, qdiv(p_Base, num));
y += w;
}
return y;
}
/**
* pow
*/
fixedp qpow( fixedp p_Base, fixedp p_Power )
{
if ( p_Base < 0 && qmod(p_Power, int2q(2)) != 0 )
return - qexp( qmul(p_Power, qlog( -p_Base )) );
else
return qexp( qmul(p_Power, qlog(qabs( p_Base ))) );
}
/**
* sinx, internal sine function
*/
static fixedp sinx(fixedp x)
{
fixedp xpwr;
long xftl;
fixedp xresult;
short positive;
int i;
xresult = 0;
xpwr = x;
xftl = 1;
positive = -1;
// Note: 12! largest for long
for (i = 1; i < 7; i+=2)
{
if ( positive )
xresult += qdiv(xpwr, long2q(xftl));
else
xresult -= qdiv(xpwr, long2q(xftl));
xpwr = qmul(x, xpwr);
xpwr = qmul(x, xpwr);
xftl *= i+1;
xftl *= i+2;
positive = !positive;
}
return xresult;
}
/**
* sine
*/
fixedp qsin(fixedp theta)
{
fixedp xresult;
short bBottom = 0;
//static fixed xPI = XPI;
//static fixed x2PI = X2PI;
//static fixed xPIO2 = XPIO2;
fixedp x = qmod(theta, Q2PI);
if ( x < 0 )
x += Q2PI;
if ( x > QPI )
{
bBottom = -1;
x -= QPI;
}
if ( x <= QPIO2 )
xresult = sinx(x);
else
xresult = sinx(QPIO2-(x-QPIO2));
if ( bBottom )
return -xresult;
return xresult;
}
/**
* cosine
*/
fixedp qcos(fixedp theta)
{
return qsin(theta + QPIO2);
}
/**
* tangent
*/
fixedp qtan(fixedp theta)
{
return qdiv(qsin(theta), qcos(theta));
}
/**
* q2a - converts a fixed point number to a string
*/
char *q2a(char *buf, fixedp n)
{
long ipart = qipart(n);
long fpart = qfpart(n);
long intdigits = 0;
int i = 0;
int j = 0;
int d = 0;
int offset = 0;
long v;
long t;
long st = 0;
if (n != 0)
{
intdigits = qipart(qceil(qlog10(qabs(n))));
}
if (intdigits < 1) intdigits = 1;
offset = intdigits - 1;
if (n < 0)
{
buf[0] = '-';
offset++;
n = -n;
ipart = -ipart;
fpart = -fpart;
}
// integer portion
for (i = 0; i < intdigits; i++)
{
j = offset - i;
d = ipart % 10;
ipart = ipart / 10;
buf[j] = '0' + d;
}
// decimal point
buf[offset + 1] = '.';
// fractional portion
v = 5;
t = FIXED_RESOLUTION >> 1;
for (i = 0; i < FIXED_DECIMALDIGITS - 1; i++)
{
v = (v << 1) + (v << 3);
}
for (i = 0; i < FIXED_FRACBITS; i++)
{
if (fpart & t)
{
st += v;
}
v = v >> 1;
t = t >> 1;
}
offset += FIXED_DECIMALDIGITS + 1;
for (i = 0; i < FIXED_DECIMALDIGITS; i++)
{
j = offset - i;
d = st % 10;
st = st / 10;
buf[j] = '0' + d;
}
// ending zero
buf[offset + 1] = '\0';
return buf;
}






