drv_sam9407.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:10k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*  MikMod sound library
  2. (c) 1998, 1999, 2000 Miodrag Vallat and others - see file AUTHORS
  3. for complete list.
  4. This library is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Library General Public License as
  6. published by the Free Software Foundation; either version 2 of
  7. the License, or (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11. GNU Library General Public License for more details.
  12. You should have received a copy of the GNU Library General Public
  13. License along with this library; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  15. 02111-1307, USA.
  16. */
  17. /*==============================================================================
  18.   
  19.   $Id: drv_sam9407.c,v 1.1.1.1 2004/01/21 01:36:35 raph Exp $
  20.   
  21.   Driver for the Linux sam9407 driver
  22.   
  23. ==============================================================================*/
  24. /*
  25.    Written by Gerd Rausch <gerd@alf.gun.de>
  26.    Tempo contributions by Xavier Hosxe <xhosxe@cyrano.com>
  27.    Released with libmikmod under LGPL license with the author's permission.
  28. */
  29. #ifdef HAVE_CONFIG_H
  30. #include "config.h"
  31. #endif
  32. #include "mikmod_internals.h"
  33. #ifdef DRV_SAM9407
  34. #ifdef HAVE_UNISTD_H
  35. #include <unistd.h>
  36. #endif
  37. #include <stdlib.h>
  38. #include <string.h>
  39. #include <errno.h>
  40. #include <fcntl.h>
  41. #include <sys/types.h>
  42. #include <sys/stat.h>
  43. #include <sys/ioctl.h>
  44. #include <sys/sam9407.h>
  45. /* Backwards compatibility with driver version 0.9.x */
  46. #ifndef SAM_MOD_API_VERSION
  47. #define SAM_MOD_API_VERSION SAM_API_VERSION
  48. #endif
  49. #define SAM_NUM_BANKS 256
  50. #define SAM_NUM_VOICES 32
  51. #define NO_LOOP_SAMPLES 8
  52. #define PENDING_PLAY (1<<0)
  53. #define PENDING_STOP (1<<1)
  54. #define PENDING_VOLUME (1<<2)
  55. #define PENDING_FREQ (1<<3)
  56. typedef struct {
  57. BOOL inUse;
  58. ULONG length, loopstart, loopend;
  59. UWORD flags;
  60. } Bank;
  61. typedef struct {
  62. BOOL playing;
  63. ULONG pending;
  64. SWORD handle;
  65. ULONG start;
  66. ULONG length;
  67. ULONG loopstart;
  68. ULONG repend;
  69. UWORD flags;
  70. ULONG freq;
  71. UWORD vol;
  72. ULONG pan;
  73. } Voice;
  74. static Bank banks[SAM_NUM_BANKS];
  75. static Voice voices[SAM_NUM_VOICES];
  76. static int card=0;
  77. static int modfd=-1;
  78. static void commandLine(CHAR *cmdline)
  79. {
  80. CHAR *ptr;
  81. if((ptr=MD_GetAtom("card", cmdline, 0))) {
  82. card=atoi(ptr);
  83. free(ptr);
  84. }
  85. }
  86. static BOOL isPresent(void)
  87. {
  88. int fd;
  89. char devName[256];
  90. sprintf(devName, "/dev/sam%d_mod", card);
  91. if((fd=open(devName, O_RDWR))>=0) {
  92. close(fd);
  93. return 1;
  94. }
  95. return (errno == EACCES ? 1 : 0);
  96. }
  97. static ULONG freeSampleSpace(int type)
  98. {
  99. SamModMemInfo memInfo;
  100. if(ioctl(modfd, SAM_IOC_MOD_MEM_INFO, &memInfo)<0)
  101. return 0;
  102. return memInfo.memFree<<1;
  103. }
  104. static SWORD sampleLoad(SAMPLOAD *s, int type)
  105. {
  106. Bank *bankP;
  107. SamModSamples modSamples;
  108. SWORD handle;
  109. SWORD *samples;
  110. int rc;
  111. for(handle=0; handle<SAM_NUM_BANKS; handle++)
  112. if(!banks[handle].inUse)
  113. break;
  114. if(handle>=SAM_NUM_BANKS) {
  115. _mm_errno=MMERR_OUT_OF_HANDLES;
  116. return -1;
  117. }
  118. bankP=banks+handle;
  119. bankP->inUse=1;
  120. SL_SampleSigned(s);
  121. SL_Sample8to16(s);
  122. bankP->length=s->sample->length;
  123. bankP->loopstart=s->sample->loopstart;
  124. bankP->loopend=s->sample->loopend ? s->sample->loopend : s->sample->length;
  125. bankP->flags=s->sample->flags;
  126. if(!(samples=(SWORD *)malloc((bankP->length+NO_LOOP_SAMPLES)<<1))) {
  127. bankP->inUse=0;
  128. _mm_errno=MMERR_SAMPLE_TOO_BIG;
  129. return -1;
  130. }
  131. if(SL_Load(samples, s, bankP->length)) {
  132. free(samples);
  133. bankP->inUse=0;
  134. _mm_errno=MMERR_SAMPLE_TOO_BIG;
  135. return -1;
  136. }
  137. if(!(bankP->flags & SF_LOOP)) {
  138. memset(samples+bankP->length, 0, NO_LOOP_SAMPLES);
  139. bankP->loopstart=bankP->length;
  140. bankP->length+=NO_LOOP_SAMPLES;
  141. bankP->loopend=bankP->length-1;
  142. }
  143. modSamples.handle=handle;
  144. modSamples.data=samples;
  145. modSamples.size=bankP->length;
  146. if((rc=ioctl(modfd, SAM_IOC_MOD_SAMPLES_LOAD, &modSamples))<0) {
  147. free(samples);
  148. bankP->inUse=0;
  149. _mm_errno=MMERR_SAMPLE_TOO_BIG;
  150. return -1;
  151. }
  152. free(samples);
  153. return handle;
  154. }
  155. void sampleUnload(SWORD handle)
  156. {
  157. unsigned char modHandle;
  158. if(!banks[handle].inUse)
  159. return;
  160. modHandle=handle;
  161. ioctl(modfd, SAM_IOC_MOD_SAMPLES_UNLOAD, &modHandle);
  162. banks[handle].inUse=0;
  163. }
  164. static ULONG realSampleLength(int type, SAMPLE *s)
  165. {
  166. if(!s)
  167. return 0;
  168. return s->length<<1;
  169. }
  170. static BOOL init(void)
  171. {
  172. int i;
  173. Voice *voiceP;
  174. char devName[256];
  175. SamApiInfo apiInfo;
  176. sprintf(devName, "/dev/sam%d_mod", card);
  177. if((modfd=open(devName, O_RDWR))<0) {
  178. _mm_errno=MMERR_OPENING_AUDIO;
  179. return 1;
  180. }
  181. if(ioctl(modfd, SAM_IOC_API_INFO, &apiInfo)<0 ||
  182.    apiInfo.version!=SAM_MOD_API_VERSION) {
  183. _mm_errno=MMERR_OPENING_AUDIO;
  184. return 1;
  185. }
  186. for(i=0; i<SAM_NUM_VOICES; i++) {
  187. voiceP=voices+i;
  188. voiceP->freq=44100;
  189. voiceP->vol=0xFF;
  190. voiceP->pan=0x80;
  191. }
  192. md_mode&=~(DMODE_SOFT_MUSIC|DMODE_SOFT_SNDFX);
  193. return 0;
  194. }
  195. static void exitHook(void)
  196. {
  197. if(modfd>=0) {
  198. close(modfd);
  199. modfd=-1;
  200. }
  201. }
  202. static BOOL reset(void)
  203. {
  204. if(ioctl(modfd, SAM_IOC_MOD_RESET)<0)
  205. return 1;
  206. return 0;
  207. }
  208. static BOOL setNumVoices(void)
  209. {
  210. return 0;
  211. }
  212. static BOOL playStart(void)
  213. {
  214. ioctl(modfd, SAM_IOC_MOD_TIMER_START);
  215. return 0;
  216. }
  217. static void playStop(void)
  218. {
  219. ioctl(modfd, SAM_IOC_MOD_POST);
  220. ioctl(modfd, SAM_IOC_MOD_TIMER_STOP);
  221. }
  222. static void update(void)
  223. {
  224. static int wait_echo;
  225. static long ticker_idx;
  226. int i;
  227. Voice *voiceP;
  228. SamModEvent event, eventBuf[SAM_NUM_VOICES*10+8], *eventP;
  229. eventP = eventBuf;
  230. for(i=0; i<md_numchn; i++) {
  231. voiceP=voices+i;
  232. if((voiceP->pending & PENDING_STOP) ||
  233.    ((voiceP->pending & PENDING_PLAY) && voiceP->playing)) {
  234. voiceP->playing=0;
  235. eventP->type=SAM_MOD_EVENT_STOP;
  236. eventP->trigger.voice=i;
  237. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModTriggerEvent));
  238. eventP->type=SAM_MOD_EVENT_CLOSE;
  239. eventP->trigger.voice=i;
  240. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModTriggerEvent));
  241. voiceP->pending&=~PENDING_STOP;
  242. }
  243. if(voiceP->pending & PENDING_PLAY) {
  244. Bank *bankP=banks+voiceP->handle;
  245. eventP->type=SAM_MOD_EVENT_OPEN;
  246. eventP->trigger.voice=i;
  247. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModTriggerEvent));
  248. eventP->type=SAM_MOD_EVENT_MEM;
  249. eventP->mem.voice=i;
  250. eventP->mem.handle=voiceP->handle;
  251. eventP->mem.sampleType=SamModSample16Bit;
  252. eventP->mem.loopType=(bankP->flags & SF_BIDI) ? SamModLoopReverse : SamModLoopForward;
  253. eventP->mem.start=voiceP->start;
  254. eventP->mem.loop=bankP->loopstart;
  255. eventP->mem.end=bankP->loopend;
  256. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModMemEvent));
  257. eventP->type=SAM_MOD_EVENT_VOL;
  258. eventP->volOut.voice=i;
  259. eventP->volOut.volume=0xFF;
  260. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModVolOutEvent));
  261. voiceP->pending|=PENDING_VOLUME|PENDING_FREQ;
  262. }
  263. if(voiceP->pending & PENDING_VOLUME) {
  264. eventP->type=SAM_MOD_EVENT_MAIN;
  265. eventP->volSend.voice=i;
  266. eventP->volSend.left=voiceP->vol*(255-voiceP->pan)/255;
  267. eventP->volSend.right=voiceP->vol*voiceP->pan/255;
  268. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModVolSendEvent));
  269. voiceP->pending&=~PENDING_VOLUME;
  270. }
  271. if(voiceP->pending & PENDING_FREQ) {
  272. eventP->type=SAM_MOD_EVENT_PITCH;
  273. eventP->pitch.voice=i;
  274. eventP->pitch.freq=voiceP->freq;
  275. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModPitchEvent));
  276. voiceP->pending&=~PENDING_FREQ;
  277. }
  278. if(voiceP->pending & PENDING_PLAY) {
  279. voiceP->playing=1;
  280. eventP->type=SAM_MOD_EVENT_START;
  281. eventP->trigger.voice=i;
  282. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModTriggerEvent));
  283. voiceP->pending&=~PENDING_PLAY;
  284. }
  285. }
  286. eventP->type=SAM_MOD_EVENT_WAIT_REL;
  287. eventP->timer.time.tv_sec=0;
  288. eventP->timer.time.tv_usec=2500000/md_bpm;
  289. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModTimerEvent));
  290. eventP->type=SAM_MOD_EVENT_ECHO;
  291. eventP->echo.closure=(void *)(ticker_idx+1);
  292. eventP=(SamModEvent *)((char *)eventP+sizeof(SamModEchoEvent));
  293. if(wait_echo)
  294. while(read(modfd, &event, sizeof(event))>0 && (long)event.echo.closure!=ticker_idx);
  295. wait_echo=1;
  296. ticker_idx++;
  297. (*md_player)();
  298. write(modfd, eventBuf, (char *)eventP-(char *)eventBuf);
  299. }
  300. static void voiceSetVolume(UBYTE voice, UWORD vol)
  301. {
  302. if(voice>=SAM_NUM_VOICES)
  303. return;
  304. voices[voice].vol=vol<=255 ? vol : 255;
  305. voices[voice].pending|=PENDING_VOLUME;
  306. }
  307. static UWORD voiceGetVolume(UBYTE voice)
  308. {
  309. return voice<SAM_NUM_VOICES ? voices[voice].vol : 0;
  310. }
  311. static void voiceSetFrequency(UBYTE voice, ULONG freq)
  312. {
  313. if(voice>=SAM_NUM_VOICES)
  314. return;
  315. voices[voice].freq=freq;
  316. voices[voice].pending|=PENDING_FREQ;
  317. }
  318. static ULONG voiceGetFrequency(UBYTE voice)
  319. {
  320. return voice<SAM_NUM_VOICES ? voices[voice].freq : 0;
  321. }
  322. static void voiceSetPanning(UBYTE voice, ULONG pan)
  323. {
  324. if(voice>=SAM_NUM_VOICES)
  325. return;
  326. voices[voice].pan=pan<=255 ? pan : 255;
  327. voices[voice].pending|=PENDING_VOLUME;
  328. }
  329. static ULONG voiceGetPanning(UBYTE voice)
  330. {
  331. return voice<SAM_NUM_VOICES ? voices[voice].pan : 0x80;
  332. }
  333. static void voicePlay(UBYTE voice, SWORD handle, ULONG start, ULONG length, ULONG loopstart, ULONG repend, UWORD flags)
  334. {
  335. Voice *voiceP;
  336. if(voice>=SAM_NUM_VOICES)
  337. return;
  338. voiceP=voices+voice;
  339. voiceP->handle=handle;
  340. voiceP->flags=flags;
  341. voiceP->start=start;
  342. voiceP->length=length;
  343. voiceP->loopstart=loopstart;
  344. voiceP->repend=repend;
  345. voiceP->flags=flags;
  346. voiceP->pending&=~PENDING_STOP;
  347. voiceP->pending|=PENDING_PLAY;
  348. }
  349. static void voiceStop(UBYTE voice)
  350. {
  351. if(voice>=SAM_NUM_VOICES)
  352. return;
  353. voices[voice].pending&=~PENDING_PLAY;
  354. voices[voice].pending|=PENDING_STOP;
  355. }
  356. static BOOL voiceStopped(UBYTE voice)
  357. {
  358. if(voice>=SAM_NUM_VOICES)
  359. return 1;
  360. return voice<SAM_NUM_VOICES ? !voices[voice].playing : 1;
  361. }
  362. static SLONG voiceGetPosition(UBYTE voice)
  363. {
  364. return -1;
  365. }
  366. static ULONG voiceRealVolume(UBYTE voice)
  367. {
  368. return 0;
  369. }
  370. MIKMODAPI MDRIVER drv_sam9407={
  371. NULL,
  372. "sam9407 driver",
  373. "Linux sam9407 driver v1.0",
  374. SAM_NUM_VOICES, 0,
  375. "sam9407",
  376. commandLine,
  377. isPresent,
  378. sampleLoad,
  379. sampleUnload,
  380. freeSampleSpace,
  381. realSampleLength,
  382. init,
  383. exitHook,
  384. reset,
  385. setNumVoices,
  386. playStart,
  387. playStop,
  388. update,
  389. NULL,
  390. voiceSetVolume,
  391. voiceGetVolume,
  392. voiceSetFrequency,
  393. voiceGetFrequency,
  394. voiceSetPanning,
  395. voiceGetPanning,
  396. voicePlay,
  397. voiceStop,
  398. voiceStopped,
  399. voiceGetPosition,
  400. voiceRealVolume
  401. };
  402. #else
  403. MISSING(drv_sam9407);
  404. #endif
  405. /* ex:set ts=4: */