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