/* Sound code copied from Water Tower */#include "SoundManager.h"void InitSoundManager(VSoundManager * sm) {  OSErr error;  int wSound;    sm->NumberOfSounds = NUMBEROFSOUNDS;  sm->SoundAvailable = 1;  sm->Sounds = (VSound *) NewPtr(sizeof(VSound) * sm->NumberOfSounds);  for (wSound = 0; wSound < sm->NumberOfSounds; wSound++) {    error = LoadSound(&sm->Sounds[wSound], (wSound + BASESOUNDRESID));    if (error != noErr) {      sm->SoundAvailable = 0;      break;    }  }  error = AllocateSoundChannels(sm);  if (error != noErr) {    sm->SoundAvailable = 0;  }  sm->CurrentSoundChannel = 0;}void CleanUpSoundManager(VSoundManager * sm) {  int wSound;    CleanUpSoundChannels(sm);  for (wSound = 0; wSound < sm->NumberOfSounds; wSound++) {    CleanUpSound(&sm->Sounds[wSound]);  }  DisposePtr((Ptr) sm->Sounds);}void SuspendSoundManager(VSoundManager * sm) {  CleanUpSoundChannels(sm);}void ResumeSoundManager(VSoundManager * sm) {  OSErr error;    error = AllocateSoundChannels(sm);  if (error != noErr) {    sm->SoundAvailable = 0;  }}OSErr AllocateSoundChannels(VSoundManager * sm) {  OSErr error;  short wChannel;    for (wChannel = 0; wChannel < NUMBEROFSOUNDCHANNELS; wChannel++) {    sm->SoundChannels[wChannel] = (SndChannelPtr) NewPtr(sizeof(SndChannel));    if (sm->SoundChannels[wChannel] == NULL) return memFullErr;    sm->SoundChannels[wChannel]->qLength = 6;    error = SndNewChannel(&sm->SoundChannels[wChannel], sampledSynth, initMono, NULL);    if (error != noErr) {      while (wChannel > 0) {        wChannel--;        DisposePtr((Ptr) sm->SoundChannels[wChannel]);        sm->SoundChannels[wChannel] = NULL;      }      return error;    }  }  return noErr;}void CleanUpSoundChannels(VSoundManager * sm) {  short wChannel;  SndCommand cmd;    for (wChannel = 0; wChannel < NUMBEROFSOUNDCHANNELS; wChannel++) {    if (sm->SoundChannels[wChannel] != NULL) {      cmd.cmd = flushCmd;      cmd.param1 = 0;      cmd.param2 = 0;      SndDoImmediate(sm->SoundChannels[wChannel], &cmd);      cmd.cmd = quietCmd;      SndDoImmediate(sm->SoundChannels[wChannel], &cmd);      SndDisposeChannel(sm->SoundChannels[wChannel], 1);      DisposePtr((Ptr) sm->SoundChannels[wChannel]);      sm->SoundChannels[wChannel] = NULL;    }  }}OSErr LoadSound(VSound * s, int ResID) {  OSErr error;    s->ResID = ResID;  s->sndList = (SndListHandle) GetResource('snd ', ResID);  error = ResError();  if (s->sndList == NULL || error != noErr) {    if (error != noErr) error = memFullErr; /* Paranoia */    return error;  }  HLock((Handle) s->sndList);  return noErr;}void CleanUpSound(VSound * s) {  if (s->sndList != NULL) {    ReleaseResource((Handle) s->sndList);    s->sndList = NULL;  }}void PlaySound(VSoundManager * sm, int soundID) {  OSErr error;  SndCommand cmd;  long offset;  VSettings * s;    s = GetSettings();  if (!sm->SoundAvailable || !s->SoundEnabled || sm->SoundChannels[sm->CurrentSoundChannel] == NULL) return;  if (soundID >= NUMBEROFSOUNDS || soundID < 0) return;    cmd.cmd = flushCmd;  cmd.param1 = 0;  cmd.param2 = 0;  SndDoImmediate(sm->SoundChannels[sm->CurrentSoundChannel], &cmd);    cmd.cmd = quietCmd;  SndDoImmediate(sm->SoundChannels[sm->CurrentSoundChannel], &cmd);    error = GetSoundHeaderOffset(sm->Sounds[soundID].sndList, &offset);  if (error != noErr) return;    cmd.cmd = bufferCmd;  cmd.param1 = 0;  cmd.param2 = (long) ((Ptr) *sm->Sounds[soundID].sndList + offset);  SndDoCommand(sm->SoundChannels[sm->CurrentSoundChannel], &cmd, 0);    sm->CurrentSoundChannel++;  if (sm->CurrentSoundChannel >= NUMBEROFSOUNDCHANNELS) sm->CurrentSoundChannel = 0;  return error;}Boolean AnySoundsPlaying(VSoundManager * sm) {  short wChannel;  OSErr error;  SCStatus status;    for (wChannel = 0; wChannel < sm->NumberOfChannels; wChannel++) {    error = SndChannelStatus(sm->SoundChannels[wChannel], sizeof(SCStatus), &status);    if (error == noErr) {      if (status.scChannelBusy) return 1;    }  }  return 0;}