snd_mix.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /*
  2. ===========================================================================
  3. Copyright (C) 1999-2005 Id Software, Inc.
  4. This file is part of Quake III Arena source code.
  5. Quake III Arena source code is free software; you can redistribute it
  6. and/or modify it under the terms of the GNU General Public License as
  7. published by the Free Software Foundation; either version 2 of the License,
  8. or (at your option) any later version.
  9. Quake III Arena source code is distributed in the hope that it will be
  10. useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Foobar; if not, write to the Free Software
  15. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  16. ===========================================================================
  17. */
  18. // snd_mix.c -- portable code to mix sounds for snd_dma.c
  19. #include "snd_local.h"
  20. static portable_samplepair_t paintbuffer[PAINTBUFFER_SIZE];
  21. static int snd_vol;
  22. // bk001119 - these not static, required by unix/snd_mixa.s
  23. int* snd_p;
  24. int snd_linear_count;
  25. short* snd_out;
  26. #if !( (defined __linux__ || defined __FreeBSD__ ) && (defined __i386__) ) // rb010123
  27. #if !id386
  28. void S_WriteLinearBlastStereo16 (void)
  29. {
  30. int i;
  31. int val;
  32. for (i=0 ; i<snd_linear_count ; i+=2)
  33. {
  34. val = snd_p[i]>>8;
  35. if (val > 0x7fff)
  36. snd_out[i] = 0x7fff;
  37. else if (val < -32768)
  38. snd_out[i] = -32768;
  39. else
  40. snd_out[i] = val;
  41. val = snd_p[i+1]>>8;
  42. if (val > 0x7fff)
  43. snd_out[i+1] = 0x7fff;
  44. else if (val < -32768)
  45. snd_out[i+1] = -32768;
  46. else
  47. snd_out[i+1] = val;
  48. }
  49. }
  50. #else
  51. __declspec( naked ) void S_WriteLinearBlastStereo16 (void)
  52. {
  53. __asm {
  54. push edi
  55. push ebx
  56. mov ecx,ds:dword ptr[snd_linear_count]
  57. mov ebx,ds:dword ptr[snd_p]
  58. mov edi,ds:dword ptr[snd_out]
  59. LWLBLoopTop:
  60. mov eax,ds:dword ptr[-8+ebx+ecx*4]
  61. sar eax,8
  62. cmp eax,07FFFh
  63. jg LClampHigh
  64. cmp eax,0FFFF8000h
  65. jnl LClampDone
  66. mov eax,0FFFF8000h
  67. jmp LClampDone
  68. LClampHigh:
  69. mov eax,07FFFh
  70. LClampDone:
  71. mov edx,ds:dword ptr[-4+ebx+ecx*4]
  72. sar edx,8
  73. cmp edx,07FFFh
  74. jg LClampHigh2
  75. cmp edx,0FFFF8000h
  76. jnl LClampDone2
  77. mov edx,0FFFF8000h
  78. jmp LClampDone2
  79. LClampHigh2:
  80. mov edx,07FFFh
  81. LClampDone2:
  82. shl edx,16
  83. and eax,0FFFFh
  84. or edx,eax
  85. mov ds:dword ptr[-4+edi+ecx*2],edx
  86. sub ecx,2
  87. jnz LWLBLoopTop
  88. pop ebx
  89. pop edi
  90. ret
  91. }
  92. }
  93. #endif
  94. #else
  95. // forward declare, implementation somewhere else
  96. void S_WriteLinearBlastStereo16 (void);
  97. #endif
  98. void S_TransferStereo16 (unsigned long *pbuf, int endtime)
  99. {
  100. int lpos;
  101. int ls_paintedtime;
  102. snd_p = (int *) paintbuffer;
  103. ls_paintedtime = s_paintedtime;
  104. while (ls_paintedtime < endtime)
  105. {
  106. // handle recirculating buffer issues
  107. lpos = ls_paintedtime & ((dma.samples>>1)-1);
  108. snd_out = (short *) pbuf + (lpos<<1);
  109. snd_linear_count = (dma.samples>>1) - lpos;
  110. if (ls_paintedtime + snd_linear_count > endtime)
  111. snd_linear_count = endtime - ls_paintedtime;
  112. snd_linear_count <<= 1;
  113. // write a linear blast of samples
  114. S_WriteLinearBlastStereo16 ();
  115. snd_p += snd_linear_count;
  116. ls_paintedtime += (snd_linear_count>>1);
  117. }
  118. }
  119. /*
  120. ===================
  121. S_TransferPaintBuffer
  122. ===================
  123. */
  124. void S_TransferPaintBuffer(int endtime)
  125. {
  126. int out_idx;
  127. int count;
  128. int out_mask;
  129. int *p;
  130. int step;
  131. int val;
  132. unsigned long *pbuf;
  133. pbuf = (unsigned long *)dma.buffer;
  134. if ( s_testsound->integer ) {
  135. int i;
  136. int count;
  137. // write a fixed sine wave
  138. count = (endtime - s_paintedtime);
  139. for (i=0 ; i<count ; i++)
  140. paintbuffer[i].left = paintbuffer[i].right = sin((s_paintedtime+i)*0.1)*20000*256;
  141. }
  142. if (dma.samplebits == 16 && dma.channels == 2)
  143. { // optimized case
  144. S_TransferStereo16 (pbuf, endtime);
  145. }
  146. else
  147. { // general case
  148. p = (int *) paintbuffer;
  149. count = (endtime - s_paintedtime) * dma.channels;
  150. out_mask = dma.samples - 1;
  151. out_idx = s_paintedtime * dma.channels & out_mask;
  152. step = 3 - dma.channels;
  153. if (dma.samplebits == 16)
  154. {
  155. short *out = (short *) pbuf;
  156. while (count--)
  157. {
  158. val = *p >> 8;
  159. p+= step;
  160. if (val > 0x7fff)
  161. val = 0x7fff;
  162. else if (val < -32768)
  163. val = -32768;
  164. out[out_idx] = val;
  165. out_idx = (out_idx + 1) & out_mask;
  166. }
  167. }
  168. else if (dma.samplebits == 8)
  169. {
  170. unsigned char *out = (unsigned char *) pbuf;
  171. while (count--)
  172. {
  173. val = *p >> 8;
  174. p+= step;
  175. if (val > 0x7fff)
  176. val = 0x7fff;
  177. else if (val < -32768)
  178. val = -32768;
  179. out[out_idx] = (val>>8) + 128;
  180. out_idx = (out_idx + 1) & out_mask;
  181. }
  182. }
  183. }
  184. }
  185. /*
  186. ===============================================================================
  187. CHANNEL MIXING
  188. ===============================================================================
  189. */
  190. static void S_PaintChannelFrom16( channel_t *ch, const sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
  191. int data, aoff, boff;
  192. int leftvol, rightvol;
  193. int i, j;
  194. portable_samplepair_t *samp;
  195. sndBuffer *chunk;
  196. short *samples;
  197. float ooff, fdata, fdiv, fleftvol, frightvol;
  198. samp = &paintbuffer[ bufferOffset ];
  199. if (ch->doppler) {
  200. sampleOffset = sampleOffset*ch->oldDopplerScale;
  201. }
  202. chunk = sc->soundData;
  203. while (sampleOffset>=SND_CHUNK_SIZE) {
  204. chunk = chunk->next;
  205. sampleOffset -= SND_CHUNK_SIZE;
  206. if (!chunk) {
  207. chunk = sc->soundData;
  208. }
  209. }
  210. if (!ch->doppler || ch->dopplerScale==1.0f) {
  211. #if idppc_altivec
  212. vector signed short volume_vec;
  213. vector unsigned int volume_shift;
  214. int vectorCount, samplesLeft, chunkSamplesLeft;
  215. #endif
  216. leftvol = ch->leftvol*snd_vol;
  217. rightvol = ch->rightvol*snd_vol;
  218. samples = chunk->sndChunk;
  219. #if idppc_altivec
  220. ((short *)&volume_vec)[0] = leftvol;
  221. ((short *)&volume_vec)[1] = leftvol;
  222. ((short *)&volume_vec)[4] = leftvol;
  223. ((short *)&volume_vec)[5] = leftvol;
  224. ((short *)&volume_vec)[2] = rightvol;
  225. ((short *)&volume_vec)[3] = rightvol;
  226. ((short *)&volume_vec)[6] = rightvol;
  227. ((short *)&volume_vec)[7] = rightvol;
  228. volume_shift = vec_splat_u32(8);
  229. i = 0;
  230. while(i < count) {
  231. /* Try to align destination to 16-byte boundary */
  232. while(i < count && (((unsigned long)&samp[i] & 0x1f) || ((count-i) < 8) || ((SND_CHUNK_SIZE - sampleOffset) < 8))) {
  233. data = samples[sampleOffset++];
  234. samp[i].left += (data * leftvol)>>8;
  235. samp[i].right += (data * rightvol)>>8;
  236. if (sampleOffset == SND_CHUNK_SIZE) {
  237. chunk = chunk->next;
  238. samples = chunk->sndChunk;
  239. sampleOffset = 0;
  240. }
  241. i++;
  242. }
  243. /* Destination is now aligned. Process as many 8-sample
  244. chunks as we can before we run out of room from the current
  245. sound chunk. We do 8 per loop to avoid extra source data reads. */
  246. samplesLeft = count - i;
  247. chunkSamplesLeft = SND_CHUNK_SIZE - sampleOffset;
  248. if(samplesLeft > chunkSamplesLeft)
  249. samplesLeft = chunkSamplesLeft;
  250. vectorCount = samplesLeft / 8;
  251. if(vectorCount)
  252. {
  253. vector unsigned char tmp;
  254. vector short s0, s1, sampleData0, sampleData1;
  255. vector short samples0, samples1;
  256. vector signed int left0, right0;
  257. vector signed int merge0, merge1;
  258. vector signed int d0, d1, d2, d3;
  259. vector unsigned char samplePermute0 =
  260. (vector unsigned char)(0, 1, 4, 5, 0, 1, 4, 5, 2, 3, 6, 7, 2, 3, 6, 7);
  261. vector unsigned char samplePermute1 =
  262. (vector unsigned char)(8, 9, 12, 13, 8, 9, 12, 13, 10, 11, 14, 15, 10, 11, 14, 15);
  263. vector unsigned char loadPermute0, loadPermute1;
  264. // Rather than permute the vectors after we load them to do the sample
  265. // replication and rearrangement, we permute the alignment vector so
  266. // we do everything in one step below and avoid data shuffling.
  267. tmp = vec_lvsl(0,&samples[sampleOffset]);
  268. loadPermute0 = vec_perm(tmp,tmp,samplePermute0);
  269. loadPermute1 = vec_perm(tmp,tmp,samplePermute1);
  270. s0 = *(vector short *)&samples[sampleOffset];
  271. while(vectorCount)
  272. {
  273. /* Load up source (16-bit) sample data */
  274. s1 = *(vector short *)&samples[sampleOffset+7];
  275. /* Load up destination sample data */
  276. d0 = *(vector signed int *)&samp[i];
  277. d1 = *(vector signed int *)&samp[i+2];
  278. d2 = *(vector signed int *)&samp[i+4];
  279. d3 = *(vector signed int *)&samp[i+6];
  280. sampleData0 = vec_perm(s0,s1,loadPermute0);
  281. sampleData1 = vec_perm(s0,s1,loadPermute1);
  282. merge0 = vec_mule(sampleData0,volume_vec);
  283. merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
  284. merge1 = vec_mulo(sampleData0,volume_vec);
  285. merge1 = vec_sra(merge1,volume_shift);
  286. d0 = vec_add(merge0,d0);
  287. d1 = vec_add(merge1,d1);
  288. merge0 = vec_mule(sampleData1,volume_vec);
  289. merge0 = vec_sra(merge0,volume_shift); /* Shift down to proper range */
  290. merge1 = vec_mulo(sampleData1,volume_vec);
  291. merge1 = vec_sra(merge1,volume_shift);
  292. d2 = vec_add(merge0,d2);
  293. d3 = vec_add(merge1,d3);
  294. /* Store destination sample data */
  295. *(vector signed int *)&samp[i] = d0;
  296. *(vector signed int *)&samp[i+2] = d1;
  297. *(vector signed int *)&samp[i+4] = d2;
  298. *(vector signed int *)&samp[i+6] = d3;
  299. i += 8;
  300. vectorCount--;
  301. s0 = s1;
  302. sampleOffset += 8;
  303. }
  304. if (sampleOffset == SND_CHUNK_SIZE) {
  305. chunk = chunk->next;
  306. samples = chunk->sndChunk;
  307. sampleOffset = 0;
  308. }
  309. }
  310. }
  311. #else
  312. for ( i=0 ; i<count ; i++ ) {
  313. data = samples[sampleOffset++];
  314. samp[i].left += (data * leftvol)>>8;
  315. samp[i].right += (data * rightvol)>>8;
  316. if (sampleOffset == SND_CHUNK_SIZE) {
  317. chunk = chunk->next;
  318. samples = chunk->sndChunk;
  319. sampleOffset = 0;
  320. }
  321. }
  322. #endif
  323. } else {
  324. fleftvol = ch->leftvol*snd_vol;
  325. frightvol = ch->rightvol*snd_vol;
  326. ooff = sampleOffset;
  327. samples = chunk->sndChunk;
  328. for ( i=0 ; i<count ; i++ ) {
  329. aoff = ooff;
  330. ooff = ooff + ch->dopplerScale;
  331. boff = ooff;
  332. fdata = 0;
  333. for (j=aoff; j<boff; j++) {
  334. if (j == SND_CHUNK_SIZE) {
  335. chunk = chunk->next;
  336. if (!chunk) {
  337. chunk = sc->soundData;
  338. }
  339. samples = chunk->sndChunk;
  340. ooff -= SND_CHUNK_SIZE;
  341. }
  342. fdata += samples[j&(SND_CHUNK_SIZE-1)];
  343. }
  344. fdiv = 256 * (boff-aoff);
  345. samp[i].left += (fdata * fleftvol)/fdiv;
  346. samp[i].right += (fdata * frightvol)/fdiv;
  347. }
  348. }
  349. }
  350. void S_PaintChannelFromWavelet( channel_t *ch, sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
  351. int data;
  352. int leftvol, rightvol;
  353. int i;
  354. portable_samplepair_t *samp;
  355. sndBuffer *chunk;
  356. short *samples;
  357. leftvol = ch->leftvol*snd_vol;
  358. rightvol = ch->rightvol*snd_vol;
  359. i = 0;
  360. samp = &paintbuffer[ bufferOffset ];
  361. chunk = sc->soundData;
  362. while (sampleOffset>=(SND_CHUNK_SIZE_FLOAT*4)) {
  363. chunk = chunk->next;
  364. sampleOffset -= (SND_CHUNK_SIZE_FLOAT*4);
  365. i++;
  366. }
  367. if (i!=sfxScratchIndex || sfxScratchPointer != sc) {
  368. S_AdpcmGetSamples( chunk, sfxScratchBuffer );
  369. sfxScratchIndex = i;
  370. sfxScratchPointer = sc;
  371. }
  372. samples = sfxScratchBuffer;
  373. for ( i=0 ; i<count ; i++ ) {
  374. data = samples[sampleOffset++];
  375. samp[i].left += (data * leftvol)>>8;
  376. samp[i].right += (data * rightvol)>>8;
  377. if (sampleOffset == SND_CHUNK_SIZE*2) {
  378. chunk = chunk->next;
  379. decodeWavelet(chunk, sfxScratchBuffer);
  380. sfxScratchIndex++;
  381. sampleOffset = 0;
  382. }
  383. }
  384. }
  385. void S_PaintChannelFromADPCM( channel_t *ch, sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
  386. int data;
  387. int leftvol, rightvol;
  388. int i;
  389. portable_samplepair_t *samp;
  390. sndBuffer *chunk;
  391. short *samples;
  392. leftvol = ch->leftvol*snd_vol;
  393. rightvol = ch->rightvol*snd_vol;
  394. i = 0;
  395. samp = &paintbuffer[ bufferOffset ];
  396. chunk = sc->soundData;
  397. if (ch->doppler) {
  398. sampleOffset = sampleOffset*ch->oldDopplerScale;
  399. }
  400. while (sampleOffset>=(SND_CHUNK_SIZE*4)) {
  401. chunk = chunk->next;
  402. sampleOffset -= (SND_CHUNK_SIZE*4);
  403. i++;
  404. }
  405. if (i!=sfxScratchIndex || sfxScratchPointer != sc) {
  406. S_AdpcmGetSamples( chunk, sfxScratchBuffer );
  407. sfxScratchIndex = i;
  408. sfxScratchPointer = sc;
  409. }
  410. samples = sfxScratchBuffer;
  411. for ( i=0 ; i<count ; i++ ) {
  412. data = samples[sampleOffset++];
  413. samp[i].left += (data * leftvol)>>8;
  414. samp[i].right += (data * rightvol)>>8;
  415. if (sampleOffset == SND_CHUNK_SIZE*4) {
  416. chunk = chunk->next;
  417. S_AdpcmGetSamples( chunk, sfxScratchBuffer);
  418. sampleOffset = 0;
  419. sfxScratchIndex++;
  420. }
  421. }
  422. }
  423. void S_PaintChannelFromMuLaw( channel_t *ch, sfx_t *sc, int count, int sampleOffset, int bufferOffset ) {
  424. int data;
  425. int leftvol, rightvol;
  426. int i;
  427. portable_samplepair_t *samp;
  428. sndBuffer *chunk;
  429. byte *samples;
  430. float ooff;
  431. leftvol = ch->leftvol*snd_vol;
  432. rightvol = ch->rightvol*snd_vol;
  433. samp = &paintbuffer[ bufferOffset ];
  434. chunk = sc->soundData;
  435. while (sampleOffset>=(SND_CHUNK_SIZE*2)) {
  436. chunk = chunk->next;
  437. sampleOffset -= (SND_CHUNK_SIZE*2);
  438. if (!chunk) {
  439. chunk = sc->soundData;
  440. }
  441. }
  442. if (!ch->doppler) {
  443. samples = (byte *)chunk->sndChunk + sampleOffset;
  444. for ( i=0 ; i<count ; i++ ) {
  445. data = mulawToShort[*samples];
  446. samp[i].left += (data * leftvol)>>8;
  447. samp[i].right += (data * rightvol)>>8;
  448. samples++;
  449. if (samples == (byte *)chunk->sndChunk+(SND_CHUNK_SIZE*2)) {
  450. chunk = chunk->next;
  451. samples = (byte *)chunk->sndChunk;
  452. }
  453. }
  454. } else {
  455. ooff = sampleOffset;
  456. samples = (byte *)chunk->sndChunk;
  457. for ( i=0 ; i<count ; i++ ) {
  458. data = mulawToShort[samples[(int)(ooff)]];
  459. ooff = ooff + ch->dopplerScale;
  460. samp[i].left += (data * leftvol)>>8;
  461. samp[i].right += (data * rightvol)>>8;
  462. if (ooff >= SND_CHUNK_SIZE*2) {
  463. chunk = chunk->next;
  464. if (!chunk) {
  465. chunk = sc->soundData;
  466. }
  467. samples = (byte *)chunk->sndChunk;
  468. ooff = 0.0;
  469. }
  470. }
  471. }
  472. }
  473. /*
  474. ===================
  475. S_PaintChannels
  476. ===================
  477. */
  478. void S_PaintChannels( int endtime ) {
  479. int i;
  480. int end;
  481. channel_t *ch;
  482. sfx_t *sc;
  483. int ltime, count;
  484. int sampleOffset;
  485. snd_vol = s_volume->value*255;
  486. //Com_Printf ("%i to %i\n", s_paintedtime, endtime);
  487. while ( s_paintedtime < endtime ) {
  488. // if paintbuffer is smaller than DMA buffer
  489. // we may need to fill it multiple times
  490. end = endtime;
  491. if ( endtime - s_paintedtime > PAINTBUFFER_SIZE ) {
  492. end = s_paintedtime + PAINTBUFFER_SIZE;
  493. }
  494. // clear the paint buffer to either music or zeros
  495. if ( s_rawend < s_paintedtime ) {
  496. if ( s_rawend ) {
  497. //Com_DPrintf ("background sound underrun\n");
  498. }
  499. Com_Memset(paintbuffer, 0, (end - s_paintedtime) * sizeof(portable_samplepair_t));
  500. } else {
  501. // copy from the streaming sound source
  502. int s;
  503. int stop;
  504. stop = (end < s_rawend) ? end : s_rawend;
  505. for ( i = s_paintedtime ; i < stop ; i++ ) {
  506. s = i&(MAX_RAW_SAMPLES-1);
  507. paintbuffer[i-s_paintedtime] = s_rawsamples[s];
  508. }
  509. // if (i != end)
  510. // Com_Printf ("partial stream\n");
  511. // else
  512. // Com_Printf ("full stream\n");
  513. for ( ; i < end ; i++ ) {
  514. paintbuffer[i-s_paintedtime].left =
  515. paintbuffer[i-s_paintedtime].right = 0;
  516. }
  517. }
  518. // paint in the channels.
  519. ch = s_channels;
  520. for ( i = 0; i < MAX_CHANNELS ; i++, ch++ ) {
  521. if ( !ch->thesfx || (ch->leftvol<0.25 && ch->rightvol<0.25 )) {
  522. continue;
  523. }
  524. ltime = s_paintedtime;
  525. sc = ch->thesfx;
  526. sampleOffset = ltime - ch->startSample;
  527. count = end - ltime;
  528. if ( sampleOffset + count > sc->soundLength ) {
  529. count = sc->soundLength - sampleOffset;
  530. }
  531. if ( count > 0 ) {
  532. if( sc->soundCompressionMethod == 1) {
  533. S_PaintChannelFromADPCM (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  534. } else if( sc->soundCompressionMethod == 2) {
  535. S_PaintChannelFromWavelet (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  536. } else if( sc->soundCompressionMethod == 3) {
  537. S_PaintChannelFromMuLaw (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  538. } else {
  539. S_PaintChannelFrom16 (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  540. }
  541. }
  542. }
  543. // paint in the looped channels.
  544. ch = loop_channels;
  545. for ( i = 0; i < numLoopChannels ; i++, ch++ ) {
  546. if ( !ch->thesfx || (!ch->leftvol && !ch->rightvol )) {
  547. continue;
  548. }
  549. ltime = s_paintedtime;
  550. sc = ch->thesfx;
  551. if (sc->soundData==NULL || sc->soundLength==0) {
  552. continue;
  553. }
  554. // we might have to make two passes if it
  555. // is a looping sound effect and the end of
  556. // the sample is hit
  557. do {
  558. sampleOffset = (ltime % sc->soundLength);
  559. count = end - ltime;
  560. if ( sampleOffset + count > sc->soundLength ) {
  561. count = sc->soundLength - sampleOffset;
  562. }
  563. if ( count > 0 ) {
  564. if( sc->soundCompressionMethod == 1) {
  565. S_PaintChannelFromADPCM (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  566. } else if( sc->soundCompressionMethod == 2) {
  567. S_PaintChannelFromWavelet (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  568. } else if( sc->soundCompressionMethod == 3) {
  569. S_PaintChannelFromMuLaw (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  570. } else {
  571. S_PaintChannelFrom16 (ch, sc, count, sampleOffset, ltime - s_paintedtime);
  572. }
  573. ltime += count;
  574. }
  575. } while ( ltime < end);
  576. }
  577. // transfer out according to DMA format
  578. S_TransferPaintBuffer( end );
  579. s_paintedtime = end;
  580. }
  581. }