dawn@0
|
1 /*
|
dawn@0
|
2 * rsmooth.c
|
dawn@0
|
3 * smooth columnwise by convolution by a running square window
|
dawn@0
|
4 * multiple passes allowed (--> triangular, gaussian, etc.)
|
dawn@0
|
5 *
|
dawn@0
|
6 * Alain de Cheveigné, CNRS Ircam, Dec 2001.
|
dawn@0
|
7 * (c) CNRS 2001.
|
dawn@0
|
8 */
|
dawn@0
|
9
|
dawn@0
|
10 #include <math.h>
|
dawn@0
|
11 #include "mex.h"
|
dawn@0
|
12
|
dawn@0
|
13 /* #define MWRAP */
|
dawn@0
|
14 #include "mwrap_check.h"
|
dawn@0
|
15
|
dawn@0
|
16 /* Input Arguments */
|
dawn@0
|
17
|
dawn@0
|
18 #define X_IN prhs[0]
|
dawn@0
|
19 #define SMOOTH_IN prhs[1]
|
dawn@0
|
20 #define NPASSES_IN prhs[2]
|
dawn@0
|
21 #define CLIP_IN prhs[3]
|
dawn@0
|
22
|
dawn@0
|
23 /* Output Arguments */
|
dawn@0
|
24
|
dawn@0
|
25 #define Y_OUT plhs[0]
|
dawn@0
|
26
|
dawn@0
|
27 static void rsmooth(
|
dawn@0
|
28 double *xp,
|
dawn@0
|
29 int smooth,
|
dawn@0
|
30 int npasses,
|
dawn@0
|
31 double *yp,
|
dawn@0
|
32 int m,
|
dawn@0
|
33 int n,
|
dawn@0
|
34 int clip
|
dawn@0
|
35 )
|
dawn@0
|
36 {
|
dawn@0
|
37 int h,i,j,k,mm;
|
dawn@0
|
38 double *work1, *work2, *a, *b, *tmp, sum;
|
dawn@0
|
39
|
dawn@0
|
40 mm = m + smooth + npasses*(smooth-1); /* nrows of work buffer */
|
dawn@0
|
41 work1 = (double *) mxCalloc(mm*n,sizeof(double));
|
dawn@0
|
42 work2 = (double *) mxCalloc(mm*n,sizeof(double));
|
dawn@0
|
43
|
dawn@0
|
44 CHECKIN(work1, (char *) work1 + sizeof(double)*mm*n);
|
dawn@0
|
45 CHECKIN(work2, (char *) work2 + sizeof(double)*mm*n);
|
dawn@0
|
46
|
dawn@0
|
47 a = work1;
|
dawn@0
|
48 b = work2;
|
dawn@0
|
49
|
dawn@0
|
50 /* transfer data to buffer, preceded with leading zeros */
|
dawn@0
|
51 for (k=0; k<n; k++) {
|
dawn@0
|
52 for (j=0;j<m;j++) {
|
dawn@0
|
53 SET(a[ j+smooth+mm*k ]) = GET(xp[ j+m*k ]);
|
dawn@0
|
54 }
|
dawn@0
|
55 }
|
dawn@0
|
56
|
dawn@0
|
57 /* smooth repeatedly */
|
dawn@0
|
58 for (h=0;h<npasses;h++) {
|
dawn@0
|
59 for (k=0; k<n; k++) { /* for each column */
|
dawn@0
|
60 sum=0;
|
dawn@0
|
61 for (j=smooth;j<mm;j++) { /* for each row (inner loop) */
|
dawn@0
|
62 sum += - GET(a[j-smooth+mm*k]) + GET(a[j+mm*k]);
|
dawn@0
|
63 SET(b[j+mm*k]) = sum/smooth;
|
dawn@0
|
64 }
|
dawn@0
|
65 }
|
dawn@0
|
66 tmp=a; a=b; b=tmp; /* swap for next round */
|
dawn@0
|
67 }
|
dawn@0
|
68
|
dawn@0
|
69 /* transfer to output matrix */
|
dawn@0
|
70 if (clip) {
|
dawn@0
|
71 for (j=0;j<m;j++) {
|
dawn@0
|
72 for (k=0; k<n; k++) {
|
dawn@0
|
73 SET(yp[j+m*k]) = GET(a[ j+(int)(npasses*(smooth-1)/2)+smooth + mm*k]);
|
dawn@0
|
74 }
|
dawn@0
|
75 }
|
dawn@0
|
76 } else {
|
dawn@0
|
77 for (j=0;j<m+npasses*(smooth-1);j++) {
|
dawn@0
|
78 for (k=0; k<n; k++) {
|
dawn@0
|
79 SET(yp[j+(m+npasses*(smooth-1))*k]) = GET(a[j + smooth + mm*k]);
|
dawn@0
|
80 }
|
dawn@0
|
81 }
|
dawn@0
|
82 }
|
dawn@0
|
83 CHECKOUT(work1);
|
dawn@0
|
84 CHECKOUT(work2);
|
dawn@0
|
85
|
dawn@0
|
86 }
|
dawn@0
|
87
|
dawn@0
|
88 void mexFunction(
|
dawn@0
|
89 int nlhs, mxArray *plhs[],
|
dawn@0
|
90 int nrhs, const mxArray *prhs[]
|
dawn@0
|
91 )
|
dawn@0
|
92 {
|
dawn@0
|
93 double *xp, *yp;
|
dawn@0
|
94 int m,n,npasses,smooth,clip;
|
dawn@0
|
95
|
dawn@0
|
96 /* Check for proper number of arguments */
|
dawn@0
|
97 if (nrhs > 4 || nrhs < 2) {
|
dawn@0
|
98 mexErrMsgTxt("RSMOOTH takes at least 2 and most 4 input arguments");
|
dawn@0
|
99 } else if (nlhs > 1) {
|
dawn@0
|
100 mexErrMsgTxt("RSMOOTH allows at most 1 output argument");
|
dawn@0
|
101 }
|
dawn@0
|
102
|
dawn@0
|
103 /* Check type of input */
|
dawn@0
|
104 m = mxGetM(X_IN); /* rows */
|
dawn@0
|
105 n = mxGetN(X_IN); /* columns */
|
dawn@0
|
106 if (!mxIsNumeric(X_IN) || mxIsComplex(X_IN) ||
|
dawn@0
|
107 mxIsSparse(X_IN) || !mxIsDouble(X_IN) || m<=1) {
|
dawn@0
|
108 mexErrMsgTxt("RSMOOTH: X should be a column vector or matrix of doubles");
|
dawn@0
|
109 }
|
dawn@0
|
110
|
dawn@0
|
111 if (mxGetM(SMOOTH_IN)*mxGetN(SMOOTH_IN) > 1 || mxGetPr(SMOOTH_IN)[0] <1) {
|
dawn@0
|
112 mexErrMsgTxt("RSMOOTH: SMOOTH should be a positive scalar");
|
dawn@0
|
113 }
|
dawn@0
|
114 smooth = mxGetPr(SMOOTH_IN)[0];
|
dawn@0
|
115
|
dawn@0
|
116 if (nrhs > 2) {
|
dawn@0
|
117 npasses = mxGetPr(NPASSES_IN)[0];
|
dawn@0
|
118 if (mxGetM(NPASSES_IN)*mxGetN(NPASSES_IN) > 1 || npasses <1) {
|
dawn@0
|
119 mexErrMsgTxt("RSMOOTH: NPASSES should be a positive scalar");
|
dawn@0
|
120 }
|
dawn@0
|
121 } else {
|
dawn@0
|
122 npasses=1;
|
dawn@0
|
123 }
|
dawn@0
|
124
|
dawn@0
|
125 if (nrhs > 3) {
|
dawn@0
|
126 clip=1;
|
dawn@0
|
127 } else {
|
dawn@0
|
128 clip=0;
|
dawn@0
|
129 }
|
dawn@0
|
130
|
dawn@0
|
131 /* Create matrix to return */
|
dawn@0
|
132 if (clip) {
|
dawn@0
|
133 Y_OUT = mxCreateDoubleMatrix(m, n, mxREAL);
|
dawn@0
|
134 } else {
|
dawn@0
|
135 Y_OUT = mxCreateDoubleMatrix(m+npasses*(smooth-1), n, mxREAL);
|
dawn@0
|
136 }
|
dawn@0
|
137
|
dawn@0
|
138 /* Assign pointers to the various parameters */
|
dawn@0
|
139 xp = mxGetPr(X_IN);
|
dawn@0
|
140 yp = mxGetPr(Y_OUT);
|
dawn@0
|
141
|
dawn@0
|
142 checkin_matrix((mxArray *) X_IN);
|
dawn@0
|
143 checkin_matrix(Y_OUT);
|
dawn@0
|
144
|
dawn@0
|
145 /* Do the actual computations in a subroutine */
|
dawn@0
|
146 rsmooth(xp,smooth,npasses,yp, m,n,clip);
|
dawn@0
|
147
|
dawn@0
|
148 checkout_matrix((mxArray *) X_IN);
|
dawn@0
|
149 checkout_matrix(Y_OUT);
|
dawn@0
|
150 return;
|
dawn@0
|
151 }
|
dawn@0
|
152
|
dawn@0
|
153
|