mmxresample.c
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:18k
源码类别:

Symbian

开发平台:

C/C++

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