1*3f1979aaSAndroid Build Coastguard Worker /*
2*3f1979aaSAndroid Build Coastguard Worker Copyright (c) 2019 Hayati Ayguen ( [email protected] )
3*3f1979aaSAndroid Build Coastguard Worker */
4*3f1979aaSAndroid Build Coastguard Worker
5*3f1979aaSAndroid Build Coastguard Worker #include "pffastconv.h"
6*3f1979aaSAndroid Build Coastguard Worker #include "pffft.h"
7*3f1979aaSAndroid Build Coastguard Worker
8*3f1979aaSAndroid Build Coastguard Worker #include <stdlib.h>
9*3f1979aaSAndroid Build Coastguard Worker #include <stdint.h>
10*3f1979aaSAndroid Build Coastguard Worker #include <stdio.h>
11*3f1979aaSAndroid Build Coastguard Worker #include <math.h>
12*3f1979aaSAndroid Build Coastguard Worker #include <assert.h>
13*3f1979aaSAndroid Build Coastguard Worker #include <string.h>
14*3f1979aaSAndroid Build Coastguard Worker
15*3f1979aaSAndroid Build Coastguard Worker #define FASTCONV_DBG_OUT 0
16*3f1979aaSAndroid Build Coastguard Worker
17*3f1979aaSAndroid Build Coastguard Worker
18*3f1979aaSAndroid Build Coastguard Worker /* detect compiler flavour */
19*3f1979aaSAndroid Build Coastguard Worker #if defined(_MSC_VER)
20*3f1979aaSAndroid Build Coastguard Worker # define RESTRICT __restrict
21*3f1979aaSAndroid Build Coastguard Worker #pragma warning( disable : 4244 4305 4204 4456 )
22*3f1979aaSAndroid Build Coastguard Worker #elif defined(__GNUC__)
23*3f1979aaSAndroid Build Coastguard Worker # define RESTRICT __restrict
24*3f1979aaSAndroid Build Coastguard Worker #endif
25*3f1979aaSAndroid Build Coastguard Worker
26*3f1979aaSAndroid Build Coastguard Worker
pffastconv_malloc(size_t nb_bytes)27*3f1979aaSAndroid Build Coastguard Worker void *pffastconv_malloc(size_t nb_bytes)
28*3f1979aaSAndroid Build Coastguard Worker {
29*3f1979aaSAndroid Build Coastguard Worker return pffft_aligned_malloc(nb_bytes);
30*3f1979aaSAndroid Build Coastguard Worker }
31*3f1979aaSAndroid Build Coastguard Worker
pffastconv_free(void * p)32*3f1979aaSAndroid Build Coastguard Worker void pffastconv_free(void *p)
33*3f1979aaSAndroid Build Coastguard Worker {
34*3f1979aaSAndroid Build Coastguard Worker pffft_aligned_free(p);
35*3f1979aaSAndroid Build Coastguard Worker }
36*3f1979aaSAndroid Build Coastguard Worker
pffastconv_simd_size()37*3f1979aaSAndroid Build Coastguard Worker int pffastconv_simd_size()
38*3f1979aaSAndroid Build Coastguard Worker {
39*3f1979aaSAndroid Build Coastguard Worker return pffft_simd_size();
40*3f1979aaSAndroid Build Coastguard Worker }
41*3f1979aaSAndroid Build Coastguard Worker
42*3f1979aaSAndroid Build Coastguard Worker
43*3f1979aaSAndroid Build Coastguard Worker
44*3f1979aaSAndroid Build Coastguard Worker struct PFFASTCONV_Setup
45*3f1979aaSAndroid Build Coastguard Worker {
46*3f1979aaSAndroid Build Coastguard Worker float * Xt; /* input == x in time domain - copy for alignment */
47*3f1979aaSAndroid Build Coastguard Worker float * Xf; /* input == X in freq domain */
48*3f1979aaSAndroid Build Coastguard Worker float * Hf; /* filterCoeffs == H in freq domain */
49*3f1979aaSAndroid Build Coastguard Worker float * Mf; /* input * filterCoeffs in freq domain */
50*3f1979aaSAndroid Build Coastguard Worker PFFFT_Setup *st;
51*3f1979aaSAndroid Build Coastguard Worker int filterLen; /* convolution length */
52*3f1979aaSAndroid Build Coastguard Worker int Nfft; /* FFT/block length */
53*3f1979aaSAndroid Build Coastguard Worker int flags;
54*3f1979aaSAndroid Build Coastguard Worker float scale;
55*3f1979aaSAndroid Build Coastguard Worker };
56*3f1979aaSAndroid Build Coastguard Worker
57*3f1979aaSAndroid Build Coastguard Worker
pffastconv_new_setup(const float * filterCoeffs,int filterLen,int * blockLen,int flags)58*3f1979aaSAndroid Build Coastguard Worker PFFASTCONV_Setup * pffastconv_new_setup( const float * filterCoeffs, int filterLen, int * blockLen, int flags )
59*3f1979aaSAndroid Build Coastguard Worker {
60*3f1979aaSAndroid Build Coastguard Worker PFFASTCONV_Setup * s = NULL;
61*3f1979aaSAndroid Build Coastguard Worker const int cplxFactor = ( (flags & PFFASTCONV_CPLX_INP_OUT) && (flags & PFFASTCONV_CPLX_SINGLE_FFT) ) ? 2 : 1;
62*3f1979aaSAndroid Build Coastguard Worker const int minFftLen = 2*pffft_simd_size()*pffft_simd_size();
63*3f1979aaSAndroid Build Coastguard Worker int i, Nfft = 2 * pffft_next_power_of_two(filterLen -1);
64*3f1979aaSAndroid Build Coastguard Worker #if FASTCONV_DBG_OUT
65*3f1979aaSAndroid Build Coastguard Worker const int iOldBlkLen = *blockLen;
66*3f1979aaSAndroid Build Coastguard Worker #endif
67*3f1979aaSAndroid Build Coastguard Worker
68*3f1979aaSAndroid Build Coastguard Worker if ( Nfft < minFftLen )
69*3f1979aaSAndroid Build Coastguard Worker Nfft = minFftLen;
70*3f1979aaSAndroid Build Coastguard Worker
71*3f1979aaSAndroid Build Coastguard Worker if ( flags & PFFASTCONV_CPLX_FILTER )
72*3f1979aaSAndroid Build Coastguard Worker return NULL;
73*3f1979aaSAndroid Build Coastguard Worker
74*3f1979aaSAndroid Build Coastguard Worker s = pffastconv_malloc( sizeof(struct PFFASTCONV_Setup) );
75*3f1979aaSAndroid Build Coastguard Worker
76*3f1979aaSAndroid Build Coastguard Worker if ( *blockLen > Nfft ) {
77*3f1979aaSAndroid Build Coastguard Worker Nfft = *blockLen;
78*3f1979aaSAndroid Build Coastguard Worker Nfft = pffft_next_power_of_two(Nfft);
79*3f1979aaSAndroid Build Coastguard Worker }
80*3f1979aaSAndroid Build Coastguard Worker *blockLen = Nfft; /* this is in (complex) samples */
81*3f1979aaSAndroid Build Coastguard Worker
82*3f1979aaSAndroid Build Coastguard Worker Nfft *= cplxFactor;
83*3f1979aaSAndroid Build Coastguard Worker
84*3f1979aaSAndroid Build Coastguard Worker if ( (flags & PFFASTCONV_DIRECT_INP) && !(flags & PFFASTCONV_CPLX_INP_OUT) )
85*3f1979aaSAndroid Build Coastguard Worker s->Xt = NULL;
86*3f1979aaSAndroid Build Coastguard Worker else
87*3f1979aaSAndroid Build Coastguard Worker s->Xt = pffastconv_malloc((unsigned)Nfft * sizeof(float));
88*3f1979aaSAndroid Build Coastguard Worker s->Xf = pffastconv_malloc((unsigned)Nfft * sizeof(float));
89*3f1979aaSAndroid Build Coastguard Worker s->Hf = pffastconv_malloc((unsigned)Nfft * sizeof(float));
90*3f1979aaSAndroid Build Coastguard Worker s->Mf = pffastconv_malloc((unsigned)Nfft * sizeof(float));
91*3f1979aaSAndroid Build Coastguard Worker s->st = pffft_new_setup(Nfft, PFFFT_REAL); /* with complex: we do 2 x fft() */
92*3f1979aaSAndroid Build Coastguard Worker s->filterLen = filterLen; /* filterLen == convolution length == length of impulse response */
93*3f1979aaSAndroid Build Coastguard Worker if ( cplxFactor == 2 )
94*3f1979aaSAndroid Build Coastguard Worker s->filterLen = 2 * filterLen - 1;
95*3f1979aaSAndroid Build Coastguard Worker s->Nfft = Nfft; /* FFT/block length */
96*3f1979aaSAndroid Build Coastguard Worker s->flags = flags;
97*3f1979aaSAndroid Build Coastguard Worker s->scale = (float)( 1.0 / Nfft );
98*3f1979aaSAndroid Build Coastguard Worker
99*3f1979aaSAndroid Build Coastguard Worker memset( s->Xt, 0, (unsigned)Nfft * sizeof(float) );
100*3f1979aaSAndroid Build Coastguard Worker if ( flags & PFFASTCONV_CORRELATION ) {
101*3f1979aaSAndroid Build Coastguard Worker for ( i = 0; i < filterLen; ++i )
102*3f1979aaSAndroid Build Coastguard Worker s->Xt[ ( Nfft - cplxFactor * i ) & (Nfft -1) ] = filterCoeffs[ i ];
103*3f1979aaSAndroid Build Coastguard Worker } else {
104*3f1979aaSAndroid Build Coastguard Worker for ( i = 0; i < filterLen; ++i )
105*3f1979aaSAndroid Build Coastguard Worker s->Xt[ ( Nfft - cplxFactor * i ) & (Nfft -1) ] = filterCoeffs[ filterLen - 1 - i ];
106*3f1979aaSAndroid Build Coastguard Worker }
107*3f1979aaSAndroid Build Coastguard Worker
108*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Xt, s->Hf, /* tmp = */ s->Mf, PFFFT_FORWARD);
109*3f1979aaSAndroid Build Coastguard Worker
110*3f1979aaSAndroid Build Coastguard Worker #if FASTCONV_DBG_OUT
111*3f1979aaSAndroid Build Coastguard Worker printf("\n fastConvSetup(filterLen = %d, blockLen %d) --> blockLen %d, OutLen = %d\n"
112*3f1979aaSAndroid Build Coastguard Worker , filterLen, iOldBlkLen, *blockLen, Nfft - filterLen +1 );
113*3f1979aaSAndroid Build Coastguard Worker #endif
114*3f1979aaSAndroid Build Coastguard Worker
115*3f1979aaSAndroid Build Coastguard Worker return s;
116*3f1979aaSAndroid Build Coastguard Worker }
117*3f1979aaSAndroid Build Coastguard Worker
118*3f1979aaSAndroid Build Coastguard Worker
pffastconv_destroy_setup(PFFASTCONV_Setup * s)119*3f1979aaSAndroid Build Coastguard Worker void pffastconv_destroy_setup( PFFASTCONV_Setup * s )
120*3f1979aaSAndroid Build Coastguard Worker {
121*3f1979aaSAndroid Build Coastguard Worker if (!s)
122*3f1979aaSAndroid Build Coastguard Worker return;
123*3f1979aaSAndroid Build Coastguard Worker pffft_destroy_setup(s->st);
124*3f1979aaSAndroid Build Coastguard Worker pffastconv_free(s->Mf);
125*3f1979aaSAndroid Build Coastguard Worker pffastconv_free(s->Hf);
126*3f1979aaSAndroid Build Coastguard Worker pffastconv_free(s->Xf);
127*3f1979aaSAndroid Build Coastguard Worker if ( s->Xt )
128*3f1979aaSAndroid Build Coastguard Worker pffastconv_free(s->Xt);
129*3f1979aaSAndroid Build Coastguard Worker pffastconv_free(s);
130*3f1979aaSAndroid Build Coastguard Worker }
131*3f1979aaSAndroid Build Coastguard Worker
132*3f1979aaSAndroid Build Coastguard Worker
pffastconv_apply(PFFASTCONV_Setup * s,const float * input_,int cplxInputLen,float * output_,int applyFlush)133*3f1979aaSAndroid Build Coastguard Worker int pffastconv_apply(PFFASTCONV_Setup * s, const float *input_, int cplxInputLen, float *output_, int applyFlush)
134*3f1979aaSAndroid Build Coastguard Worker {
135*3f1979aaSAndroid Build Coastguard Worker const float * RESTRICT X = input_;
136*3f1979aaSAndroid Build Coastguard Worker float * RESTRICT Y = output_;
137*3f1979aaSAndroid Build Coastguard Worker const int Nfft = s->Nfft;
138*3f1979aaSAndroid Build Coastguard Worker const int filterLen = s->filterLen;
139*3f1979aaSAndroid Build Coastguard Worker const int flags = s->flags;
140*3f1979aaSAndroid Build Coastguard Worker const int cplxFactor = ( (flags & PFFASTCONV_CPLX_INP_OUT) && (flags & PFFASTCONV_CPLX_SINGLE_FFT) ) ? 2 : 1;
141*3f1979aaSAndroid Build Coastguard Worker const int inputLen = cplxFactor * cplxInputLen;
142*3f1979aaSAndroid Build Coastguard Worker int inpOff, procLen, numOut = 0, j, part, cplxOff;
143*3f1979aaSAndroid Build Coastguard Worker
144*3f1979aaSAndroid Build Coastguard Worker /* applyFlush != 0:
145*3f1979aaSAndroid Build Coastguard Worker * inputLen - inpOff -filterLen + 1 > 0
146*3f1979aaSAndroid Build Coastguard Worker * <=> inputLen -filterLen + 1 > inpOff
147*3f1979aaSAndroid Build Coastguard Worker * <=> inpOff < inputLen -filterLen + 1
148*3f1979aaSAndroid Build Coastguard Worker *
149*3f1979aaSAndroid Build Coastguard Worker * applyFlush == 0:
150*3f1979aaSAndroid Build Coastguard Worker * inputLen - inpOff >= Nfft
151*3f1979aaSAndroid Build Coastguard Worker * <=> inputLen - Nfft >= inpOff
152*3f1979aaSAndroid Build Coastguard Worker * <=> inpOff <= inputLen - Nfft
153*3f1979aaSAndroid Build Coastguard Worker * <=> inpOff < inputLen - Nfft + 1
154*3f1979aaSAndroid Build Coastguard Worker */
155*3f1979aaSAndroid Build Coastguard Worker
156*3f1979aaSAndroid Build Coastguard Worker if ( cplxFactor == 2 )
157*3f1979aaSAndroid Build Coastguard Worker {
158*3f1979aaSAndroid Build Coastguard Worker const int maxOff = applyFlush ? (inputLen -filterLen + 1) : (inputLen - Nfft + 1);
159*3f1979aaSAndroid Build Coastguard Worker #if 0
160*3f1979aaSAndroid Build Coastguard Worker printf( "*** inputLen %d, filterLen %d, Nfft %d => maxOff %d\n", inputLen, filterLen, Nfft, maxOff);
161*3f1979aaSAndroid Build Coastguard Worker #endif
162*3f1979aaSAndroid Build Coastguard Worker for ( inpOff = 0; inpOff < maxOff; inpOff += numOut )
163*3f1979aaSAndroid Build Coastguard Worker {
164*3f1979aaSAndroid Build Coastguard Worker procLen = ( (inputLen - inpOff) >= Nfft ) ? Nfft : (inputLen - inpOff);
165*3f1979aaSAndroid Build Coastguard Worker numOut = ( procLen - filterLen + 1 ) & ( ~1 );
166*3f1979aaSAndroid Build Coastguard Worker if (!numOut)
167*3f1979aaSAndroid Build Coastguard Worker break;
168*3f1979aaSAndroid Build Coastguard Worker #if 0
169*3f1979aaSAndroid Build Coastguard Worker if (!inpOff)
170*3f1979aaSAndroid Build Coastguard Worker printf("*** inpOff = %d, numOut = %d\n", inpOff, numOut);
171*3f1979aaSAndroid Build Coastguard Worker if (inpOff + filterLen + 2 >= maxOff )
172*3f1979aaSAndroid Build Coastguard Worker printf("*** inpOff = %d, inpOff + numOut = %d\n", inpOff, inpOff + numOut);
173*3f1979aaSAndroid Build Coastguard Worker #endif
174*3f1979aaSAndroid Build Coastguard Worker
175*3f1979aaSAndroid Build Coastguard Worker if ( flags & PFFASTCONV_DIRECT_INP )
176*3f1979aaSAndroid Build Coastguard Worker {
177*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, X + inpOff, s->Xf, /* tmp = */ s->Mf, PFFFT_FORWARD);
178*3f1979aaSAndroid Build Coastguard Worker }
179*3f1979aaSAndroid Build Coastguard Worker else
180*3f1979aaSAndroid Build Coastguard Worker {
181*3f1979aaSAndroid Build Coastguard Worker memcpy( s->Xt, X + inpOff, (unsigned)procLen * sizeof(float) );
182*3f1979aaSAndroid Build Coastguard Worker if ( procLen < Nfft )
183*3f1979aaSAndroid Build Coastguard Worker memset( s->Xt + procLen, 0, (unsigned)(Nfft - procLen) * sizeof(float) );
184*3f1979aaSAndroid Build Coastguard Worker
185*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Xt, s->Xf, /* tmp = */ s->Mf, PFFFT_FORWARD);
186*3f1979aaSAndroid Build Coastguard Worker }
187*3f1979aaSAndroid Build Coastguard Worker
188*3f1979aaSAndroid Build Coastguard Worker pffft_zconvolve_no_accu(s->st, s->Xf, s->Hf, /* tmp = */ s->Mf, s->scale);
189*3f1979aaSAndroid Build Coastguard Worker
190*3f1979aaSAndroid Build Coastguard Worker if ( flags & PFFASTCONV_DIRECT_OUT )
191*3f1979aaSAndroid Build Coastguard Worker {
192*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Mf, Y + inpOff, s->Xf, PFFFT_BACKWARD);
193*3f1979aaSAndroid Build Coastguard Worker }
194*3f1979aaSAndroid Build Coastguard Worker else
195*3f1979aaSAndroid Build Coastguard Worker {
196*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Mf, s->Xf, /* tmp = */ s->Xt, PFFFT_BACKWARD);
197*3f1979aaSAndroid Build Coastguard Worker memcpy( Y + inpOff, s->Xf, (unsigned)numOut * sizeof(float) );
198*3f1979aaSAndroid Build Coastguard Worker }
199*3f1979aaSAndroid Build Coastguard Worker }
200*3f1979aaSAndroid Build Coastguard Worker return inpOff / cplxFactor;
201*3f1979aaSAndroid Build Coastguard Worker }
202*3f1979aaSAndroid Build Coastguard Worker else
203*3f1979aaSAndroid Build Coastguard Worker {
204*3f1979aaSAndroid Build Coastguard Worker const int maxOff = applyFlush ? (inputLen -filterLen + 1) : (inputLen - Nfft + 1);
205*3f1979aaSAndroid Build Coastguard Worker const int numParts = (flags & PFFASTCONV_CPLX_INP_OUT) ? 2 : 1;
206*3f1979aaSAndroid Build Coastguard Worker
207*3f1979aaSAndroid Build Coastguard Worker for ( inpOff = 0; inpOff < maxOff; inpOff += numOut )
208*3f1979aaSAndroid Build Coastguard Worker {
209*3f1979aaSAndroid Build Coastguard Worker procLen = ( (inputLen - inpOff) >= Nfft ) ? Nfft : (inputLen - inpOff);
210*3f1979aaSAndroid Build Coastguard Worker numOut = procLen - filterLen + 1;
211*3f1979aaSAndroid Build Coastguard Worker
212*3f1979aaSAndroid Build Coastguard Worker for ( part = 0; part < numParts; ++part ) /* iterate per real/imag component */
213*3f1979aaSAndroid Build Coastguard Worker {
214*3f1979aaSAndroid Build Coastguard Worker
215*3f1979aaSAndroid Build Coastguard Worker if ( flags & PFFASTCONV_CPLX_INP_OUT )
216*3f1979aaSAndroid Build Coastguard Worker {
217*3f1979aaSAndroid Build Coastguard Worker cplxOff = 2 * inpOff + part;
218*3f1979aaSAndroid Build Coastguard Worker for ( j = 0; j < procLen; ++j )
219*3f1979aaSAndroid Build Coastguard Worker s->Xt[j] = X[cplxOff + 2 * j];
220*3f1979aaSAndroid Build Coastguard Worker if ( procLen < Nfft )
221*3f1979aaSAndroid Build Coastguard Worker memset( s->Xt + procLen, 0, (unsigned)(Nfft - procLen) * sizeof(float) );
222*3f1979aaSAndroid Build Coastguard Worker
223*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Xt, s->Xf, /* tmp = */ s->Mf, PFFFT_FORWARD);
224*3f1979aaSAndroid Build Coastguard Worker }
225*3f1979aaSAndroid Build Coastguard Worker else if ( flags & PFFASTCONV_DIRECT_INP )
226*3f1979aaSAndroid Build Coastguard Worker {
227*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, X + inpOff, s->Xf, /* tmp = */ s->Mf, PFFFT_FORWARD);
228*3f1979aaSAndroid Build Coastguard Worker }
229*3f1979aaSAndroid Build Coastguard Worker else
230*3f1979aaSAndroid Build Coastguard Worker {
231*3f1979aaSAndroid Build Coastguard Worker memcpy( s->Xt, X + inpOff, (unsigned)procLen * sizeof(float) );
232*3f1979aaSAndroid Build Coastguard Worker if ( procLen < Nfft )
233*3f1979aaSAndroid Build Coastguard Worker memset( s->Xt + procLen, 0, (unsigned)(Nfft - procLen) * sizeof(float) );
234*3f1979aaSAndroid Build Coastguard Worker
235*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Xt, s->Xf, /* tmp = */ s->Mf, PFFFT_FORWARD);
236*3f1979aaSAndroid Build Coastguard Worker }
237*3f1979aaSAndroid Build Coastguard Worker
238*3f1979aaSAndroid Build Coastguard Worker pffft_zconvolve_no_accu(s->st, s->Xf, s->Hf, /* tmp = */ s->Mf, s->scale);
239*3f1979aaSAndroid Build Coastguard Worker
240*3f1979aaSAndroid Build Coastguard Worker if ( flags & PFFASTCONV_CPLX_INP_OUT )
241*3f1979aaSAndroid Build Coastguard Worker {
242*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Mf, s->Xf, /* tmp = */ s->Xt, PFFFT_BACKWARD);
243*3f1979aaSAndroid Build Coastguard Worker
244*3f1979aaSAndroid Build Coastguard Worker cplxOff = 2 * inpOff + part;
245*3f1979aaSAndroid Build Coastguard Worker for ( j = 0; j < numOut; ++j )
246*3f1979aaSAndroid Build Coastguard Worker Y[ cplxOff + 2 * j ] = s->Xf[j];
247*3f1979aaSAndroid Build Coastguard Worker }
248*3f1979aaSAndroid Build Coastguard Worker else if ( flags & PFFASTCONV_DIRECT_OUT )
249*3f1979aaSAndroid Build Coastguard Worker {
250*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Mf, Y + inpOff, s->Xf, PFFFT_BACKWARD);
251*3f1979aaSAndroid Build Coastguard Worker }
252*3f1979aaSAndroid Build Coastguard Worker else
253*3f1979aaSAndroid Build Coastguard Worker {
254*3f1979aaSAndroid Build Coastguard Worker pffft_transform(s->st, s->Mf, s->Xf, /* tmp = */ s->Xt, PFFFT_BACKWARD);
255*3f1979aaSAndroid Build Coastguard Worker memcpy( Y + inpOff, s->Xf, (unsigned)numOut * sizeof(float) );
256*3f1979aaSAndroid Build Coastguard Worker }
257*3f1979aaSAndroid Build Coastguard Worker
258*3f1979aaSAndroid Build Coastguard Worker }
259*3f1979aaSAndroid Build Coastguard Worker }
260*3f1979aaSAndroid Build Coastguard Worker
261*3f1979aaSAndroid Build Coastguard Worker return inpOff;
262*3f1979aaSAndroid Build Coastguard Worker }
263*3f1979aaSAndroid Build Coastguard Worker }
264*3f1979aaSAndroid Build Coastguard Worker
265