home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / pc / ABUSESRC.ZIP / AbuseSrc / imlib / port / mac / sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  5.4 KB  |  286 lines

  1. #include "sound.hpp"
  2. #include "jmalloc.hpp"
  3. #include "readwav.hpp"
  4. #include <sound.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7.  
  8. // Maximum number of channels open at one time
  9. #define    MAXCHANNELS    8
  10. #define USE_ASYNCH
  11.  
  12. class AsynchChannel {
  13. public:
  14.     SndChannelPtr    channel;
  15.     int playing;
  16.     SndListHandle sound;
  17. };
  18.  
  19. pascal void DonePlaying(SndChannelPtr channel, SndCommand *cmd);
  20.  
  21. SndCallBackUPP        DonePlayingCB;
  22.  
  23. class CSoundManager
  24. {
  25. public:
  26.     AsynchChannel    Channel[MAXCHANNELS];
  27.     int Channels;
  28.     int Next;
  29.  
  30.     // Construction & destruction
  31.     int Init();
  32.     void Uninit();
  33.     
  34.     void PlaySnd(void *, unsigned long size, unsigned int vol);
  35.     
  36.     void Silence();
  37. } SoundMan;
  38.  
  39. int CSoundManager::Init()
  40. {
  41.     OSErr err = noErr;
  42.  
  43. #ifdef USE_ASYNCH
  44.     DonePlayingCB = NewSndCallBackProc(DonePlaying);
  45. #else
  46.     DonePlayingCB = nil;
  47. #endif
  48.  
  49.     Next = 0;
  50.     Channels = MAXCHANNELS;
  51.  
  52.     for(short i = 0; i < Channels; i++) 
  53.     {
  54.         char Data[64];
  55.         SndListHandle snd;
  56.         SndListPtr sp;
  57.  
  58. #if 1
  59.         // Create resource headers for all channels
  60.         sp = (SndListPtr)&Data[0];
  61.         sp->format = 1;
  62.         sp->numModifiers = 1;
  63.         sp->modifierPart[0].modNumber = 5;
  64.         sp->modifierPart[0].modInit = 0x80;
  65.         sp->numCommands = 1;
  66.         sp->commandPart[0].cmd = 0x8051;
  67.         sp->commandPart[0].param1 = 0;
  68.         sp->commandPart[0].param2 = 0x14;
  69.         
  70.         SoundHeaderPtr p = (SoundHeaderPtr)&sp->dataPart[0];
  71.         p->loopStart = 0;
  72.         p->loopEnd = 1;
  73.         p->sampleRate = rate11khz;
  74.         p->encode = 0;
  75.         p->baseFrequency = 0x3c;
  76.  
  77.         PtrToHand((Ptr)sp,(Handle*)&snd,64);
  78.         HLock((Handle)snd);
  79. #else
  80.         snd = (SndListHandle)GetResource('snd ',1001);
  81.         HLock((Handle)snd);
  82. #endif
  83.  
  84.         Channel[i].channel = nil;
  85.         Channel[i].playing = FALSE;
  86.         Channel[i].sound = snd;
  87.  
  88.         // Create all the channels upon creation
  89.         err = SndNewChannel(&Channel[i].channel, 
  90.                             sampledSynth, 
  91.                             initMono + initNoInterp,
  92.                             (SndCallBackUPP)DonePlayingCB);
  93.                             
  94.         if(err != noErr) 
  95.         {
  96.             fprintf(stderr,"Aiiiieee! Sound manager couldn't initialize!");
  97.             break;
  98.         }
  99.     }
  100.     
  101.     return (err == noErr);
  102. }
  103.  
  104. void CSoundManager::Uninit()
  105. {    
  106.     Silence();
  107.     
  108.     for(int i = 0; i < Channels; i++) 
  109.     {
  110.         OSErr err;
  111.         
  112.         err = SndDisposeChannel (Channel[i].channel, true);
  113.         
  114.         Channel[i].channel = nil;
  115.         Channel[i].playing = FALSE;
  116.         DisposeHandle((Handle)Channel[i].sound);
  117.         Channel[i].sound = nil;
  118.     }
  119. }
  120.  
  121.  
  122. void CSoundManager::PlaySnd(void *data, unsigned long size, unsigned int vol)
  123. {
  124.     AsynchChannel *    channel = nil;
  125.     OSErr        err = noErr;
  126.     SndCommand cmd;
  127.     short chan;
  128.     
  129.     // Find a channel to play from
  130. #ifdef USE_ASYNCH
  131.     channel = nil;
  132.     for(short i = 0; i < Channels; i++)
  133.     {
  134.         if(Channel[i].playing == FALSE)
  135.         {
  136.             channel = &Channel[i];
  137.             chan = i;
  138.             break;
  139.         }
  140.     }
  141.     // If all the channels were busy ignore sound
  142.     if (channel == nil)
  143.         return;    
  144. #else
  145.     channel = &Channel[Next];
  146.     Next = (Next+1)%Channels;
  147. #endif
  148.  
  149.     // grab sound channel        
  150.     channel->playing = TRUE;
  151.  
  152.     cmd.cmd = quietCmd;
  153.     cmd.param1 = 0;
  154.     cmd.param2 = 0;
  155.     err = SndDoImmediate(channel->channel, &cmd);
  156.     cmd.cmd = flushCmd;
  157.     err = SndDoImmediate(channel->channel, &cmd);
  158.     
  159.     SoundHeaderPtr p = (SoundHeaderPtr)&(**channel->sound).dataPart[0];
  160.     p->samplePtr = (Ptr)data;
  161.     p->length = size;
  162.     
  163.     cmd.cmd = volumeCmd;
  164.     cmd.param2 = (vol<<17) | (vol<<1);
  165.     err = SndDoImmediate(channel->channel, &cmd);
  166.     
  167.     // play sound on channel
  168.     err = SndPlay (channel->channel, channel->sound, 1);
  169.     
  170.     if (err != noErr) 
  171.     {
  172.         channel->playing = TRUE;
  173.         fprintf(stderr,"Couldn't play sound!\n");
  174.     }
  175. #ifdef USE_ASYNCH
  176.     else
  177.     {
  178.         // setup callback
  179.         cmd.cmd = callBackCmd;
  180.         cmd.param1 = chan;
  181.         cmd.param2 = (long)channel;
  182.         err = SndDoCommand (channel->channel, &cmd, 0);
  183.     }
  184. #endif
  185. }
  186.  
  187. void CSoundManager::Silence()
  188. {
  189.     for(short i = 0; i < Channels; i++)
  190.     {
  191.         if(Channel[i].playing)
  192.         {
  193.             SndCommand    cmd;
  194.             OSErr        err;
  195.             
  196.             cmd.cmd = quietCmd;
  197.             cmd.param1 = 0;
  198.             cmd.param2 = 0;
  199.             err = SndDoImmediate(Channel[i].channel, &cmd);
  200.             cmd.cmd = flushCmd;
  201.             err = SndDoImmediate(Channel[i].channel, &cmd);
  202.             
  203.             // Mark the channel as empty
  204.             Channel[i].playing = FALSE;
  205.         }
  206.     }
  207. }
  208.  
  209. #pragma segment Main
  210. pascal void DonePlaying(SndChannelPtr channel, SndCommand *cmd)
  211. {
  212. #if 0
  213.     fprintf(stderr,"%x done.\n",(int)cmd->param2);
  214. #endif
  215.     ((AsynchChannel *)(cmd->param2))->playing = FALSE;
  216. }
  217.  
  218. sound_effect::sound_effect(char *filename)
  219. {
  220.     long rate;
  221.     
  222.     data = read_wav(filename,rate,size);
  223. }
  224.  
  225.  
  226. sound_effect::~sound_effect()
  227. {
  228.   if (data)
  229.       jfree(data); 
  230. }
  231.  
  232.  
  233. void sound_effect::play(int volume, int pitch, int panpot)
  234. {
  235.     SoundMan.PlaySnd(data,size,volume);
  236. }
  237.  
  238. int sound_init(int argc, char **argv)
  239. {
  240.     return SoundMan.Init();
  241. }
  242.  
  243. void sound_uninit()
  244. {
  245.   SoundMan.Uninit();
  246. }
  247.  
  248.  
  249. song::song(char *filename)
  250. {
  251.   data=NULL;
  252.   Name=strcpy((char *)malloc(strlen(filename)+1),filename);
  253.   song_id=0;
  254. }
  255.  
  256. song::~song()
  257. {
  258.   if (playing())
  259.     stop();  
  260.   if (data) free(data);
  261.   free(Name);  
  262. }  
  263.  
  264. void song::play(unsigned char volume)
  265. {
  266.   printf("play song %s, volume %d\n",name(),volume);  
  267.   song_id=1;  
  268. }
  269.  
  270.  
  271. void song::stop(long fadeout_time)                                       // time in ms
  272. {
  273.   printf("stop song %s, fade timeout %d\n",name(),fadeout_time);
  274.   song_id=0;
  275.   
  276. }
  277.  
  278. int song::playing()
  279. {
  280.   return song_id;  
  281. }
  282.  
  283. void song::set_volume(int volume)                  // 0...127
  284. {
  285. }
  286.