SndAlleg.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. /*
  2. * Allegro Sound Driver for EMULib Sound system - The TI-NESulator Project
  3. * SndAlleg.C
  4. *
  5. * Created by Manoel Trapier
  6. * Copyright 2003-2008 986 Corp. All rights reserved.
  7. *
  8. * $LastChangedDate$
  9. * $Author$
  10. * $HeadURL$
  11. * $Revision$
  12. *
  13. */
  14. #include <Sound.h>
  15. /* Allegro includes */
  16. #ifdef __APPLE__
  17. #define USE_CONSOLE
  18. #include <Allegro/allegro.h>
  19. #else
  20. #define USE_CONSOLE
  21. #include <allegro.h>
  22. #endif
  23. #include <os_dependent.h>
  24. #include <stdlib.h>
  25. #include <stdio.h>
  26. //#include <unistd.h>
  27. //#include <fcntl.h>
  28. #include <pthread.h>
  29. //#include <sys/ioctl.h>
  30. #define AUDIO_CONV(A) (128+(A))
  31. AUDIOSTREAM *stream;
  32. static pthread_t ThreadID;
  33. static int SoundRate = 0;
  34. static int MasterVolume = 64;
  35. static int MasterSwitch = (1<<SND_CHANNELS)-1;
  36. static int LoopFreq = 25;
  37. static int NoiseGen = 1;
  38. static int Suspended = 0;
  39. static struct
  40. {
  41. int Type; /* Channel type (SND_*) */
  42. int Freq; /* Channel frequency (Hz) */
  43. int Volume; /* Channel volume (0..255) */
  44. const signed char *Data; /* Wave data (-128..127 each) */
  45. int Length; /* Wave length in Data */
  46. int Rate; /* Wave playback rate (or 0Hz) */
  47. int Pos; /* Wave current position in Data */
  48. int Count; /* Phase counter */
  49. } CH[SND_CHANNELS];
  50. static void UnixSetWave(int Channel,const signed char *Data,int Length,int Rate);
  51. static void UnixSetSound(int Channel,int NewType);
  52. static void UnixDrum(int Type,int Force);
  53. static void UnixSetChannels(int Volume,int Switch);
  54. static void UnixSound(int Channel,int NewFreq,int NewVolume);
  55. static int OpenSoundDevice(int Rate,int Verbose);
  56. static void *DSPLoop(void *Arg);
  57. /** StopSound() **********************************************/
  58. /** Temporarily suspend sound. **/
  59. /*************************************************************/
  60. void StopSound(void) { Suspended=1; }
  61. /** ResumeSound() ********************************************/
  62. /** Resume sound after StopSound(). **/
  63. /*************************************************************/
  64. void ResumeSound(void) { Suspended=0; }
  65. /** OpenSoundDevice() ****************************************/
  66. /** Open /dev/dsp with a given level of sound quality. **/
  67. /** Returns 0 if failed or sound quality (Mode). **/
  68. /*************************************************************/
  69. static int OpenSoundDevice(int Rate,int Verbose)
  70. {
  71. voice_start(stream->voice);
  72. if(Verbose) puts("OK");
  73. return(Rate);
  74. }
  75. /** DSPLoop() ************************************************/
  76. /** Main loop of the sound server. **/
  77. /*************************************************************/
  78. static void *DSPLoop(void *Arg)
  79. {
  80. int Wave[SND_BUFSIZE];
  81. unsigned char *Buf;
  82. register int J,I,K,L,M,N,L1,L2,A1,A2,V;
  83. int FreqCount;
  84. N = L = A2 = 0;
  85. for(J=0;J<SND_CHANNELS;J++)
  86. {
  87. CH[J].Type = SND_MELODIC;
  88. CH[J].Count = 0;
  89. CH[J].Volume = 0;
  90. CH[J].Freq = 0;
  91. }
  92. FreqCount=SoundRate/SND_BUFSIZE;
  93. for(;;)
  94. {
  95. Buf = get_audio_stream_buffer(stream);
  96. if (Buf) {
  97. FreqCount-=LoopFreq;
  98. /* If suspending sound... */
  99. if(Suspended)
  100. {
  101. /* Close sound device */
  102. while(Suspended) sleep(1);
  103. /* Reopen sound device */
  104. SoundRate=OpenSoundDevice(SoundRate,0);
  105. }
  106. /* Waveform generator */
  107. for(J=0,M=MasterSwitch;M&&(J<SND_CHANNELS);J++,M>>=1)
  108. if(CH[J].Freq&&(V=CH[J].Volume)&&(M&1))
  109. switch(CH[J].Type)
  110. {
  111. case SND_NOISE: /* White Noise */
  112. /* For high frequencies, recompute volume */
  113. if(CH[J].Freq<=SoundRate) K=0x10000*CH[J].Freq/SoundRate;
  114. else { V=V*SoundRate/CH[J].Freq;K=0x10000; }
  115. L1=CH[J].Count;
  116. V<<=7;
  117. for(I=0;I<SND_BUFSIZE;I++)
  118. {
  119. L1+=K;
  120. if(L1&0xFFFF0000)
  121. {
  122. L1&=0xFFFF;
  123. if((NoiseGen<<=1)&0x80000000) NoiseGen^=0x08000001;
  124. }
  125. Wave[I]+=NoiseGen&1? V:-V;
  126. }
  127. CH[J].Count=L1;
  128. break;
  129. case SND_WAVE: /* Custom Waveform */
  130. /* Waveform data must have correct length! */
  131. if(CH[J].Length<=0) break;
  132. /* Start counting */
  133. K = CH[J].Rate>0? (SoundRate<<15)/CH[J].Freq/CH[J].Rate
  134. : (SoundRate<<15)/CH[J].Freq/CH[J].Length;
  135. L1 = CH[J].Pos%CH[J].Length;
  136. L2 = CH[J].Count;
  137. A1 = CH[J].Data[L1]*V;
  138. /* If expecting interpolation... */
  139. if(L2<K)
  140. {
  141. /* Compute interpolation parameters */
  142. A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
  143. L = (L2>>15)+1;
  144. N = ((K-(L2&0x7FFF))>>15)+1;
  145. }
  146. /* Add waveform to the buffer */
  147. for(I=0;I<SND_BUFSIZE;I++)
  148. if(L2<K)
  149. {
  150. /* Interpolate linearly */
  151. Wave[I]+=A1+L*(A2-A1)/N;
  152. /* Next waveform step */
  153. L2+=0x8000;
  154. /* Next interpolation step */
  155. L++;
  156. }
  157. else
  158. {
  159. L1 = (L1+L2/K)%CH[J].Length;
  160. L2 = (L2%K)+0x8000;
  161. A1 = CH[J].Data[L1]*V;
  162. Wave[I]+=A1;
  163. /* If expecting interpolation... */
  164. if(L2<K)
  165. {
  166. /* Compute interpolation parameters */
  167. A2 = CH[J].Data[(L1+1)%CH[J].Length]*V;
  168. L = 1;
  169. N = ((K-L2)>>15)+1;
  170. }
  171. }
  172. /* End counting */
  173. CH[J].Pos = L1;
  174. CH[J].Count = L2;
  175. break;
  176. case SND_QS_DU0:
  177. /* Do not allow frequencies that are too high */
  178. if(CH[J].Freq>=SoundRate/3) break;
  179. K=0x10000*CH[J].Freq/SoundRate;
  180. L1=CH[J].Count;
  181. V<<=7;
  182. for(I=0;I<SND_BUFSIZE;I++)
  183. {
  184. L2=L1+K;
  185. Wave[I]+=L1&0x2000?(L2&0x8000? V:0):(L2&0x8000? 0:-V);
  186. L1=L2;
  187. }
  188. CH[J].Count=L1;
  189. break;
  190. case SND_QS_DU1:
  191. /* Do not allow frequencies that are too high */
  192. if(CH[J].Freq>=SoundRate/3) break;
  193. K=0x10000*CH[J].Freq/SoundRate;
  194. L1=CH[J].Count;
  195. V<<=7;
  196. for(I=0;I<SND_BUFSIZE;I++)
  197. {
  198. L2=L1+K;
  199. Wave[I]+=L1&0x4000?(L2&0x8000? V:0):(L2&0x8000? 0:-V);
  200. L1=L2;
  201. }
  202. CH[J].Count=L1;
  203. break;
  204. case SND_QS_DU3:
  205. /* Do not allow frequencies that are too high */
  206. if(CH[J].Freq>=SoundRate/3) break;
  207. K=0x10000*CH[J].Freq/SoundRate;
  208. L1=CH[J].Count;
  209. V<<=7;
  210. for(I=0;I<SND_BUFSIZE;I++)
  211. {
  212. L2=L1+K;
  213. Wave[I]+=L1&0xC000?(L2&0x4000? V:0):(L2&0xC000? 0:-V);
  214. L1=L2;
  215. }
  216. CH[J].Count=L1;
  217. break;
  218. case SND_QS_DU2:
  219. case SND_MELODIC: /* Melodic Sound */
  220. default: /* Default Sound */
  221. /* Do not allow frequencies that are too high */
  222. if(CH[J].Freq>=SoundRate/3) break;
  223. K=0x10000*CH[J].Freq/SoundRate;
  224. L1=CH[J].Count;
  225. V<<=7;
  226. for(I=0;I<SND_BUFSIZE;I++)
  227. {
  228. L2=L1+K;
  229. Wave[I]+=L1&0x8000? (L2&0x8000? V:0):(L2&0x8000? 0:-V);
  230. L1=L2;
  231. }
  232. CH[J].Count=L1;
  233. break;
  234. case SND_TRIANGLE: /* Default Sound */
  235. /* Do not allow frequencies that are too high */
  236. if(CH[J].Freq>=SoundRate/3) break;
  237. K=0x10000*CH[J].Freq/SoundRate;
  238. L1=CH[J].Count;
  239. V<<=7;
  240. for(I=0;I<SND_BUFSIZE;I++)
  241. {
  242. L2=L1+K;
  243. Wave[I]+= L1&0x8000?V:-V /*(L2&0x8000? V:0):(L2&0x8000? 0:-V)*/;
  244. L1=L2;
  245. }
  246. CH[J].Count=L1;
  247. break;
  248. }
  249. /* Mix and convert waveforms */
  250. for(J=0;J<SND_BUFSIZE;J++)
  251. {
  252. I=(Wave[J]*MasterVolume)>>16;
  253. I=I<-128? -128:I>127? 127:I;
  254. Buf[J]=AUDIO_CONV(I);
  255. Wave[J]=0;
  256. }
  257. free_audio_stream_buffer(stream);
  258. }
  259. }
  260. return(0);
  261. }
  262. /** InitSound() **********************************************/
  263. /** Initialize DSP. Returns Rate on success, 0 otherwise. **/
  264. /** Mode is 0 to skip initialization (will be silent). **/
  265. /*************************************************************/
  266. int InitSound(int Rate,int Verbose)
  267. {
  268. /* If sound was initialized, kill it */
  269. TrashSound();
  270. /* Silence requested */
  271. if(Rate<=0) return(0);
  272. /* Synthesis rate should be at least 8kHz */
  273. if(Rate<8192) Rate=44100;
  274. /* Initialize things */
  275. SoundRate = 0;
  276. ThreadID = 0;
  277. Suspended = 0;
  278. /* Set driver functions */
  279. SndDriver.SetSound = UnixSetSound;
  280. SndDriver.Drum = UnixDrum;
  281. SndDriver.SetChannels = UnixSetChannels;
  282. SndDriver.Sound = UnixSound;
  283. SndDriver.SetWave = UnixSetWave;
  284. if (install_sound(DIGI_AUTODETECT, MIDI_NONE, "") != 0)
  285. {
  286. console_printf(Console_Error, "%s!\n", allegro_error);
  287. return 1;
  288. }
  289. stream = play_audio_stream(SND_BUFSIZE, 8, FALSE, Rate, 255, 128);
  290. if (!stream) {
  291. console_printf(Console_Error, "Error creating audio stream!\n");
  292. return 1;
  293. }
  294. voice_stop(stream->voice);
  295. /* Open sound device */
  296. if(Verbose) puts("Starting sound server:");
  297. if(!(Rate=OpenSoundDevice(Rate,Verbose))) return(0);
  298. /* Create DSPLoop() thread */
  299. if(Verbose) console_printf(Console_Default, " Creating thread...");
  300. if(pthread_create(&ThreadID,0,DSPLoop,0))
  301. { if(Verbose) puts("FAILED");return(0); }
  302. /* Detach the thread */
  303. pthread_detach(ThreadID);
  304. /* Done */
  305. if(Verbose) puts("OK");
  306. return(SoundRate=Rate);
  307. }
  308. /** TrashSound() *********************************************/
  309. /** Shut DSP down. **/
  310. /*************************************************************/
  311. void TrashSound(void)
  312. {
  313. StopSound();
  314. console_printf(Console_Default, "%s: Kill thread...\n", __func__);
  315. if(ThreadID) pthread_cancel(ThreadID);
  316. SoundRate = 0;
  317. ThreadID = 0;
  318. }
  319. /** UnixSound() **********************************************/
  320. /** Generate sound of given frequency (Hz) and volume **/
  321. /** (0..255) via given channel. **/
  322. /*************************************************************/
  323. void UnixSound(int Channel,int NewFreq,int NewVolume)
  324. {
  325. if((Channel<0)||(Channel>=SND_CHANNELS)) return;
  326. if(!NewVolume||!NewFreq) { NewVolume=0;NewFreq=0; }
  327. CH[Channel].Volume = NewVolume;
  328. CH[Channel].Freq = NewFreq;
  329. }
  330. /** UnixSetChannels() ****************************************/
  331. /** Set master volume (0..255) and turn channels on/off. **/
  332. /** Each bit in Toggle corresponds to a channel (1=on). **/
  333. /*************************************************************/
  334. void UnixSetChannels(int MVolume,int MSwitch)
  335. {
  336. /* Set new MasterSwitch value */
  337. MasterSwitch = MSwitch;
  338. MasterVolume = MVolume;
  339. }
  340. /** UnixSetSound() *******************************************/
  341. /** Set sound type (SND_NOISE/SND_MELODIC) for a given **/
  342. /** channel. **/
  343. /*************************************************************/
  344. void UnixSetSound(int Channel,int NewType)
  345. {
  346. if((Channel<0)||(Channel>=SND_CHANNELS)) return;
  347. CH[Channel].Type = NewType;
  348. }
  349. /** UnixSetWave() ********************************************/
  350. /** Set waveform for a given channel. The channel will be **/
  351. /** marked with sound type SND_WAVE. Set Rate=0 if you want **/
  352. /** waveform to be an instrument or set it to the waveform **/
  353. /** own playback rate. **/
  354. /*************************************************************/
  355. void UnixSetWave(int Channel,const signed char *Data,int Length,int Rate)
  356. {
  357. if((Channel<0)||(Channel>=SND_CHANNELS)||(Length<=0)) return;
  358. CH[Channel].Type = SND_WAVE;
  359. CH[Channel].Length = Length;
  360. CH[Channel].Rate = Rate;
  361. CH[Channel].Pos = 0;
  362. CH[Channel].Count = 0;
  363. CH[Channel].Data = Data;
  364. }
  365. /** UnixDrum() ***********************************************/
  366. /** Hit a drum of a given type with given force. **/
  367. /*************************************************************/
  368. void UnixDrum(int Type,int Force)
  369. {
  370. /* This function is currently empty */
  371. }