9
|
1 /*
|
|
2
|
|
3 Name:
|
|
4 DRV_VOX.C
|
|
5
|
|
6 Description:
|
|
7 Mikmod driver for output on linux and FreeBSD Open Sound System (OSS)
|
|
8 (/dev/dsp)
|
|
9
|
|
10 Portability: VoxWare/SS/OSS land. Linux, FreeBSD (NetBSD & SCO?)
|
|
11
|
|
12 New fragment configuration code done by Rao:
|
|
13 ============================================
|
|
14
|
|
15 You can use the environment variables 'MM_FRAGSIZE' and 'MM_NUMFRAGS' to
|
|
16 override the default size & number of audio buffer fragments. If you
|
|
17 experience crackles & pops, try experimenting with these values.
|
|
18
|
|
19 Read experimental.txt within the VoxWare package for information on these
|
|
20 options. They are _VERY_ important with relation to sound popping and smooth
|
|
21 playback.
|
|
22
|
|
23 In general, the slower your system, the higher these values need to be.
|
|
24
|
|
25 MM_NUMFRAGS is within the range 2 to 255 (decimal)
|
|
26
|
|
27 MM_FRAGSIZE is is within the range 7 to 17 (dec). The requested fragment size
|
|
28 will be 2^MM_FRAGSIZE
|
|
29
|
|
30 - This driver DOES work with MikMod 3.0
|
|
31 - modifed to use an ioctl() to figure out how much data to do with
|
|
32 each write, keeps us from blocking extensivly
|
|
33
|
|
34 */
|
|
35 #include <stdio.h>
|
|
36 #include <stdlib.h>
|
|
37 #include <unistd.h>
|
|
38 #include <sys/types.h>
|
|
39 #include <sys/time.h>
|
|
40 #include <sys/stat.h>
|
|
41 #include <fcntl.h>
|
|
42 #ifdef __FreeBSD__
|
|
43 #include <machine/soundcard.h>
|
|
44 #else
|
|
45 #include <sys/soundcard.h>
|
|
46 #endif /* __FreeBSD__ */
|
|
47 #include <sys/ioctl.h>
|
|
48 #include <sys/wait.h>
|
|
49 #include "mikmod.h"
|
|
50 #include "mmio.h"
|
|
51
|
|
52 #define DEFAULT_FRAGSIZE 17
|
|
53 #define DEFAULT_NUMFRAGS 4
|
|
54
|
|
55 static int sndfd;
|
|
56 static int fragmentsize;
|
|
57 static char* audiobuffer;
|
|
58
|
|
59
|
|
60 static BOOL OSS_IsThere(void)
|
|
61 {
|
|
62 return (access("/dev/dsp",W_OK)==0);
|
|
63 }
|
|
64
|
|
65
|
|
66 static BOOL OSS_Init(void)
|
|
67 {
|
|
68 char *env;
|
|
69 int play_precision,play_stereo,play_rate;
|
|
70 int fragsize,numfrags;
|
|
71
|
|
72 if((sndfd=open("/dev/dsp",O_WRONLY))<0){
|
|
73 return 1;
|
|
74 }
|
|
75
|
|
76 fragsize=(env=getenv("MM_FRAGSIZE")) ? atoi(env) : DEFAULT_FRAGSIZE;
|
|
77 numfrags=(env=getenv("MM_NUMFRAGS")) ? atoi(env) : DEFAULT_NUMFRAGS;
|
|
78
|
|
79 if(fragsize<7 || fragsize>17) fragsize=DEFAULT_FRAGSIZE;
|
|
80 if(numfrags<2 || numfrags>255) numfrags=DEFAULT_NUMFRAGS;
|
|
81
|
|
82 fragmentsize=(numfrags<<16) | fragsize;
|
|
83
|
|
84 #ifndef __FreeBSD__
|
|
85 if(ioctl(sndfd, SNDCTL_DSP_SETFRAGMENT, &fragmentsize)<0){
|
|
86 close(sndfd);
|
|
87 return 1;
|
|
88 }
|
|
89 #endif /* __FreeBSD__ */
|
|
90
|
|
91 play_precision = (md_mode & DMODE_16BITS) ? 16 : 8;
|
|
92 play_stereo= (md_mode & DMODE_STEREO) ? 1 : 0;
|
|
93 play_rate=md_mixfreq;
|
|
94
|
|
95 if(ioctl(sndfd, SNDCTL_DSP_SAMPLESIZE, &play_precision) == -1 ||
|
|
96 ioctl(sndfd, SNDCTL_DSP_STEREO, &play_stereo) == -1 ||
|
|
97 ioctl(sndfd, SNDCTL_DSP_SPEED, &play_rate) == -1){
|
|
98 close(sndfd);
|
|
99 return 1;
|
|
100 }
|
|
101
|
|
102 ioctl(sndfd, SNDCTL_DSP_GETBLKSIZE, &fragmentsize);
|
|
103
|
|
104 /* Lose this for now - it will confuse ncurses etc...
|
|
105 printf("Fragment size is %ld\n",fragmentsize); */
|
|
106
|
|
107 if(VC_Init()){
|
|
108 close(sndfd);
|
|
109 return 1;
|
|
110 }
|
|
111
|
|
112 audiobuffer = (char*) _mm_malloc(fragmentsize * sizeof(char) * 2);
|
|
113
|
|
114 if(audiobuffer==NULL){
|
|
115 VC_Exit();
|
|
116 close(sndfd);
|
|
117 return 1;
|
|
118 }
|
|
119
|
|
120 return 0;
|
|
121 }
|
|
122
|
|
123
|
|
124 static void OSS_Exit(void)
|
|
125 {
|
|
126 free(audiobuffer);
|
|
127 VC_Exit();
|
|
128 close(sndfd);
|
|
129 }
|
|
130
|
|
131
|
|
132 static void OSS_Update(void)
|
|
133 {
|
|
134 audio_buf_info buffinf;
|
|
135 ioctl(sndfd, SNDCTL_DSP_GETOSPACE, &buffinf);
|
|
136 VC_WriteBytes(audiobuffer,buffinf.fragments*buffinf.fragsize);
|
|
137 write(sndfd,audiobuffer,buffinf.fragments*buffinf.fragsize);
|
|
138 }
|
|
139
|
|
140 BOOL OSS_Reset(void)
|
|
141 {
|
|
142 ioctl(sndfd, SNDCTL_DSP_RESET);
|
|
143 VC_Exit();
|
|
144 return VC_Init();
|
|
145 }
|
|
146
|
|
147
|
|
148 MDRIVER drv_oss =
|
|
149 {
|
|
150 NULL,
|
|
151 "Open Sound System (OSS)",
|
|
152 "Open Sound System (OSS) Driver v1.3 - by Rao & MikMak (with a little hacking from Pete)",
|
|
153 0,255,
|
|
154 OSS_IsThere,
|
|
155 VC_SampleLoad,
|
|
156 VC_SampleUnload,
|
|
157 VC_SampleSpace,
|
|
158 VC_SampleLength,
|
|
159 OSS_Init,
|
|
160 OSS_Exit,
|
|
161 OSS_Reset,
|
|
162 VC_SetNumVoices,
|
|
163 VC_PlayStart,
|
|
164 VC_PlayStop,
|
|
165 OSS_Update,
|
|
166 VC_VoiceSetVolume,
|
|
167 VC_VoiceSetFrequency,
|
|
168 VC_VoiceSetPanning,
|
|
169 VC_VoicePlay,
|
|
170 VC_VoiceStop,
|
|
171 VC_VoiceStopped,
|
|
172 VC_VoiceReleaseSustain,
|
|
173 VC_VoiceGetPosition,
|
|
174 VC_VoiceRealVolume
|
|
175 };
|