home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / linux / sound.c < prev   
Encoding:
C/C++ Source or Header  |  1995-08-24  |  10.1 KB  |  459 lines

  1. #include "sound.hpp"
  2. #include "readwav.hpp"
  3. #include "specs.hpp"
  4. #include "sdriver.hpp"
  5. #include "jmalloc.hpp"
  6. #include "specs.hpp"
  7. #include "macs.hpp"
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <fcntl.h>
  11. #include <unistd.h>
  12. #include <linux/soundcard.h>
  13. #include <sys/ioctl.h>
  14. #include <sys/stat.h>
  15. #include <sys/types.h>
  16. #include <sys/time.h>
  17. #include <string.h>
  18. #include <signal.h>
  19. #include "dprint.hpp"
  20. #include <fcntl.h>
  21. #include <linux/limits.h>
  22.  
  23.  
  24. int sound_child_fd=-1,
  25.     sound_parent_fd=-1,
  26.     sound_status[2],
  27.     sound_child_pid;
  28.  
  29.  
  30. #define BUF_BITS 9
  31. #define BUF_SIZE (1<<BUF_BITS)
  32. #define NUM_CHANNELS 8
  33. #define SAMPLE_SPEED 11025
  34.  
  35. int s_dev,full_pot=0,start_seq;
  36.  
  37.  
  38. unsigned char buf[BUF_SIZE];   // mixing buffer
  39.  
  40.  
  41. struct sfx
  42. {
  43.   unsigned char *data;
  44.   long size;  
  45. } ;
  46.  
  47. struct channel
  48. {
  49.   unsigned char *data;                  // next data to be qued
  50.   long left;                   // how much is left to play?  
  51.   unsigned char volume_shift;  
  52.   unsigned long add_time;      // time at which the channel started playing  
  53. } channels[NUM_CHANNELS];
  54.  
  55.  
  56.  
  57.  
  58.  
  59. sfx *seffects=NULL;
  60. short total_effects=0;
  61.  
  62. void sound_watch(int f);
  63.  
  64. // add a new sound effect into the channel list, if no free channel
  65. // oldest gets replaced with new sound
  66. void play(short id, unsigned char volume)
  67. {
  68.   int i,free_channel=-1;
  69.   unsigned long last_channel_time=0;  
  70.   for (i=0;i<NUM_CHANNELS;i++)
  71.   {
  72.     if (channels[i].data)
  73.     {      
  74.       if (channels[i].add_time>last_channel_time)
  75.       {    
  76.         last_channel_time=channels[i].add_time;
  77.     if (free_channel==-1)
  78.         free_channel=i;    
  79.       }      
  80.     }    
  81.     else free_channel=i;        
  82.   }
  83.  
  84.   channels[free_channel].add_time=last_channel_time+1;
  85.   channels[free_channel].data=seffects[id].data+1024;
  86.   channels[free_channel].left=seffects[id].size-1024;
  87.   channels[free_channel].volume_shift=(127-volume)>>4;
  88. }
  89.  
  90. int output_sounds()  // return 0 if no sounds to ouput
  91. {
  92.   unsigned char *s;
  93.   int i,j,bytes=0;  
  94.  
  95. //  usleep((BUF_SIZE*90000/SAMPLE_SPEED)); // sleep long enough for old sample to alomst finish
  96.   
  97.   
  98.   signed short sums[BUF_SIZE],run_size,*sp;
  99.   memset(sums,0,BUF_SIZE*sizeof(short));
  100.   for (j=0;j<NUM_CHANNELS;j++)
  101.   {
  102.     if (channels[j].data)
  103.     {
  104.       if (channels[j].left<BUF_SIZE)    // hom many bytes will this channel run for?
  105.         run_size=channels[j].left;
  106.       else run_size=BUF_SIZE;
  107.  
  108.       if (run_size>bytes)          // how many bytes to output?
  109.         bytes=run_size;
  110.       
  111.       // add the chanels together into a short
  112.       for (i=0,sp=sums;i<run_size;i++,sp++)
  113.         *sp+=(((signed short)*(channels[j].data++))-128)>>channels[j].volume_shift;
  114.  
  115.       if (channels[j].left<=BUF_SIZE)
  116.         channels[j].data=NULL;
  117.       else channels[j].left-=BUF_SIZE;
  118.       
  119.     }
  120.   }
  121.  
  122.  
  123.  
  124.     
  125.   for (i=0,sp=sums,s=buf;i<BUF_SIZE;i++,s++,sp++)
  126.     if (*sp<-128) *s=0;
  127.     else if (*sp>127) *s=255;
  128.     else *s=(unsigned char)(*sp+128);
  129.  
  130.  
  131.   write(s_dev, buf, BUF_SIZE);
  132.   return 1;    // always say we have something, we will do blanks if nothing else
  133.   
  134. }
  135.  
  136.  
  137. int sound_init(int argc, char **argv) 
  138. {  
  139.   int i;  
  140.   char buf[PIPE_BUF];
  141.   for (i=1;i<argc;i++)
  142.   {
  143.     if (!strcmp(argv[i],"-nosound"))
  144.       return 0;
  145.   }
  146.  
  147.   if (sound_child_fd!=-1)
  148.   {
  149.    fprintf(stderr,"Sound already initialized\n");
  150.     return 1;
  151.   }
  152.  
  153.   int fds[2];
  154.   if (pipe(fds)==-1) 
  155.   {
  156.     fprintf(stderr,"error creating pipe for sound driver\n");
  157.     exit(1);
  158.   } 
  159.  
  160.   if (pipe(sound_status)==-1) 
  161.   {
  162.     fprintf(stderr,"error creating pipe for sound driver\n");
  163.     exit(1);
  164.   } 
  165.  
  166.  
  167.   sound_child_pid=fork();
  168.   if (sound_child_pid)                // if we are the parent, then check that status from the child
  169.   {
  170.  
  171.     char status;
  172.     read(fds[0],buf,PIPE_BUF);
  173.     if (buf[0])
  174.     {
  175.       sound_child_fd=fds[0];
  176.       sound_parent_fd=fds[1];
  177.       atexit(sound_uninit);          // make sure the child dies when the program ends
  178.       return SFX_INITIALIZED;
  179.     } else 
  180.     {
  181.       dprintf("sound : child returned init failure\n");
  182.       return 0;      
  183.     }
  184.   } else
  185.   {
  186.     int fd=open("/dev/mixer",O_WRONLY);
  187.     if (fd!=-1)
  188.     {
  189.       int vol=127;
  190.       ioctl(fd,MIXER_WRITE(SOUND_MIXER_VOLUME),&vol);
  191.       close(fd);
  192.     } else fprintf(stderr,"sound driver : Unable to open /dev/mixer, can't set volume\n");
  193.  
  194.     
  195.     buf[0]=0;                             // get ready to send failure
  196.     s_dev=open("/dev/dsp",O_WRONLY,0);
  197.     if (s_dev<0)
  198.     {
  199.       fprintf(stderr,"sound driver : Unable to open /dev/dsp, sound effects disabled\n");    
  200.       write(fds[1],buf,PIPE_BUF);
  201.       exit(1);
  202.     }
  203.     dprintf("sound driver : opened /dev/dsp\n");
  204.     i = 0x00020000|BUF_BITS;    /* 2 fragments of 2^BUF_BITS bytes */
  205.     ioctl(s_dev, SNDCTL_DSP_SETFRAGMENT, &i);
  206.  
  207.     i = 8;     // samples are 8 bit
  208.     if (ioctl(s_dev, SNDCTL_DSP_SAMPLESIZE, &i)<0)
  209.     {
  210.       fprintf(stderr,"SNDDRV : Sample size 8 failed, sound effects disabled\n");    
  211.       close(s_dev);
  212.       write(fds[1],buf,PIPE_BUF);
  213.       exit(1);
  214.     }
  215.  
  216.     i = SAMPLE_SPEED; 
  217.     if (ioctl(s_dev, SNDCTL_DSP_SPEED, &i)<0)
  218.     {
  219.       fprintf(stderr,"SNDDRV : dsp_speed failed, sound effects disabled\n");    
  220.       close(s_dev);
  221.       write(fds[1],buf,PIPE_BUF);
  222.       exit(1);
  223.     }
  224.  
  225.     i = 0;     // no stero
  226.     if (ioctl(s_dev, SNDCTL_DSP_STEREO, &i)<0)
  227.     {
  228.       fprintf(stderr,"SNDDRV : Sample size 8 failed, sound effects disabled\n");    
  229.       close(s_dev);
  230.       write(fds[1],buf,PIPE_BUF);
  231.       exit(1);
  232.     }
  233.  
  234.     
  235.     for (i=0;i<NUM_CHANNELS;i++)    // clear all the sound channels
  236.       channels[i].data=NULL;  
  237.  
  238.  
  239.     buf[0]=1;
  240.     write(fds[1],buf,PIPE_BUF);        // send a success signal to parent
  241.     sound_child_fd=fds[0];
  242.     sound_parent_fd=fds[1];
  243.     sound_watch(sound_child_fd);
  244.   }
  245.   CHECK(0);                         // should never get here!
  246.   return 0;                         
  247. }
  248.  
  249.  
  250. int sound_fd_ready_to_read(int fd)
  251. {
  252.   struct timeval tv={0,0};
  253.   fd_set kbd_set,ex_set;
  254.   FD_ZERO(&kbd_set);
  255.   FD_SET(fd,&kbd_set);
  256.   memcpy((void *)&ex_set,(void *)&kbd_set,sizeof(ex_set));
  257.   select(FD_SETSIZE,&kbd_set,NULL,&ex_set,&tv);                // check for exception
  258.   return (FD_ISSET(fd,&kbd_set) || FD_ISSET(fd,&ex_set));
  259. }
  260.  
  261.  
  262. void sound_quit(int client_fd)
  263. {
  264.   close(sound_parent_fd);
  265.   close(sound_child_fd);
  266.   close(sound_status[0]);
  267.   close(sound_status[1]);
  268.   close(s_dev);
  269.   exit(0);  
  270. }
  271.  
  272. short new_id()
  273. {
  274.   int i;
  275.   for (i=0;i<total_effects;i++)
  276.     if (seffects[i].size==0)
  277.       return i;
  278.   i=total_effects;  
  279.   total_effects++;  
  280.   seffects=(sfx *)realloc(seffects,sizeof(sfx)*(total_effects)); 
  281.   seffects[i].size=0;  
  282.   return i;  
  283. }
  284.  
  285.  
  286. void sound_watch(int f)
  287. {
  288.   int wait=0;
  289.   char fn[200];
  290.   while (1)
  291.   {    
  292.     if (output_sounds())
  293.       wait=0;
  294.     else wait=1;    
  295.  
  296.     if (wait || sound_fd_ready_to_read(f))    // is there a command waiting?
  297.     {
  298.       unsigned char cmd;
  299.  
  300.       int status=read(f,&cmd,1);
  301.       
  302.       if (status!=1)
  303.       { sound_quit(f); }
  304.       
  305.       switch (cmd)
  306.       {
  307.         case SDRIVER_QUIT : sound_quit(f); break;
  308.         case SDRIVER_LOAD :
  309.     {      
  310.       short id=new_id();
  311.       unsigned short sl;
  312.       read(f,&sl,2);
  313.       read(f,fn,sl);
  314.       long sample_speed;
  315.       seffects[id].data=(unsigned char *)read_wav(fn,sample_speed,seffects[id].size); 
  316.       write(sound_status[1],&id,2);
  317.     } break;
  318.         case SDRIVER_UNLOAD :
  319.     {
  320.       short id;    
  321.       read(f,&id,2);
  322.       if (id>=total_effects || !seffects[id].size)
  323.       {
  324.         fprintf(stderr,"SNDDRV : bad unload sound id %d\n",id);
  325.         sound_quit(f);
  326.       }
  327.       free(seffects[id].data);
  328.       seffects[id].size=0;    
  329.     } break;    
  330.         case SDRIVER_PLAY :
  331.     {
  332.       unsigned char vol;
  333.       read(f,&vol,1);      
  334.  
  335.       short id;    
  336.       read(f,&id,2);
  337.       if (id>=total_effects || !seffects[id].size)
  338.       {
  339.         fprintf(stderr,"SNDDRV : bad play sound id %d\n",id);
  340.         sound_quit(f);
  341.       }
  342.       play(id,vol);
  343.     } break;
  344.     default :
  345.       fprintf(stderr,"SNDDRV : Bad command %d\n",cmd);
  346.       sound_quit(f);
  347.       break;
  348.       
  349.       }          
  350.     }     
  351.   }
  352. }
  353.  
  354.  
  355. sound_effect::sound_effect(char *filename)
  356. {
  357.   long rate;    
  358.   short id;  
  359.   if (sound_child_fd>=0)
  360.   {    
  361.     unsigned char cmd=SDRIVER_LOAD;    
  362.     write(sound_parent_fd,&cmd,1);
  363.     unsigned short string_length=strlen(filename)+1;
  364.     write(sound_parent_fd,&string_length,2);
  365.     write(sound_parent_fd,filename,string_length);
  366.     read(sound_status[0],&id,2);
  367.     size=(long)id;    
  368.   }  
  369. }
  370.  
  371.  
  372. sound_effect::~sound_effect()
  373. {
  374.   short id;  
  375.   if (sound_child_fd>=0)
  376.   {
  377.     unsigned char cmd=SDRIVER_UNLOAD;   // tell the driver to unload the sound
  378.     write(sound_parent_fd,&cmd,1);    
  379.     id=(short)size;
  380.     write(sound_parent_fd,&id,2);    
  381.   }
  382. }
  383.  
  384.  
  385. void sound_effect::play(int volume, int pitch, int panpot)
  386. {  
  387.   if (sound_child_fd>=0)
  388.   {    
  389.     unsigned char cmd=SDRIVER_PLAY;
  390.     write(sound_parent_fd,&cmd,1);    
  391.  
  392.     unsigned char vol=(unsigned char)volume;
  393.     write(sound_parent_fd,&vol,1);    
  394.  
  395.     short id=(short)size;
  396.     write(sound_parent_fd,&id,2);
  397.   }
  398. }
  399.  
  400. void sound_uninit()         // called by parent
  401. {
  402.   if (sound_child_fd>=0)    // mkae sure the child has been forked
  403.   {
  404.     char cmd=SDRIVER_QUIT;
  405.     write(sound_parent_fd,&cmd,1);
  406.     close(sound_parent_fd);
  407.     close(sound_child_fd);
  408.     close(sound_status[0]);
  409.     close(sound_status[1]);
  410.     sound_child_fd=-1;
  411.   }
  412. }
  413.  
  414.  
  415. song::song(char *filename)
  416. {
  417.   data=NULL;
  418.   Name=strcpy((char *)jmalloc(strlen(filename)+1,"song name"),filename);
  419.   song_id=0;
  420. }
  421.  
  422. song::~song()
  423. {
  424.   if (playing())
  425.     stop();  
  426.   if (data) jfree(data);
  427.   jfree(Name);  
  428. }  
  429.  
  430. void song::play(unsigned char volume)
  431. {
  432.   printf("play song %s, volume %d\n",name(),volume);  
  433.   song_id=1;  
  434. }
  435.  
  436.  
  437. void song::stop(long fadeout_time)                                       // time in ms
  438. {
  439.   printf("stop song %s, fade timeout %d\n",name(),fadeout_time);
  440.   song_id=0;
  441.   
  442. }
  443.  
  444. int song::playing()
  445. {
  446.   return song_id;  
  447. }
  448.  
  449.  
  450.  
  451. void set_music_volume(int volume)                  // 0...127
  452. {
  453. ;  
  454. }
  455.  
  456.  
  457.  
  458.  
  459.