source: abuse/tags/0.7.0/src/sndserver.cpp @ 475

Last change on this file since 475 was 2, checked in by Sam Hocevar, 17 years ago
  • imported original 0.7.0 tarball
File size: 7.4 KB
Line 
1extern "C"
2{
3#include <sys/types.h>
4#include <stdio.h>
5#include <fcntl.h>
6#include <sys/ioctl.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <malloc.h>
10#include <sys/stat.h>
11#include <linux/soundcard.h>
12#include <sys/time.h>
13#include "DoomDef.h"
14};
15
16#include "sndserver.h"
17#include "wadread.h"
18
19#define SOUNDDIR LIBDIR "/sfx/"
20
21typedef struct wadinfo_struct
22{
23  char  identification[4];              // should be IWAD
24  int   numlumps;
25  int   infotableofs;
26} wadinfo_t;
27
28typedef struct filelump_struct
29{
30  int   filepos;
31  int   size;
32  char  name[8];
33} filelump_t;
34
35static int mytime = 0;          // an internal time keeper
36int numsounds;                  // number of sound effects
37int longsound;                  // longest sound effect
38int lengths[NUMSFX];            // lengths of all sound effects
39unsigned char mixbuffer[MIXBUFFERSIZE]; // mixing buffer
40int sfxdevice;                  // file descriptor of sfx device
41int musdevice;                  // file descriptor of music device
42unsigned char *channels[8];     // the channel data pointers
43unsigned char *channelsend[8];  // the channel data end pointers
44int channelstart[8];            // time that the channel started playing
45int channelhandles[8];          // the channel handles
46
47static void derror(char *msg)
48{
49  fprintf(stderr, "error: %s\n", msg);
50  exit(-1);
51}
52
53int mix(void)
54{
55
56  register int i, j, d;
57
58//  if (channels[0]) fprintf(stderr, ".");
59
60//  for (d=i=0 ; i<8 ; i++)
61//    d |= (int) channels[i];
62//  if (!d) return 0;
63
64  // mix into the mixing buffer
65  for (i=0 ; i<MIXBUFFERSIZE ; i++)
66  {
67    d = 0;
68    j = 8;
69    do {
70      if (channels[--j])
71      {
72        d += *channels[j]++ - 128;
73      }
74    } while (j);
75    if (d > 127) mixbuffer[i] = 255;
76    else if (d < -128) mixbuffer[i] = 0;
77    else mixbuffer[i] = (unsigned char) (d+128);
78//    if (d > 127) mixbuffer[i] = 0;
79//    else if (d < -128) mixbuffer[i] = 255;
80//    else mixbuffer[i] = (unsigned char) (-d+127);
81  }
82
83  // check for freed channels
84  for (j=0 ; j<8 ; j++)
85  {
86    if (channels[j] == channelsend[j]) channels[j] = 0;
87  }
88
89  return 1;
90
91}
92
93void grabdata(int c, char **v)
94{
95
96  int i;
97
98  numsounds = NUMSFX;
99  longsound = 0;
100
101  openwad("../frame/doom.wad");
102
103  for (i=1 ; i<NUMSFX ; i++)
104  {
105    if (!S_sfx[i].link)
106    {
107      S_sfx[i].data = getsfx(S_sfx[i].name, &lengths[i]);
108      if (longsound < lengths[i]) longsound = lengths[i];
109    } else {
110      S_sfx[i].data = S_sfx[i].link->data;
111      lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(struct sfxinfo_t)];
112    }
113    /*
114    // test only
115    {
116      int fd;
117      char name[10];
118      sprintf(name, "sfx%d", i);
119      fd = open(name, O_WRONLY|O_CREAT, 0644);
120      write(fd, S_sfx[i].data, lengths[i]);
121      close(fd);
122    }
123    */
124  }
125
126}
127
128void opensfxdev(int c, char **v)
129{
130
131  int i, rc;
132
133  // open the sound device
134  sfxdevice = open("/dev/dsp", O_WRONLY, 0);
135  if (sfxdevice < 0) derror("Could not open /dev/dsp");
136
137  // set it up for the proper sound format
138  i = 8;
139  rc = ioctl(sfxdevice, SNDCTL_DSP_SAMPLESIZE, &i);
140  if (rc < 0) fprintf(stderr, "SAMPLESIZE failed\n");
141  i = 11111;
142  rc = ioctl(sfxdevice, SNDCTL_DSP_SPEED, &i);
143  if (rc < 0) fprintf(stderr, "SPEED failed\n");
144  i = 0;
145  rc = ioctl(sfxdevice, SNDCTL_DSP_STEREO, &i);
146  if (rc < 0) fprintf(stderr, "STEREO failed\n");
147//  i = 2;
148//  rc = ioctl(sfxdevice, SNDCTL_DSP_SUBDIVIDE, &i);
149//  if (rc < 0) fprintf(stderr, "SUBDIVIDE failed\n");
150
151}
152
153void closesfxdev(void)
154{
155  close(sfxdevice);
156}
157
158void openmusdev(int c, char **v)
159{
160}
161
162void closemusdev(void)
163{
164}
165
166static struct timeval last={0,0}, now;
167static struct timezone whocares;
168
169void updatesounds(void)
170{
171  int deltatime;
172  int rc;
173
174  rc = mix();
175  rc = ioctl(sfxdevice, SNDCTL_DSP_POST, 0);
176//  rc = ioctl(sfxdevice, SNDCTL_DSP_SYNC, 0);
177  if (rc < 0) fprintf(stderr, "SYNC failed?!\n");
178  write(sfxdevice, mixbuffer, MIXBUFFERSIZE);
179/*
180  gettimeofday(&now, &whocares);
181  deltatime = (now.tv_sec - last.tv_sec)*1000000 + now.tv_usec - last.tv_usec;
182  deltatime = deltatime - (1 * MIXBUFFERSIZE * 1000000) / (1 * SPEED);
183  last = now;
184  if (deltatime < 0)
185    usleep (-deltatime);
186  if (rc)
187  {
188    write(sfxdevice, mixbuffer, MIXBUFFERSIZE);
189    fprintf(stderr, ".");
190  }
191*/
192}
193
194int addsfx(int sfxid, int volume)
195{
196
197  int i;
198  int rc = -1;
199  static unsigned short handlenums = 0;
200  int oldest = mytime;
201  int oldestnum = 0;
202
203  for (i=0 ; i<8 ; i++)
204  {
205    if (!channels[i])
206    {
207      channelsend[i] =
208        (channels[i] = (unsigned char *) S_sfx[sfxid].data) + lengths[sfxid];
209      if (!handlenums) handlenums = 100;
210      channelhandles[i] = rc = handlenums++;
211      channelstart[i] = mytime;
212      break;
213    }
214    else
215    {
216      if (channelstart[i] < oldest)
217      {
218        oldestnum = i;
219        oldest = channelstart[i];
220      }
221    }
222  }
223
224  // if no channels were available, kill oldest sound and replace it
225  if (i == 8)
226  {
227    channelsend[oldestnum] =
228      (channels[oldestnum] = (unsigned char *) S_sfx[sfxid].data)
229       + lengths[sfxid];
230    if (!handlenums) handlenums = 100;
231    channelhandles[oldestnum] = rc = handlenums++;
232    channelstart[i] = mytime;
233  }
234
235  return rc;
236
237}
238
239void outputushort(int num)
240{
241
242  static unsigned char buff[5] = { 0, 0, 0, 0, '\n' };
243  static char *badbuff = "xxxx\n";
244
245  // outputs a 16-bit # in hex or "xxxx" if -1.
246  if (num < 0)
247  {
248    write(1, badbuff, 5);
249  } else {
250    buff[0] = num>>12;
251    buff[0] += buff[0] > 9 ? 'a'-10 : '0';
252    buff[1] = (num>>8) & 0xf;
253    buff[1] += buff[1] > 9 ? 'a'-10 : '0';
254    buff[2] = (num>>4) & 0xf;
255    buff[2] += buff[2] > 9 ? 'a'-10 : '0';
256    buff[3] = num & 0xf;
257    buff[3] += buff[3] > 9 ? 'a'-10 : '0';
258    write(1, buff, 5);
259  }
260
261}
262
263void initdata(void)
264{
265  int i;
266  for (i=0 ; i<sizeof(channels)/sizeof(unsigned char *) ; i++) channels[i] = 0;
267  gettimeofday(&last, &whocares);
268  usleep(100000);
269}
270
271int main(int c, char **v)
272{
273
274  int done = 0;
275  int rc, nrc, sndnum, handle = 0;
276  unsigned char commandbuf[10];
277  fd_set fdset, scratchset;
278  struct timeval zerowait = { 0, 0 };
279
280  grabdata(c, v);       // get sound data
281  initdata();           // init any data
282
283  opensfxdev(c, v);     // open sfx device
284  openmusdev(c, v);     // open music device
285  fprintf(stderr, "ready\n");
286
287  // parse commands and play sounds until done
288  FD_ZERO(&fdset);
289  FD_SET(0, &fdset);
290  while (!done)
291  {
292    mytime++;
293    do {
294      scratchset = fdset;
295      rc = select(FD_SETSIZE, &scratchset, 0, 0, &zerowait);
296      if (rc > 0)
297      {
298  //      fprintf(stderr, "select is true\n");
299        // got a command
300        nrc = read(0, commandbuf, 1);
301        if (!nrc) { done = 1; rc = 0; }
302        else {
303          switch (commandbuf[0])
304          {
305            case 'p':           // play a new sound effect
306              read(0, commandbuf, 3);
307              commandbuf[0] -= commandbuf[0]>='a' ? 'a'-10 : '0';
308              commandbuf[1] -= commandbuf[1]>='a' ? 'a'-10 : '0';
309              sndnum = (commandbuf[0]<<4) + commandbuf[1];
310  //        fprintf(stderr, "cmd: play sound %d\n", sndnum);
311              handle = addsfx(sndnum, 127); // returns the handle
312//            outputushort(handle);
313              break;
314            case 'q':
315              read(0, commandbuf, 1);
316              done = 1; rc = 0;
317              break;
318            case 's':
319              {
320                int fd;
321                read(0, commandbuf, 3);
322                commandbuf[2] = 0;
323                fd = open((char*)commandbuf, O_CREAT|O_WRONLY, 0644);
324                commandbuf[0] -= commandbuf[0]>='a' ? 'a'-10 : '0';
325                commandbuf[1] -= commandbuf[1]>='a' ? 'a'-10 : '0';
326                sndnum = (commandbuf[0]<<4) + commandbuf[1];
327                write(fd, S_sfx[sndnum].data, lengths[sndnum]);
328                close(fd);
329              }
330              break;
331            default:
332              fprintf(stderr, "Did not recognize command\n");
333              break;
334          }
335        }
336      }
337    } while (rc > 0);
338    updatesounds();
339  }
340
341  closesfxdev();
342  closemusdev();
343
344}
Note: See TracBrowser for help on using the repository browser.