mmxresample.c
上传用户:dangjiwu
上传日期:2013-07-19
资源大小:42019k
文件大小:19k
源码类别:

Symbian

开发平台:

Visual C++

  1. /* ***** BEGIN LICENSE BLOCK *****
  2.  * Source last modified: $Id: mmxresample.c,v 1.8.32.1 2004/07/09 02:01:17 hubbe Exp $
  3.  * 
  4.  * Portions Copyright (c) 1995-2004 RealNetworks, Inc. All Rights Reserved.
  5.  * 
  6.  * The contents of this file, and the files included with this file,
  7.  * are subject to the current version of the RealNetworks Public
  8.  * Source License (the "RPSL") available at
  9.  * http://www.helixcommunity.org/content/rpsl unless you have licensed
  10.  * the file under the current version of the RealNetworks Community
  11.  * Source License (the "RCSL") available at
  12.  * http://www.helixcommunity.org/content/rcsl, in which case the RCSL
  13.  * will apply. You may also obtain the license terms directly from
  14.  * RealNetworks.  You may not use this file except in compliance with
  15.  * the RPSL or, if you have a valid RCSL with RealNetworks applicable
  16.  * to this file, the RCSL.  Please see the applicable RPSL or RCSL for
  17.  * the rights, obligations and limitations governing use of the
  18.  * contents of the file.
  19.  * 
  20.  * Alternatively, the contents of this file may be used under the
  21.  * terms of the GNU General Public License Version 2 or later (the
  22.  * "GPL") in which case the provisions of the GPL are applicable
  23.  * instead of those above. If you wish to allow use of your version of
  24.  * this file only under the terms of the GPL, and not to allow others
  25.  * to use your version of this file under the terms of either the RPSL
  26.  * or RCSL, indicate your decision by deleting the provisions above
  27.  * and replace them with the notice and other provisions required by
  28.  * the GPL. If you do not delete the provisions above, a recipient may
  29.  * use your version of this file under the terms of any one of the
  30.  * RPSL, the RCSL or the GPL.
  31.  * 
  32.  * This file is part of the Helix DNA Technology. RealNetworks is the
  33.  * developer of the Original Code and owns the copyrights in the
  34.  * portions it created.
  35.  * 
  36.  * This file, and the files included with this file, is distributed
  37.  * and made available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY
  38.  * KIND, EITHER EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS
  39.  * ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES
  40.  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET
  41.  * ENJOYMENT OR NON-INFRINGEMENT.
  42.  * 
  43.  * Technology Compatibility Kit Test Suite(s) Location:
  44.  *    http://www.helixcommunity.org/content/tck
  45.  * 
  46.  * Contributor(s):
  47.  * 
  48.  * ***** END LICENSE BLOCK ***** */
  49. #ifdef _M_IX86
  50. /*
  51.  * Polyphase sampling rate conversion.
  52.  * by Ken Cooke
  53.  */
  54. #include "hlxclib/stdlib.h"
  55. #include "hlxclib/string.h"
  56. //#include <stdio.h>
  57. #include "allresamplers.h"
  58. /* leave a trace of the C source version in the object code */
  59. static const char VERSION[] = "$Revision: 1.8.32.1 $" ;
  60. #define CLIP(s) ((s) > 32767 ? 32767 : ((s) < -32768 ? -32768 : (s)))
  61. #define NWING 48
  62. #define NTAPS 96
  63. typedef short filtwing[NWING];
  64. #define PCMBUFLEN (NBLOCK + 2*NTAPS)
  65. #define ROFFSET (PCMBUFLEN / 2)
  66. #define RBYTEOFF (ROFFSET * 2)
  67. /* precomputed filter tables */
  68. #define HELIX_FEATURE_MMXFILTER_6_1
  69. #define HELIX_FEATURE_MMXFILTER_640_147
  70. #define HELIX_FEATURE_MMXFILTER_3_1
  71. #define HELIX_FEATURE_MMXFILTER_320_147
  72. #define HELIX_FEATURE_MMXFILTER_3_2
  73. #define HELIX_FEATURE_MMXFILTER_160_147
  74. #define HELIX_FEATURE_MMXFILTER_441_80
  75. #define HELIX_FEATURE_MMXFILTER_4_1
  76. #define HELIX_FEATURE_MMXFILTER_441_160
  77. #define HELIX_FEATURE_MMXFILTER_2_1
  78. #define HELIX_FEATURE_MMXFILTER_441_320
  79. #define HELIX_FEATURE_MMXFILTER_147_160
  80. #include "mmxfilters.c"
  81. //extern int updn_list[];
  82. //extern filtwing *filter_list[];
  83. //extern int *nextstate_list[];
  84. /* filter state */
  85. typedef struct {
  86. int up;
  87. int dn;
  88. int nchans;
  89. int phase;
  90. int offset;
  91. short *histbuf;
  92. short *pcmleft, *pcmrght;
  93. short *revbuf;
  94. short *revleft, *revrght;
  95. short *lwingptr;
  96. short *rwingptr;
  97. filtwing *filter;
  98. int *nextstate;
  99. } state_t;
  100. void *
  101. RAInitResamplerMMX(int inrate, int outrate, int nchans)
  102. {
  103. state_t *s;
  104. int divisor, up, dn;
  105. int idx;
  106. if (nchans != MONO && nchans != STEREO) {
  107. // printf("Error: must be mono or stereon");
  108. return NULL;
  109. }
  110. /* reduce to smallest fraction */
  111. divisor = gcd(inrate, outrate);
  112. up = outrate / divisor;
  113. dn = inrate / divisor;
  114. // printf("up = %d, down = %dn", up, dn);
  115. /* find corresponding filter in tables */
  116. for (idx = 0; updn_list[idx]; idx++)
  117. if (updn_list[idx] == ((up << 16) | dn))
  118. break;
  119. if (!updn_list[idx]) {
  120. // printf("Error: conversion by %d/%d not supportedn", up, dn);
  121. return NULL; /* unsupported rates */
  122. }
  123. /* malloc buffers */
  124. s = (state_t *) malloc(sizeof(state_t));
  125. if (s == NULL)
  126. return NULL;
  127. s->histbuf = (short *) calloc(PCMBUFLEN, sizeof(short));
  128. s->revbuf = (short *) calloc(PCMBUFLEN, sizeof(short));
  129. if (s->histbuf == NULL || s->revbuf == NULL)
  130. return NULL;
  131. /* filter init */
  132. s->filter = filter_list[idx];
  133. s->nextstate = nextstate_list[idx];
  134. s->up = up;
  135. s->dn = dn;
  136. s->nchans = nchans;
  137. s->phase = 0;
  138. s->offset = 0;
  139. s->pcmleft = s->histbuf + NTAPS;
  140. s->revleft = s->revbuf + NBLOCK/2;
  141. s->pcmrght = s->pcmleft + ROFFSET;
  142. s->revrght = s->revleft + ROFFSET;
  143. s->rwingptr = s->filter[0];
  144. s->lwingptr = s->filter[(s->nextstate[up-1]>>8) & 0xfff];
  145. return (void *) s;
  146. }
  147. void *
  148. RAInitResamplerCopyMMX(int nchans, void *inst)
  149. {
  150. state_t *s_in = (state_t *)inst;
  151. state_t *s_out = (state_t *) malloc(sizeof(state_t));
  152. if (s_in == NULL || s_out == NULL)
  153. return NULL;
  154. s_out->histbuf = (short *) calloc(PCMBUFLEN, sizeof(short));
  155. s_out->revbuf = (short *) calloc(PCMBUFLEN, sizeof(short));
  156. if (s_out->histbuf == NULL || s_out->revbuf == NULL)
  157. return NULL;
  158. /* filter init */
  159. s_out->filter = s_in->filter;
  160. s_out->nextstate = s_in->nextstate;
  161. s_out->up = s_in->up;
  162. s_out->dn = s_in->dn;
  163. s_out->nchans = nchans;
  164. s_out->phase = 0;
  165. s_out->offset = 0;
  166. s_out->pcmleft = s_out->histbuf + NTAPS;
  167. s_out->revleft = s_out->revbuf + NBLOCK/2;
  168. s_out->pcmrght = s_out->pcmleft + ROFFSET;
  169. s_out->revrght = s_out->revleft + ROFFSET;
  170. s_out->rwingptr = s_out->filter[0];
  171. s_out->lwingptr = s_out->filter[(s_out->nextstate[s_out->up-1]>>8) & 0xfff];
  172. return s_out ;
  173. }
  174. void
  175. RAFreeResamplerMMX(void *inst)
  176. {
  177. state_t *s = (state_t *)inst;
  178. if (s != NULL) {
  179. if (s->revbuf)
  180. free(s->revbuf);
  181. if (s->histbuf)
  182. free(s->histbuf);
  183. free(s);
  184. }
  185. }
  186. int
  187. RAResampleStereoMMX(void *inbuf, int insamps, tConverter *pCvt, short *outbuf, int outstride, void *inst)
  188. {
  189.     state_t *s = (state_t *)inst;
  190. short *pcmptr, *revptr, *pcmend;
  191. short *rwingptr, *lwingptr;
  192. int i, outsamps;
  193. /* local copies */
  194. filtwing *filter = s->filter;
  195. int *nextstate = s->nextstate;
  196. int phase = s->phase;
  197. int round13[2] = { 1<<13, 1<<13 };
  198. // TICK();
  199. // ASSERT(!(insamps & 0x1)); /* stereo must be even */
  200. outstride *= sizeof(short) ;
  201. // hack the state machine to point to pcmleft and pcmright buffers.
  202. pCvt->pStateMachine[0].incOutput = s->pcmrght - s->pcmleft ;
  203. pCvt->pStateMachine[1].incOutput = s->pcmleft - s->pcmrght + 1 ;
  204. insamps = 2*pCvt->pfCvt(s->pcmleft,inbuf,insamps,pCvt->pStateMachine) ;
  205. #if 0
  206. /* deinterleave new input */
  207. for (i = 0; i < insamps/2; i++) {
  208. s->pcmleft[i] = inbuf[0];
  209. s->pcmrght[i] = inbuf[1];
  210. inbuf += 2;
  211. }
  212. #endif
  213. /* create revbufs */
  214. for (i = -insamps/2; i < NTAPS; i++) {
  215. s->revleft[i] = s->pcmleft[-i-1];
  216. s->revrght[i] = s->pcmrght[-i-1];
  217. }
  218. /* restore filter state */
  219. pcmptr = s->pcmleft + s->offset - (NTAPS-1);
  220. revptr = s->revleft - s->offset - 1;
  221. pcmend = s->pcmleft + insamps/2 - (NTAPS-1);
  222. rwingptr = s->rwingptr;
  223. lwingptr = s->lwingptr;
  224. __asm {
  225. mov esi, pcmptr
  226. mov edi, revptr
  227. mov ebx, phase
  228. mov ecx, outbuf
  229. mov eax, rwingptr
  230. mov edx, lwingptr
  231. movq mm5, round13
  232. conv_loop: /* while (pcmptr < pcmend) */
  233. cmp esi, pcmend
  234. jae conv_done
  235. /* LEFT CHANNEL */
  236. /* prime */
  237. movq mm6, [esi+0]
  238. pmaddwd mm6, [eax+0]
  239. movq mm1, [edi+0]
  240. pmaddwd mm1, [edx+0]
  241. movq mm2, [esi+8]
  242. psrad mm6, 8
  243. pmaddwd mm2, [eax+8]
  244. //paddd mm6, mm0
  245. movq mm3, [edi+8]
  246. psrad mm1, 8
  247. pmaddwd mm3, [edx+8]
  248. paddd mm6, mm1
  249. movq mm0, [esi+16]
  250. psrad mm2, 6
  251. pmaddwd mm0, [eax+16]
  252. paddd mm6, mm2
  253. movq mm1, [edi+16]
  254. psrad mm3, 6
  255. pmaddwd mm1, [edx+16]
  256. paddd mm6, mm3
  257. movq mm2, [esi+24]
  258. psrad mm0, 4
  259. pmaddwd mm2, [eax+24]
  260. paddd mm6, mm0
  261. movq mm3, [edi+24]
  262. psrad mm1, 4
  263. pmaddwd mm3, [edx+24]
  264. paddd mm6, mm1
  265. movq mm0, [esi+32]
  266. psrad mm2, 3
  267. pmaddwd mm0, [eax+32]
  268. paddd mm6, mm2
  269. movq mm1, [edi+32]
  270. psrad mm3, 3
  271. pmaddwd mm1, [edx+32]
  272. paddd mm6, mm3
  273. movq mm2, [esi+40]
  274. psrad mm0, 2
  275. pmaddwd mm2, [eax+40]
  276. paddd mm6, mm0
  277. movq mm3, [edi+40]
  278. psrad mm1, 2
  279. pmaddwd mm3, [edx+40]
  280. paddd mm6, mm1
  281. movq mm0, [esi+48]
  282. psrad mm2, 1
  283. pmaddwd mm0, [eax+48]
  284. paddd mm6, mm2
  285. movq mm1, [edi+48]
  286. psrad mm3, 1
  287. pmaddwd mm1, [edx+48]
  288. paddd mm6, mm3
  289. /* acc shift */
  290. psrad mm6, 8
  291. movq mm2, [esi+56]
  292. psrad mm0, 8
  293. pmaddwd mm2, [eax+56]
  294. paddd mm6, mm0
  295. movq mm3, [edi+56]
  296. psrad mm1, 8
  297. pmaddwd mm3, [edx+56]
  298. paddd mm6, mm1
  299. movq mm0, [esi+64]
  300. psrad mm2, 7
  301. pmaddwd mm0, [eax+64]
  302. paddd mm6, mm2
  303. movq mm1, [edi+64]
  304. psrad mm3, 7
  305. pmaddwd mm1, [edx+64]
  306. paddd mm6, mm3
  307. movq mm2, [esi+72]
  308. psrad mm0, 6
  309. pmaddwd mm2, [eax+72]
  310. paddd mm6, mm0
  311. movq mm3, [edi+72]
  312. psrad mm1, 6
  313. pmaddwd mm3, [edx+72]
  314. paddd mm6, mm1
  315. movq mm0, [esi+80]
  316. psrad mm2, 5
  317. pmaddwd mm0, [eax+80]
  318. paddd mm6, mm2
  319. movq mm1, [edi+80]
  320. psrad mm3, 5
  321. pmaddwd mm1, [edx+80]
  322. paddd mm6, mm3
  323. movq mm2, [esi+88]
  324. psrad mm0, 4
  325. pmaddwd mm2, [eax+88]
  326. paddd mm6, mm0
  327. movq mm3, [edi+88]
  328. psrad mm1, 4
  329. pmaddwd mm3, [edx+88]
  330. paddd mm6, mm1
  331. /* flush */
  332. psrad mm2, 1
  333. paddd mm6, mm2
  334. psrad mm3, 1
  335. paddd mm6, mm3
  336. /* RIGHT CHANNEL */
  337. /* prime */
  338. movq mm7, [esi+RBYTEOFF+0]
  339. pmaddwd mm7, [eax+0]
  340. movq mm1, [edi+RBYTEOFF+0]
  341. pmaddwd mm1, [edx+0]
  342. movq mm2, [esi+RBYTEOFF+8]
  343. psrad mm7, 8
  344. pmaddwd mm2, [eax+8]
  345. //paddd mm7, mm0
  346. movq mm3, [edi+RBYTEOFF+8]
  347. psrad mm1, 8
  348. pmaddwd mm3, [edx+8]
  349. paddd mm7, mm1
  350. movq mm0, [esi+RBYTEOFF+16]
  351. psrad mm2, 6
  352. pmaddwd mm0, [eax+16]
  353. paddd mm7, mm2
  354. movq mm1, [edi+RBYTEOFF+16]
  355. psrad mm3, 6
  356. pmaddwd mm1, [edx+16]
  357. paddd mm7, mm3
  358. movq mm2, [esi+RBYTEOFF+24]
  359. psrad mm0, 4
  360. pmaddwd mm2, [eax+24]
  361. paddd mm7, mm0
  362. movq mm3, [edi+RBYTEOFF+24]
  363. psrad mm1, 4
  364. pmaddwd mm3, [edx+24]
  365. paddd mm7, mm1
  366. movq mm0, [esi+RBYTEOFF+32]
  367. psrad mm2, 3
  368. pmaddwd mm0, [eax+32]
  369. paddd mm7, mm2
  370. movq mm1, [edi+RBYTEOFF+32]
  371. psrad mm3, 3
  372. pmaddwd mm1, [edx+32]
  373. paddd mm7, mm3
  374. movq mm2, [esi+RBYTEOFF+40]
  375. psrad mm0, 2
  376. pmaddwd mm2, [eax+40]
  377. paddd mm7, mm0
  378. movq mm3, [edi+RBYTEOFF+40]
  379. psrad mm1, 2
  380. pmaddwd mm3, [edx+40]
  381. paddd mm7, mm1
  382. movq mm0, [esi+RBYTEOFF+48]
  383. psrad mm2, 1
  384. pmaddwd mm0, [eax+48]
  385. paddd mm7, mm2
  386. movq mm1, [edi+RBYTEOFF+48]
  387. psrad mm3, 1
  388. pmaddwd mm1, [edx+48]
  389. paddd mm7, mm3
  390. /* acc shift */
  391. psrad mm7, 8
  392. movq mm2, [esi+RBYTEOFF+56]
  393. psrad mm0, 8
  394. pmaddwd mm2, [eax+56]
  395. paddd mm7, mm0
  396. movq mm3, [edi+RBYTEOFF+56]
  397. psrad mm1, 8
  398. pmaddwd mm3, [edx+56]
  399. paddd mm7, mm1
  400. movq mm0, [esi+RBYTEOFF+64]
  401. psrad mm2, 7
  402. pmaddwd mm0, [eax+64]
  403. paddd mm7, mm2
  404. movq mm1, [edi+RBYTEOFF+64]
  405. psrad mm3, 7
  406. pmaddwd mm1, [edx+64]
  407. paddd mm7, mm3
  408. movq mm2, [esi+RBYTEOFF+72]
  409. psrad mm0, 6
  410. pmaddwd mm2, [eax+72]
  411. paddd mm7, mm0
  412. movq mm3, [edi+RBYTEOFF+72]
  413. psrad mm1, 6
  414. pmaddwd mm3, [edx+72]
  415. paddd mm7, mm1
  416. movq mm0, [esi+RBYTEOFF+80]
  417. psrad mm2, 5
  418. pmaddwd mm0, [eax+80]
  419. paddd mm7, mm2
  420. movq mm1, [edi+RBYTEOFF+80]
  421. psrad mm3, 5
  422. pmaddwd mm1, [edx+80]
  423. paddd mm7, mm3
  424. movq mm2, [esi+RBYTEOFF+88]
  425. psrad mm0, 4
  426. pmaddwd mm2, [eax+88]
  427. paddd mm7, mm0
  428. movq mm3, [edi+RBYTEOFF+88]
  429. psrad mm1, 4
  430. pmaddwd mm3, [edx+88]
  431. paddd mm7, mm1
  432. /* flush */
  433. psrad mm2, 1
  434. paddd mm7, mm2
  435. psrad mm3, 1
  436. paddd mm7, mm3
  437. /* BOTH CHANNELS */
  438. /* horizontal add */
  439. movq mm0, mm6
  440. punpckhdq mm6, mm7
  441. punpckldq mm0, mm7
  442. paddd mm6, mm0
  443. /* round, shift, clip */
  444. paddd mm6, mm5
  445. psrad mm6, 14
  446. packssdw mm6, mm6
  447. /* bump to next state */
  448. mov edx, nextstate
  449. mov ebx, [edx+4*ebx] // phase = nextstate[phase]
  450. lea edx, [ebx+ebx]
  451. and edx, 0xff<<1
  452. add esi, edx // pcmptr += pcmstep
  453. sub edi, edx // revptr -= pcmstep
  454. mov edx, ebx
  455. shr ebx, 20 // phase
  456. shr edx, 3
  457. and edx, 0xfff<<5 // 32 * idx
  458. lea edx, [edx+2*edx] // 96 * idx
  459. add edx, filter // lwingptr = filter[idx]
  460. movd [ecx], mm6 // *outptr++
  461. // add ecx, 4
  462. add   ecx,outstride
  463. lea eax, [ebx+2*ebx] // 3 * idx
  464. shl eax, 5 // 96 * idx
  465. add eax, filter // rwingptr = filter[idx]
  466. jmp conv_loop
  467. conv_done:
  468. sub ecx, outbuf // outsamps = outptr - outbuf
  469. shr ecx, 1
  470. mov outsamps, ecx
  471. mov pcmptr, esi
  472. mov revptr, edi
  473. mov phase, ebx
  474. mov rwingptr, eax
  475. mov lwingptr, edx
  476. emms
  477. }
  478. /* save filter state */
  479. s->phase = phase;
  480. s->offset = pcmptr - pcmend;
  481. s->rwingptr = rwingptr;
  482. s->lwingptr = lwingptr;
  483. memmove(s->pcmleft-NTAPS, s->pcmleft-NTAPS + insamps/2, NTAPS * sizeof(short));
  484. memmove(s->pcmrght-NTAPS, s->pcmrght-NTAPS + insamps/2, NTAPS * sizeof(short));
  485. // TOCK(outsamps);
  486. return outsamps;
  487. }
  488. int
  489. RAResampleMonoMMX(void *inbuf, int insamps, tConverter *pCvt, short *outbuf, int outstride, void *inst)
  490. {
  491.     state_t *s = (state_t *)inst;
  492. short *pcmptr, *revptr, *pcmend;
  493. short *rwingptr, *lwingptr;
  494. int i, outsamps;
  495. /* local copies */
  496. filtwing *filter = s->filter;
  497. int *nextstate = s->nextstate;
  498. int phase = s->phase;
  499. int round13[2] = { 1<<13, 1<<13 };
  500. // TICK();
  501. outstride *= sizeof(short) ;
  502. /* copy/convert new input */
  503. insamps = pCvt->pfCvt(s->pcmleft,inbuf,insamps,pCvt->pStateMachine) ;
  504. /* create revbuf */
  505. for (i = -insamps; i < NTAPS; i++)
  506. s->revrght[i] = s->pcmleft[-i-1];
  507. /* restore filter state */
  508. pcmptr = s->pcmleft + s->offset - (NTAPS-1);
  509. revptr = s->revrght - s->offset - 1;
  510. pcmend = s->pcmleft + insamps - (NTAPS-1);
  511. rwingptr = s->rwingptr;
  512. lwingptr = s->lwingptr;
  513. __asm {
  514. mov esi, pcmptr
  515. mov edi, revptr
  516. mov ebx, phase
  517. mov ecx, outbuf
  518. mov eax, rwingptr
  519. mov edx, lwingptr
  520. movq mm5, round13
  521. conv_loop: /* while (pcmptr < pcmend) */
  522. cmp esi, pcmend
  523. jae conv_done
  524. /* prime */
  525. movq mm7, [esi+0]
  526. pmaddwd mm7, [eax+0]
  527. movq mm1, [edi+0]
  528. pmaddwd mm1, [edx+0]
  529. movq mm2, [esi+8]
  530. psrad mm7, 8
  531. pmaddwd mm2, [eax+8]
  532. //paddd mm7, mm0
  533. movq mm3, [edi+8]
  534. psrad mm1, 8
  535. pmaddwd mm3, [edx+8]
  536. paddd mm7, mm1
  537. /* kernel */
  538. movq mm0, [esi+16]
  539. psrad mm2, 6
  540. pmaddwd mm0, [eax+16]
  541. paddd mm7, mm2
  542. movq mm1, [edi+16]
  543. psrad mm3, 6
  544. pmaddwd mm1, [edx+16]
  545. paddd mm7, mm3
  546. movq mm2, [esi+24]
  547. psrad mm0, 4
  548. pmaddwd mm2, [eax+24]
  549. paddd mm7, mm0
  550. movq mm3, [edi+24]
  551. psrad mm1, 4
  552. pmaddwd mm3, [edx+24]
  553. paddd mm7, mm1
  554. /* end kernel */
  555. movq mm0, [esi+32]
  556. psrad mm2, 3
  557. pmaddwd mm0, [eax+32]
  558. paddd mm7, mm2
  559. movq mm1, [edi+32]
  560. psrad mm3, 3
  561. pmaddwd mm1, [edx+32]
  562. paddd mm7, mm3
  563. movq mm2, [esi+40]
  564. psrad mm0, 2
  565. pmaddwd mm2, [eax+40]
  566. paddd mm7, mm0
  567. movq mm3, [edi+40]
  568. psrad mm1, 2
  569. pmaddwd mm3, [edx+40]
  570. paddd mm7, mm1
  571. movq mm0, [esi+48]
  572. psrad mm2, 1
  573. pmaddwd mm0, [eax+48]
  574. paddd mm7, mm2
  575. movq mm1, [edi+48]
  576. psrad mm3, 1
  577. pmaddwd mm1, [edx+48]
  578. paddd mm7, mm3
  579. /* acc shift */
  580. psrad mm7, 8
  581. movq mm2, [esi+56]
  582. psrad mm0, 8
  583. pmaddwd mm2, [eax+56]
  584. paddd mm7, mm0
  585. movq mm3, [edi+56]
  586. psrad mm1, 8
  587. pmaddwd mm3, [edx+56]
  588. paddd mm7, mm1
  589. movq mm0, [esi+64]
  590. psrad mm2, 7
  591. pmaddwd mm0, [eax+64]
  592. paddd mm7, mm2
  593. movq mm1, [edi+64]
  594. psrad mm3, 7
  595. pmaddwd mm1, [edx+64]
  596. paddd mm7, mm3
  597. movq mm2, [esi+72]
  598. psrad mm0, 6
  599. pmaddwd mm2, [eax+72]
  600. paddd mm7, mm0
  601. movq mm3, [edi+72]
  602. psrad mm1, 6
  603. pmaddwd mm3, [edx+72]
  604. paddd mm7, mm1
  605. movq mm0, [esi+80]
  606. psrad mm2, 5
  607. pmaddwd mm0, [eax+80]
  608. paddd mm7, mm2
  609. movq mm1, [edi+80]
  610. psrad mm3, 5
  611. pmaddwd mm1, [edx+80]
  612. paddd mm7, mm3
  613. movq mm2, [esi+88]
  614. psrad mm0, 4
  615. pmaddwd mm2, [eax+88]
  616. paddd mm7, mm0
  617. movq mm3, [edi+88]
  618. psrad mm1, 4
  619. pmaddwd mm3, [edx+88]
  620. paddd mm7, mm1
  621. /* flush */
  622. psrad mm2, 1
  623. paddd mm7, mm2
  624. psrad mm3, 1
  625. paddd mm7, mm3
  626. /* horizontal add */
  627. movq mm0, mm7
  628. psrlq mm7, 32
  629. paddd mm7, mm0
  630. /* round, shift, clip */
  631. paddd mm7, mm5
  632. psrad mm7, 14
  633. packssdw mm7, mm7
  634. movd eax, mm7
  635. /* bump to next state */
  636. mov edx, nextstate
  637. mov ebx, [edx+4*ebx] // phase = nextstate[phase]
  638. lea edx, [ebx+ebx]
  639. and edx, 0xff<<1
  640. add esi, edx // pcmptr += pcmstep
  641. sub edi, edx // revptr -= pcmstep
  642. mov edx, ebx
  643. shr ebx, 20 // phase
  644. shr edx, 3
  645. and edx, 0xfff<<5 // 32 * idx
  646. lea edx, [edx+2*edx] // 96 * idx
  647. add edx, filter // lwingptr = filter[idx]
  648. mov word ptr [ecx], ax // *outptr++
  649. // add ecx, 2
  650. add   ecx, outstride
  651. lea eax, [ebx+2*ebx] // 3 * idx
  652. shl eax, 5 // 96 * idx
  653. add eax, filter // rwingptr = filter[idx]
  654. jmp conv_loop
  655. conv_done:
  656. sub ecx, outbuf // outsamps = outptr - outbuf
  657. shr ecx, 1
  658. mov outsamps, ecx
  659. mov pcmptr, esi
  660. mov revptr, edi
  661. mov phase, ebx
  662. mov rwingptr, eax
  663. mov lwingptr, edx
  664. emms
  665. }
  666. /* save filter state */
  667. s->phase = phase;
  668. s->offset = pcmptr - pcmend;
  669. s->rwingptr = rwingptr;
  670. s->lwingptr = lwingptr;
  671. memmove(s->pcmleft-NTAPS, s->pcmleft-NTAPS + insamps, NTAPS * sizeof(short));
  672. // TOCK(outsamps);
  673. return outsamps;
  674. }
  675. #include "mymath.h"
  676. int
  677. RAGetMaxOutputMMX(int insamps, void *inst)
  678. {
  679.     state_t *s = (state_t *)inst;
  680. int inframes, outframes, outsamps;
  681. inframes = (insamps + (s->nchans-1)) / s->nchans;
  682. outframes = (int) myCeil((double)inframes * s->up / s->dn);
  683. outsamps = outframes * s->nchans;
  684. return outsamps;
  685. }
  686. int
  687. RAGetMinInputMMX(int outsamps, void *inst)
  688. {
  689.     state_t *s = (state_t *)inst;
  690. int inframes, outframes, insamps;
  691. outframes = (outsamps + (s->nchans-1)) / s->nchans;
  692. inframes = (int) myCeil((double)outframes * s->dn / s->up);
  693. insamps = inframes * s->nchans;
  694. return insamps;
  695. }
  696. int
  697. RAGetDelayMMX(void *inst)
  698. {
  699. state_t *s = (state_t *)inst;
  700. return (int)(NWING * (float)s->up / s->dn) ;
  701. }
  702. #endif