Custom Sound Fades

Date:    Fri, 19 May 1995 14:50:42 +0500
From:    "Roman V. Bojur" <rbojur@IABB.TOGLIATTI.SU>
Subject: Re: Kustom FadeIN/Volume: Stumped

>I want to fade a sound in to a predetermined volume. Maybe the Lingo Fadein
>+ volume of sound do this on their own but it hasn't worked for me-

I too hate this algorithmic hacking with multiplication and division of different things. So I didn't look through your code but just send mine for you and those interested. It smoothly fades from the current volume of sound to the volume specified and IT WORKS!

Syntax is

   fadeSound chNum, ticksNum, newVol
where
   chNum    - sound channel you wish to fade
   ticksNum - fading time in ticks (1/60 sec)
   newVol   - volume you wish to fade to

It assumes that sound is already playing in channel chNum.

So here is the code:

on fadeSound chNum, ticksNum, newVol
  put the volume of sound chNum into oldVol
  put the ticks into oldTime
  put abs(newVol-oldVol) into iterNum
  -- fade in or fade out (or nothing)?
  if newVol > oldVol then
    put 1 into stVal
  else if newVol < oldVol then
    put -1 into stVal
  else
    put 0 into stVal
  end if
  repeat with i = 1 to iterNum
    set the volume of sound chNum to oldVol + (i*stVal)
    updateStage
    -- pause to assure smooth fading
    repeat while (the ticks-oldTime) < integer(ticksNum*i/iterNum)
    end repeat
  end repeat
end fadeSound


Date:    Sat, 20 May 1995 12:11:05 +0930
From:    Mark Snoswell <ms@ADAM.COM.AU>
Subject: Custom sound fade handler library.
Here is a little gift to all of the Direct-l community for all of the help I have revieved. A set of sound fade utilities that SHOULD really be built into Director (hint, hint MM). These routines are debugged and work on all platforms. If you like them or have sugestions (How do you impliment handlers with a varible number of arguments? this would allow me to roll the three main functions into one..) PLEASE let me know.

The routines provide the ability to fade sound from any level to any other level over any period of time in the background.. that is while your movie continues to run. There are also "safe" routines to play short sound FX.

There is only 1 technical restriction, which is : DO NOT issue a startTimer command while the sounds are fading. This is not a practical problem as you should NEVER issue a startTimer command but rather record the current time and then calculate any timer loops from that time. This allows lots of unsynchronised events to share the one timer.

The code is copyright 1995 to Mark Snoswell, but can be freely used if acompanied by the following acknowledgment in the code and in print with any product:

   "Sound Routines Copyright Mark Snoswell EMail ms@adam.com.au, Adelaide
   Australia 1995"

The handlers are set up to handle 4 sound channels, however this can easily be changed to 8 channels if desired. The inital lists must be set with up with initialiseSounds() prior to use: ie in a startMovie script.

on SoundFade Channel, Duration, ToVol, FromVol
Sets from and to volumes: after sound is playing use SoundFadeTo
on SoundFadeTo Channel, Duration, ToVol
Starts with current sound volume.
on SoundFX Channel, SoundFile, Volume
Plays an FX at a set volume, resetting the volume afterwards. Designed for short FX only
on SoundPuppet SoundName
Plays an FX at a set volume, resetting the volume afterwards. Designed for short FX only and when you want a puppetsound.
on startMovie
  initialiseSounds()
end startMovie

on initialiseSounds()
  global SoundTargetVolume, SoundCurrentVolume, SoundIncrement, SoundSetTime
  set SoundIncrement = [0.0, 0.0, 0.0, 0.0]
  set SoundTargetVolume = [0.0, 0.0, 0.0, 0.0]
  set  SoundCurrentVolume = [0.0, 0.0, 0.0, 0.0]
  set SoundSetTime = [0, 0, 0, 0]
end initialiseSounds()

on Idle
  --fadeSounds
  global SoundTargetVolume, SoundCurrentVolume, SoundIncrement, SoundSetTime

  repeat with Channel = 1 to 4
    set Elapsed = (the timer - getAt(SoundSetTime,Channel))
    if Elapsed < 0 then abort "The timer has been tampered with"
    set Increment = getAt(SoundIncrement,Channel) * Elapsed
    if integer(Increment) then
      set Target = getAt(SoundTargetVolume,Channel)
      set Current = getAt(SoundCurrentVolume,Channel)
      if (abs(Target - Current) <= abs(Increment)) then
        setAt SoundIncrement,Channel, 0
      else
        set t = Current + Increment
        setAt SoundCurrentVolume,Channel,  t
        if the volume of sound Channel <> integer(t) then
          if integer(t) then
            set the volume of sound Channel = t
          else sound stop Channel

        end if
      end if
    end if
  end repeat
  --end fadeSounds

end idle


on SoundFade Channel,  Duration, ToVol, FromVol
  global SoundTargetVolume, SoundCurrentVolume, SoundIncrement, SoundSetTime

  if FromVol < 0 then set FromVol = 0
  else if FromVol > 255 then set FromVol = 255
  set the volume of sound Channel = FromVol

  SoundFadeSetup(Channel,  Duration, ToVol, FromVol)
end  fadeSound

on SoundFadeTo Channel,  Duration, ToVol
  global SoundTargetVolume, SoundCurrentVolume, SoundIncrement, SoundSetTime

  set FromVol = the volume of sound Channel
  SoundFadeSetup(Channel,  Duration, ToVol, FromVol)
end  fadeSound


on SoundPuppet SoundName
  --Plays an FX at a set volume, resetting the volume afterwards
  -- Designed for short FX only

  set vol = the volume of sound 1
  puppetsound SoundName
  updatestage
  repeat while soundBusy(1)
  end repeat
  puppetsound 0
  set the volume of sound 1 = vol
  updatestage
end SoundPuppet


on SoundFX Channel, SoundFile, Volume
  -- Plays an FX at a set volume, resetting the volume afterwards
  -- Designed for short FX only

  set vol = the volume of sound Channel
  set the volume of sound Channel = Volume
  sound playFile Channel, SoundFile
  repeat while soundBusy(Channel)
  end repeat
  set the volume of sound Channel = vol
end SoundFX


-- Do NOT call directly; used by other Soundxx handlers

on SoundFadeSetup  Channel,  Duration, ToVol, FromVol
  global SoundTargetVolume, SoundCurrentVolume, SoundIncrement, SoundSetTime

  if ToVol < 0 then set ToVol = 0
  else if ToVol > 255 then set ToVol = 255

  if (FromVol = ToVol) then
    setAt SoundIncrement, Channel,  0
  else
    setAt SoundSetTime, Channel, the timer
    setAt SoundCurrentVolume, Channel, float(FromVol)
    setAt SoundTargetVolume, Channel, float(ToVol)
    setAt SoundIncrement, Channel,  float(ToVol - FromVol) / (60.0 * float(Duration))
  end if

end SoundFadeSetup