Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /*
  2. Copyright (C) 1996-1997 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. #include <unistd.h>
  21. #include <fcntl.h>
  22. #include <stdlib.h>
  23. #include <sys/types.h>
  24. #include <sys/ioctl.h>
  25. #include <sys/mman.h>
  26. #include <sys/shm.h>
  27. #include <sys/wait.h>
  28. #include <stdio.h>
  29. #include <sys/audioio.h>
  30. #include <errno.h>
  31. #include "quakedef.h"
  32.  
  33. int audio_fd;
  34. int snd_inited;
  35.  
  36. static int bufpos;
  37. static int wbufp;
  38. static audio_info_t info;
  39.  
  40. #define BUFFER_SIZE             8192
  41.  
  42. unsigned char dma_buffer[BUFFER_SIZE];
  43. unsigned char pend_buffer[BUFFER_SIZE];
  44. int pending;
  45.  
  46. static int lastwrite = 0;
  47.  
  48. qboolean SNDDMA_Init(void)
  49. {
  50.         int rc;
  51.         int fmt;
  52.         int tmp;
  53.         int i;
  54.         char *s;
  55.         int caps;
  56.  
  57.         if (snd_inited) {
  58.                 printf("Sound already init'd\n");
  59.                 return;
  60.         }
  61.  
  62.         shm = &sn;
  63.         shm->splitbuffer = 0;
  64.  
  65.         audio_fd = open("/dev/audio", O_WRONLY|O_NDELAY);
  66.  
  67.         if (audio_fd < 0) {
  68.                 if (errno == EBUSY) {
  69.                         Con_Printf("Audio device is being used by another process\n");
  70.                 }
  71.                 perror("/dev/audio");
  72.                 Con_Printf("Could not open /dev/audio\n");
  73.                 return (0);
  74.         }
  75.  
  76.         if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
  77.                 perror("/dev/audio");
  78.                 Con_Printf("Could not communicate with audio device.\n");
  79.                 close(audio_fd);
  80.                 return 0;
  81.         }
  82.  
  83.         //
  84.         // set to nonblock
  85.         //
  86.         if (fcntl(audio_fd, F_SETFL, O_NONBLOCK) < 0) {
  87.                 perror("/dev/audio");
  88.                 close(audio_fd);
  89.                 return 0;
  90.         }
  91.  
  92.         AUDIO_INITINFO(&info);
  93.  
  94.         shm->speed = 11025;
  95.  
  96.         // try 16 bit stereo
  97.         info.play.encoding = AUDIO_ENCODING_LINEAR;
  98.         info.play.sample_rate = 11025;
  99.         info.play.channels = 2;
  100.         info.play.precision = 16;
  101.  
  102.         if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
  103.                 info.play.encoding = AUDIO_ENCODING_LINEAR;
  104.                 info.play.sample_rate = 11025;
  105.                 info.play.channels = 1;
  106.                 info.play.precision = 16;
  107.                 if (ioctl(audio_fd, AUDIO_SETINFO, &info) < 0) {
  108.                         Con_Printf("Incapable sound hardware.\n");
  109.                         close(audio_fd);
  110.                         return 0;
  111.                 }
  112.                 Con_Printf("16 bit mono sound initialized\n");
  113.                 shm->samplebits = 16;
  114.                 shm->channels = 1;
  115.         } else { // 16 bit stereo
  116.                 Con_Printf("16 bit stereo sound initialized\n");
  117.                 shm->samplebits = 16;
  118.                 shm->channels = 2;
  119.         }
  120.  
  121.         shm->soundalive = true;
  122.         shm->samples = sizeof(dma_buffer) / (shm->samplebits/8);
  123.         shm->samplepos = 0;
  124.         shm->submission_chunk = 1;
  125.         shm->buffer = (unsigned char *)dma_buffer;
  126.  
  127.         snd_inited = 1;
  128.  
  129.         return 1;
  130. }
  131.  
  132. int SNDDMA_GetDMAPos(void)
  133. {
  134.         if (!snd_inited)
  135.                 return (0);
  136.  
  137.         if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
  138.                 perror("/dev/audio");
  139.                 Con_Printf("Could not communicate with audio device.\n");
  140.                 close(audio_fd);
  141.                 snd_inited = 0;
  142.                 return (0);
  143.         }
  144.  
  145.         return ((info.play.samples*shm->channels) % shm->samples);
  146. }
  147.  
  148. int SNDDMA_GetSamples(void)
  149. {
  150.         if (!snd_inited)
  151.                 return (0);
  152.  
  153.         if (ioctl(audio_fd, AUDIO_GETINFO, &info) < 0) {
  154.                 perror("/dev/audio");
  155.                 Con_Printf("Could not communicate with audio device.\n");
  156.                 close(audio_fd);
  157.                 snd_inited = 0;
  158.                 return (0);
  159.         }
  160.  
  161.         return info.play.samples;
  162. }
  163.  
  164. void SNDDMA_Shutdown(void)
  165. {
  166.         if (snd_inited) {
  167.                 close(audio_fd);
  168.                 snd_inited = 0;
  169.         }
  170. }
  171.  
  172. /*
  173. ==============
  174. SNDDMA_Submit
  175.  
  176. Send sound to device if buffer isn't really the dma buffer
  177. ===============
  178. */
  179. void SNDDMA_Submit(void)
  180. {
  181.         int samps;
  182.         int bsize;
  183.         int bytes, b;
  184.         static unsigned char writebuf[1024];
  185.         unsigned char *p;
  186.         int idx;
  187.         int stop = paintedtime;
  188.         extern int soundtime;
  189.  
  190.         if (paintedtime < wbufp)
  191.                 wbufp = 0; // reset
  192.  
  193.         bsize = shm->channels * (shm->samplebits/8);
  194.         bytes = (paintedtime - wbufp) * bsize;
  195.  
  196.         if (!bytes)
  197.                 return;
  198.  
  199.         if (bytes > sizeof(writebuf)) {
  200.                 bytes = sizeof(writebuf);
  201.                 stop = wbufp + bytes/bsize;
  202.         }
  203.  
  204.         p = writebuf;
  205.         idx = (wbufp*bsize) & (BUFFER_SIZE - 1);
  206.  
  207.         for (b = bytes; b; b--) {
  208.                 *p++ = dma_buffer[idx];
  209.                 idx = (idx + 1) & (BUFFER_SIZE - 1);
  210.         }
  211.  
  212.         wbufp = stop;
  213.  
  214.         if (write(audio_fd, writebuf, bytes) < bytes)
  215.                 printf("audio can't keep up!\n");
  216.  
  217. }
  218.  
  219.