8
|
1 /*
|
|
2
|
|
3 Name:
|
|
4 DRV_AF.C
|
|
5
|
|
6 Description:
|
|
7 Mikmod driver for output on AF audio server.
|
|
8
|
|
9 Written by Roine Gustafsson <e93_rog@e.kth.se> Oct 25, 1995
|
|
10
|
|
11 Portability:
|
|
12 Unixes running Digital AudioFile library, available from
|
|
13 ftp://crl.dec.com/pub/DEC/AF
|
|
14
|
|
15 Usage:
|
|
16 Run the audio server (Aaxp&, Amsb&, whatever)
|
|
17 Set environment variable AUDIOFILE to something like 'mymachine:0'.
|
|
18 Remember, stereo is default! See commandline switches.
|
|
19
|
|
20 I have a version which uses 2 computers for stereo.
|
|
21 Contact me if you want it.
|
|
22
|
|
23 THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
|
24 INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS,
|
|
25 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
|
26 CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
27 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
28 NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
29 CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
30
|
|
31 History:
|
|
32 ver 1.21 Bugfix: AFFragmentSize could end up uneven.
|
|
33 Thanks to Marcus Sundberg <e94_msu@e.kth.se>
|
|
34 ver 1.22 Compatibility: change "AFBuffer" to "audiobuffer"
|
|
35 Steve McIntyre <stevem@chiark.greenend.org.uk>
|
|
36 ver 1.30 Compatibility: Use new driver API
|
|
37 Steve McIntyre <stevem@chiark.greenend.org.uk>
|
|
38 */
|
|
39
|
|
40 #include <malloc.h>
|
|
41 #include <stdlib.h>
|
|
42 #include <AF/AFlib.h>
|
|
43
|
|
44 #include "mikmod.h"
|
|
45
|
|
46 /* Global variables */
|
|
47
|
|
48 SBYTE *audiobuffer;
|
|
49 static int AFFragmentSize;
|
|
50 AFAudioConn *AFaud;
|
|
51 ATime AFtime;
|
|
52 AC AFac;
|
|
53 AFDeviceDescriptor *AFdesc;
|
|
54
|
|
55 BOOL AF_IsThere(void)
|
|
56 {
|
|
57
|
|
58 /* I'll think of a detection routine ... somtime */
|
|
59
|
|
60 return 1;
|
|
61
|
|
62 }
|
|
63
|
|
64 BOOL AF_Init(void)
|
|
65 {
|
|
66 unsigned long mask;
|
|
67 AFSetACAttributes attributes;
|
|
68 int srate;
|
|
69 ADevice device;
|
|
70 unsigned int channels;
|
|
71 AEncodeType type;
|
|
72 char *server;
|
|
73 int n;
|
|
74
|
|
75 AFaud = AFOpenAudioConn( "" );
|
|
76 if ( AFaud == NULL ) {
|
|
77 myerr="Cannot open sounddevice.";
|
|
78 return 0;
|
|
79 }
|
|
80
|
|
81 /* Search for a suitable device */
|
|
82 device = -1;
|
|
83 for ( n = 0; n < AFaud->ndevices; n++ ) {
|
|
84 AFdesc = AAudioDeviceDescriptor( AFaud, n );
|
|
85 if ( AFdesc->playNchannels == 2 && md_mode&DMODE_STEREO ) {
|
|
86 device = n;
|
|
87 break;
|
|
88 }
|
|
89 if ( AFdesc->playNchannels == 1 && !(md_mode&DMODE_STEREO) ) {
|
|
90 device = n;
|
|
91 break;
|
|
92 }
|
|
93 }
|
|
94 if ( device == -1 ) {
|
|
95 myerr="Cannot find suitable audio port!";
|
|
96 AFCloseAudioConn( AFaud );
|
|
97 return 0;
|
|
98 }
|
|
99
|
|
100 attributes.preempt = Mix;
|
|
101 attributes.start_timeout = 0;
|
|
102 attributes.end_silence = 0;
|
|
103 attributes.type = LIN16; /* In case of an 8bit device, the AF converts the 16 bit data to 8 bit */
|
|
104 attributes.channels = (md_mode&DMODE_STEREO)? Stereo: Mono;
|
|
105
|
|
106 mask = ACPreemption | ACEncodingType | ACStartTimeout | ACEndSilence | ACChannels;
|
|
107 AFac = AFCreateAC( AFaud, device, mask, &attributes );
|
|
108 srate=AFac->device->playSampleFreq;
|
|
109
|
|
110 md_mode|=DMODE_16BITS; /* This driver only handles 16bits */
|
|
111 AFFragmentSize = (srate/40)*8; /* Update 5 times/sec */
|
|
112 md_mixfreq=srate; /* set mixing freq */
|
|
113
|
|
114 if ( md_mode & DMODE_STEREO ) {
|
|
115 if ( ( audiobuffer = (SBYTE *)malloc( 2*2*AFFragmentSize ) ) == NULL ) {
|
|
116 myerr="Out of memory!";
|
|
117 AFCloseAudioConn( AFaud );
|
|
118 return 0;
|
|
119 }
|
|
120
|
|
121 } else {
|
|
122 if ( ( audiobuffer = (SBYTE *)malloc( 2*AFFragmentSize ) ) == NULL ) {
|
|
123 myerr="Out of memory!";
|
|
124 AFCloseAudioConn( AFaud );
|
|
125 return 0;
|
|
126 }
|
|
127 }
|
|
128
|
|
129 if ( !VC_Init() ) {
|
|
130 AFCloseAudioConn( AFaud );
|
|
131 free( audiobuffer );
|
|
132 return 0;
|
|
133 }
|
|
134
|
|
135 return 1;
|
|
136 }
|
|
137
|
|
138 void AF_PlayStart( void )
|
|
139 {
|
|
140
|
|
141 AFtime = AFGetTime( AFac );
|
|
142 VC_PlayStart();
|
|
143
|
|
144 }
|
|
145
|
|
146
|
|
147 void AF_Exit(void)
|
|
148 {
|
|
149
|
|
150 VC_Exit();
|
|
151 AFCloseAudioConn(AFaud);
|
|
152 free( AFBuffer );
|
|
153
|
|
154 }
|
|
155
|
|
156 void AF_Update(void)
|
|
157 {
|
|
158
|
|
159 UWORD *p,*l,*r;
|
|
160 int i;
|
|
161
|
|
162
|
|
163 VC_WriteBytes( AFBuffer, AFFragmentSize );
|
|
164 if ( md_mode & DMODE_STEREO ) {
|
|
165 AFPlaySamples( AFac, AFtime, AFFragmentSize, (unsigned char *)AFBuffer );
|
|
166 AFtime+=AFFragmentSize/4;
|
|
167 // while ( AFGetTime( AFac ) < AFtime-1000 );
|
|
168 } else {
|
|
169 AFPlaySamples( AFac, AFtime, AFFragmentSize, (unsigned char *)AFBuffer );
|
|
170 AFtime+=AFFragmentSize/2;
|
|
171 // while ( AFGetTime( AFac ) < AFtime-1000 );
|
|
172 }
|
|
173
|
|
174 }
|
|
175
|
|
176
|
|
177 DRIVER drv_AF={
|
|
178 NULL,
|
|
179 "AF driver",
|
|
180 "MikMod AudioFile Driver v1.22",
|
|
181 AF_IsThere,
|
|
182 VC_SampleLoad,
|
|
183 VC_SampleUnload,
|
|
184 VC_SampleSpace,
|
|
185 VC_SampleLength,
|
|
186 AF_Init,
|
|
187 AF_Exit,
|
|
188 VC_SetNumChannels,
|
|
189 AF_PlayStart,
|
|
190 VC_PlayStop,
|
|
191 AF_Update,
|
|
192 VC_VoiceSetVolume,
|
|
193 VC_VoiceSetFrequency,
|
|
194 VC_VoiceSetPanning,
|
|
195 VC_VoicePlay,
|
|
196 VC_VoiceStop,
|
|
197 VC_VoiceStopped,
|
|
198 VC_VoiceReleaseSustain,
|
|
199 VC_VoiceGetPosition,
|
|
200 VC_RealVolume
|
|
201 };
|