freeaudio.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590
  1. // freeaudio.cpp
  2. // 2007.02.15 new dsound device, readpointer and tidy up SA
  3. // 2006.05.26 overflow handling for winmmdevice waveOutGetPosition
  4. // 2006.04.26 winmmdevice doubles latency for windows98
  5. // 2006.04.26 fixed recycling of autostopped channels
  6. // 2006.01.17 fixed recycling of stopped channels
  7. // 2005.11.22 fixed freepool sounds not resetting parameters - thanks to Fetze
  8. // 2005.09.13 new ALSA code for Linux - thanks to Craig Kiesau
  9. // 2005.08.05 new single looped buffer with timer callback for win32mmdevice
  10. // 2005.07.04 reduced audio latency
  11. // 2005.06.17 fixed memory leak in sound allocation
  12. // 2005.05.23 removed output transitions for queued/paused sounds
  13. // 2005.04.05 added AudioOutputUnitStop call for apple close
  14. // 2005.01.07 fixed up audio hardware failure handling
  15. // 2004.08.16 fixed channelstatus, allocchannel now always returns unique handle
  16. // 2004.06.04 added linux drivers
  17. // 2004.03.19 new ,loop parameter support in loadsound(file,looping)
  18. // 2004.03.02 dynamic sounds release temp channel when recycled SA
  19. // 2004.02.06 initial single file release SA
  20. #include "freeaudio.h"
  21. #include <stdlib.h>
  22. #include <stdio.h>
  23. #include <memory.h>
  24. //static audiodevice *audio=0;
  25. mixer::mixer(int bufflen):output(0)
  26. {
  27. int i;
  28. size=bufflen;
  29. playlist=0;
  30. // freelist=0;
  31. mbuff=new int[bufflen];
  32. for (i=0;i<size;i++) mbuff[i]=0;
  33. freq=0;channels=0;
  34. }
  35. sound *mixer::allocsound(output *out)
  36. {
  37. sound *s;
  38. s=freelist.pull(); //getfreesound();
  39. if (s){
  40. if (io && s->channel){
  41. io->freechannel(s->channel);
  42. s->channel=0;
  43. }
  44. }else{
  45. s=new sound(this);
  46. }
  47. if (out){
  48. s->resetrate(out->getrate(1));
  49. s->resetvolume(out->getvolume(1));
  50. s->resetpan(out->getpan(1));
  51. s->resetdepth(out->getdepth(1));
  52. }else{
  53. s->resetrate(65536);
  54. s->resetvolume(VOLUMEONE);
  55. s->resetpan(0);
  56. s->resetdepth(0);
  57. }
  58. return s;
  59. }
  60. sound *mixer::play(sample *sam,output *out,int state)
  61. {
  62. sound *s;
  63. if (!sam) return 0;
  64. if (sam->channels==0) return 0;
  65. if (freq==0) return 0;
  66. s=allocsound(out);
  67. sam->refcount++;
  68. s->status=state;
  69. s->samp=sam;
  70. s->pos64=0;
  71. s->mix64=0;
  72. s->starttime=bbMilliSecs();
  73. startlist.push(s);
  74. return s;
  75. }
  76. sound::sound(output *p):output(p){
  77. status=STOPPED;
  78. next=0;
  79. resetrate(65536);
  80. resetvolume(VOLUMEONE);
  81. resetpan(0);
  82. resetdepth(0);
  83. }
  84. void sound::flush(){
  85. if (status==STREAMING && samp){
  86. int readpos=samp->writepos;
  87. mix64=((i64)(readpos*samp->channels))<<32;
  88. pos64=((i64)((readpos%samp->samples)*samp->channels))<<32;
  89. }
  90. }
  91. // mix audio stream at rate,amplitude with linear interpolation
  92. #define blend(a,b,c) (a+((((b)-(a))*((((int)(c))>>16)&65535))>>16))
  93. #define ublend(a,b,c) ( ((a-128)<<8) + ((((b)-(a))*((((int)(c))>>16)&65535))>>8) )
  94. /*
  95. int ublend(u8 a,u8 b,int c)
  96. {
  97. int a0=a-128;
  98. int b0=b-128;
  99. return blend(a0,b0,c);
  100. }
  101. */
  102. int sound::mix(int *b,int size) //returns 0=ok 1=releasechannel
  103. {
  104. short *s;
  105. u8 *c;
  106. int t,n;
  107. int count;
  108. short pan,depth;
  109. short right,left;
  110. int amp0,amp1;
  111. i64 freq0,freq1;
  112. i64 len64,freq64;
  113. int p;
  114. if (status==STOPPED) return 1;
  115. if (status&PAUSED) return -2;
  116. if (status==FREE) return -1;
  117. count=size/2;
  118. if (delay)
  119. {
  120. if (delay>=count)
  121. {
  122. delay-=count;
  123. return 0;
  124. }
  125. if (delay>0)
  126. {
  127. count-=delay;
  128. b+=delay*2;
  129. }
  130. delay=0;
  131. }
  132. freq0=((i64)samp->freq*getrate(0))/44100;
  133. freq1=((i64)samp->freq*getrate(1))/44100;
  134. n=(freq0*count)>>16;
  135. int readpos=mix64>>32;
  136. if ((status&STREAMING) && (readpos+n>samp->writepos)) return 0;
  137. amp0=getvolume(0);
  138. amp1=getvolume(1);
  139. pan=getpan(1);
  140. depth=getdepth(1);
  141. len64=((i64)(samp->samples*samp->channels))<<32;
  142. if ((amp0==amp1) && (freq0==freq1))
  143. {
  144. freq64=(freq0*samp->channels)<<16;
  145. if (amp1==0) //muted
  146. {
  147. currentvolume=0;
  148. pos64+=freq64*count;
  149. mix64+=freq64*count;
  150. while (pos64>=len64)
  151. {
  152. if (status&LOOPING) pos64-=len64;else return 1;
  153. }
  154. return 0;
  155. }
  156. right=left=amp0;
  157. if (pan>0) left=(left*(4096-pan))>>12;
  158. if (pan<0) right=(right*(4096+pan))>>12;
  159. if (depth<0) right=-right;
  160. if (samp->bits==8)
  161. {
  162. c=(u8 *)samp->data;
  163. if (samp->channels==1)
  164. {
  165. while (count-->0)
  166. {
  167. p=(int)(pos64>>32);
  168. t=ublend(c[p],c[p+1],pos64);
  169. mix64+=freq64;
  170. pos64+=freq64;
  171. *b+++=(t*left)>>8;
  172. *b+++=(t*right)>>8;
  173. while (pos64>=len64)
  174. {
  175. if (status&LOOPING) pos64-=len64;else return 1;
  176. }
  177. }
  178. }
  179. else
  180. {
  181. while (count-->0)
  182. {
  183. p=(int)(pos64>>32)&-2;
  184. *b+++=(ublend(c[p+0],c[p+2],pos64>>1)*left)>>8;
  185. *b+++=(ublend(c[p+1],c[p+3],pos64>>1)*right)>>8;
  186. pos64+=freq64;
  187. mix64+=freq64;
  188. while (pos64>=len64)
  189. {
  190. if (status&LOOPING) pos64-=len64;else return 1;
  191. }
  192. }
  193. }
  194. }
  195. else
  196. {
  197. s=(short *)samp->data;
  198. if (samp->channels==1)
  199. {
  200. while (count-->0)
  201. {
  202. p=(int)(pos64>>32);
  203. t=blend(s[p],s[p+1],pos64);
  204. mix64+=freq64;
  205. pos64+=freq64;
  206. *b+++=(t*left)>>8;
  207. *b+++=(t*right)>>8;
  208. while (pos64>=len64)
  209. {
  210. if (status&LOOPING)
  211. {
  212. pos64-=len64;
  213. }
  214. else
  215. {
  216. return 1;
  217. }
  218. }
  219. }
  220. }
  221. else
  222. {
  223. while (count-->0)
  224. {
  225. p=(int)(pos64>>32)&-2;
  226. *b+++=(blend(s[p+0],s[p+2],pos64>>1)*left)>>8;
  227. *b+++=(blend(s[p+1],s[p+3],pos64>>1)*right)>>8;
  228. mix64+=freq64;
  229. pos64+=freq64;
  230. while (pos64>=len64)
  231. {
  232. if (status&LOOPING) pos64-=len64;else return 1;
  233. }
  234. }
  235. }
  236. }
  237. return 0;
  238. }
  239. else //dynamice volume|frequency
  240. {
  241. int v1,v2,vd;
  242. i64 f1,f2,fd;
  243. v1=amp0<<8;
  244. v2=amp1<<8;
  245. vd=(v2-v1)/count;
  246. f1=(freq0*samp->channels)<<16;
  247. f2=(freq1*samp->channels)<<16;
  248. fd=(f2-f1)/count;
  249. currentvolume=targetvolume;
  250. currentrate=targetrate;
  251. if (samp->bits==8)
  252. {
  253. c=(u8 *)samp->data;
  254. if (samp->channels==1)
  255. {
  256. while (count-->0)
  257. {
  258. left=right=v1>>8;
  259. if (pan>0) left=(left*(4096-pan))>>12;
  260. if (pan<0) right=(right*(4096+pan))>>12;
  261. p=(int)(pos64>>32);
  262. t=ublend(c[p],c[p+1],pos64);
  263. *b+++=(left*t)>>8;
  264. *b+++=(right*t)>>8;
  265. v1+=vd;
  266. pos64+=f1;
  267. mix64+=f1;
  268. f1+=fd;
  269. while (pos64>=len64)
  270. {
  271. if (status&LOOPING) pos64-=len64;else return 1;
  272. }
  273. }
  274. }
  275. else
  276. {
  277. while (count-->0)
  278. {
  279. left=right=v1>>8;
  280. if (pan>0) left=(left*(4096-pan))>>12;
  281. if (pan<0) right=(right*(4096+pan))>>12;
  282. if (depth<0) right=-right;
  283. p=(int)(pos64>>32)&-2;
  284. *b+++=(ublend(c[p+0],c[p+2],pos64>>1)*left)>>8;
  285. *b+++=(ublend(c[p+1],c[p+3],pos64>>1)*right)>>8;
  286. v1+=vd;
  287. pos64+=f1;
  288. mix64+=f1;
  289. f1+=fd;
  290. while (pos64>=len64)
  291. {
  292. if (status&LOOPING) pos64-=len64;else return 1;
  293. }
  294. }
  295. }
  296. }
  297. else
  298. {
  299. s=(short *)samp->data;
  300. if (samp->channels==1)
  301. {
  302. while (count-->0)
  303. {
  304. left=right=v1>>8;
  305. if (pan>0) left=(left*(4096-pan))>>12;
  306. if (pan<0) right=(right*(4096+pan))>>12;
  307. if (depth<0) right=-right;
  308. p=(int)(pos64>>32);
  309. t=blend(s[p],s[p+1],pos64);
  310. *b+++=(t*left)>>8;
  311. *b+++=(t*right)>>8;
  312. v1+=vd;
  313. mix64+=f1;
  314. pos64+=f1;
  315. f1+=fd;
  316. while (pos64>=len64)
  317. {
  318. if (status&LOOPING) pos64-=len64;else return 1;
  319. }
  320. }
  321. }
  322. else
  323. {
  324. while (count-->0)
  325. {
  326. left=right=v1>>8;
  327. if (pan>0) left=(left*(4096-pan))>>12;
  328. if (pan<0) right=(right*(4096+pan))>>12;
  329. if (depth<0) right=-right;
  330. p=(int)(pos64>>32)&-2;
  331. *b+++=(blend(s[p+0],s[p+2],pos64>>1)*left)>>8;
  332. *b+++=(blend(s[p+1],s[p+3],pos64>>1)*right)>>8;
  333. v1+=vd;
  334. mix64+=f1;
  335. pos64+=f1;
  336. f1+=fd;
  337. while (pos64>=len64)
  338. {
  339. if (status&LOOPING) pos64-=len64;else return 1;
  340. }
  341. }
  342. }
  343. }
  344. return 0;
  345. }
  346. }
  347. void mixer::releaseall()
  348. {
  349. sound *s;
  350. while (s=playlist)
  351. {
  352. playlist=s->next;
  353. releasesound(s);
  354. }
  355. }
  356. void mixer::releasesound(sound *s) // should only be called by mix
  357. {
  358. s->samp->free();
  359. s->samp=0;
  360. freelist.push(s);
  361. }
  362. void mixer::mix(int count)
  363. {
  364. sound *sptr,*tptr,**lptr;
  365. while (sptr=startlist.pull())
  366. {
  367. sptr->next=playlist;
  368. playlist=sptr;
  369. int skip=20+sptr->starttime-bbMilliSecs();
  370. if (skip<0) skip=0;
  371. skip=(skip*freq)/1000;
  372. sptr->delay=skip;
  373. }
  374. sptr=playlist;
  375. lptr=&playlist;
  376. while (sptr)
  377. {
  378. int res=sptr->mix(mbuff,count); //,count
  379. switch (res)
  380. {
  381. case 0:
  382. lptr=&sptr->next;
  383. sptr=sptr->next;
  384. break;
  385. case 1: //STOP
  386. if (sptr->recycle){
  387. sptr->status=output::FREE; //dynamic
  388. tptr=sptr;
  389. *lptr=sptr=sptr->next;
  390. releasesound(tptr);
  391. }else{
  392. sptr->status=output::STOPPED;
  393. lptr=&sptr->next;
  394. sptr=sptr->next;
  395. }
  396. break;
  397. case -1: //FREE
  398. tptr=sptr;
  399. *lptr=sptr=sptr->next;
  400. releasesound(tptr);
  401. break;
  402. case -2: //PAUSED
  403. lptr=&sptr->next;
  404. sptr=sptr->next;
  405. break;
  406. }
  407. }
  408. }
  409. void mixer::mix8(u8 *abuff,int count)
  410. {
  411. int i,j;
  412. int *tptr;
  413. if (count==0) count=size;
  414. mix(count);
  415. tptr=mbuff;
  416. for (i=0;i<count;i++)
  417. {
  418. j=((*tptr)>>16)+0x80;
  419. if (j & 0xffffff00) {if (j<0) j=0;else j=0xff;}
  420. *abuff++=j;
  421. *tptr++=0;
  422. }
  423. }
  424. void mixer::mix16(short *d,int count)
  425. {
  426. int *tptr;
  427. if (count==0) count=size;
  428. mix(count);
  429. tptr=mbuff;
  430. for (int i=0;i<count;i++)
  431. {
  432. *d++=BND(*tptr>>4,-32768,32767);
  433. *tptr++=0;
  434. }
  435. }
  436. void mixer::mix16s(short *dd,int count)
  437. {
  438. int *d,*tptr;
  439. if (count==0) count=size;
  440. mix(count);
  441. d=(int*)dd;
  442. tptr=mbuff;
  443. for (int i=0;i<count;i++) //ll;i++)
  444. {
  445. int t=*tptr>>8;
  446. int p=*d;
  447. short s1=p;
  448. u32 p1=BND(s1+t,-32768,32767);
  449. u32 p2=BND((p>>16)+t,-32768,32767);
  450. *d++=(p1&0xffff)+(p2<<16);
  451. *tptr++=0;
  452. }
  453. }
  454. int sample::init(int n,int f,int c,int b,void *_data)
  455. {
  456. freq=f;
  457. channels=c;
  458. bits=b;
  459. refcount=1;
  460. if (b<8) b=8; //single bit handler
  461. samplesize=channels*b/8;
  462. samples=n;//size/samplesize;
  463. sizebytes=n*samplesize;
  464. if (_data){
  465. capacity=0;
  466. data=_data;
  467. }else{
  468. capacity=sizebytes+samplesize;
  469. data=malloc(capacity);
  470. }
  471. buffer=data;
  472. writepos=0;
  473. return 0;
  474. };
  475. void sample::setloop(int l)
  476. {
  477. char *p;
  478. loop=l;
  479. p=(char*)data;
  480. if (loop)
  481. memcpy(p+sizebytes,p,samplesize);
  482. else
  483. memcpy(p+sizebytes,p+sizebytes-samplesize,samplesize);
  484. }
  485. void sample::free()
  486. {
  487. if (--refcount==0)
  488. {
  489. if (capacity) ::free(data);
  490. delete this;
  491. }
  492. }
  493. void sample::write(int n)
  494. {
  495. writepos+=n;
  496. buffer=(char *)data+(writepos%samples)*samplesize;
  497. }
  498. int sample::write( void *src,int samples,int readpos)
  499. {
  500. int n,t,nn; //,bytes;
  501. t=0;
  502. while (samples)
  503. {
  504. n=buffersize(readpos);
  505. if (n==0) break;
  506. if (n>samples) n=samples;
  507. nn=n*samplesize;
  508. memcpy(buffer,src,nn);
  509. src=(char*)src+nn;
  510. samples-=n;t+=n;write(n);
  511. }
  512. return t;
  513. }
  514. int sample::buffersize(int readpos)
  515. {
  516. int inuse,rpos,wpos;
  517. inuse=writepos-readpos;
  518. if (inuse>=samples) return 0; //buffer full!
  519. wpos=writepos%samples;
  520. rpos=readpos%samples;
  521. if (rpos>wpos) return rpos-wpos;
  522. return samples-wpos;
  523. }
  524. int sample::peek(int t)
  525. {
  526. int s;
  527. if (t<0||t>=samples) return 0;
  528. switch (samplesize)
  529. {
  530. case 1:
  531. s=((u8*)data)[t]<<8;
  532. break;
  533. case 2:
  534. if (channels==1) s=((u16*)data)[t];else s=((u8*)data)[t*2]<<8;
  535. break;
  536. case 4:
  537. s=((u16*)data)[t*2];
  538. break;
  539. }
  540. return s-32768;
  541. }