Guide to Use of Sound in Director - Javascript Version

Stephen Wilson, Conceptual/ Information Arts Program, SFSU

Sound formats

Wav is the Windows standard for recorded digital sound and is now understood by macintosh. Thus it is the most recommended for work in Director.
Aiff is the mac standard for recorded digital sound

Quicktime(mov) sound-only movies are very flexible and can be used in Director via quicktime movie controls.

Midi (mid) is the international standard for storing note based synthesized music. It is not a digitized recording but rather a sequence of note values and instrument notations which are synthesized on midi instruments.  It is highly compressed.  (Must be converted to be used in Director 8)

Mp3 is highly compressed, high quality (Must be converted to be used in Director 8)
RealAudio (ram) is a streaming format.  (It is purposely hard to capture on local computers in order to protect copyright.  It cannot be captured without specialized software)
Windows Media Player (avi, wmv) are another streaming formats.


Sampling Rates and Bit Resolution

Digital sound recording can be captured at various levels of quality.  Sampling rates indicate how many snippets of the analog sound wave are captured per second.  They are measured in kilohertz (khz-thousands of samples per second)  Customary values include 11.025 khz (AM quality) , 22.050 khz(FM), and 44.100 khz (CD quality).   There is a calculable trade-off between quality and file size.  44khz samples require 4 times the file size as 11khz samples.

Sound quality is also affected by bit resolution - for example 8 or 16-bit resolution.  Bit resolution refers to how many nuances can be differentiated in each sample.  8 bit = 256 variations; 16 bit = 65,536 variations.

You can also pick whether to record in mono or stereo (2 channels)


Sampling, Composing, and Capturing Sound

Director has no sound creation capabilities except a rudimentary recording function (Insert media element).  You must either capture sound from the web (for example, public domain sound archives) or use specialized software to create and edit sound.

Sampling and editing software (for example, SoundEdit, Peak, Deck, Pro Tools, Sound Forge) include flexible tools for recording and processing sounds.  You can mix several tracks, apply filters and effects, etc.  You can then save in various formats.

Sequencing software allows you to create midi compositions by chosing notes and instrument defintiions and arranging via standard or non-standard musical notation.

Speech synthesis software allows you to convert standard ascii text into speech generated with synthesized voices.  (Requires special xtra to use in Director)

You can get sound into the computer via the microphone, the earphone output on a tape or cdplayer, or via the internal cd player in the computer.  Newer macs need special sound digitizing usb hardware to take the sound signal in.


Methods by which Director refers to sounds


Methods by which Director plays sounds


Samples of Lingo to Control Sound   (Javascript version)

These examples assume that you have imported sound into Director into cast members called "greeting" and "heartbeat" via the link to external file or direct import.  (The members could be named anything you want.)  Also the examples show mouseUp scripts, the scripts could be placed anywhere Lingo goes - for example on enterFrame, etc.) Sound channels can be on any channel 1-8.  You need to keep track to where you put sounds; they are not visible in score.  8 sounds can be playing simultaneously.  If you start playing a sound in a channel that already has a sound, it will stop it and start the new one.

Play, stop, pause a sound

play a sound  (can be on any channel 1-8)

function mouseUp()   {
sound(1).play (member("a1"));
}

function mouseUp()   {
sound(1).stop();
}
 

Pause and start a sound  ( no need to specify name of sound - already determined when started playing in particular channel - picks up where paused)

function mouseEnter(){
sound(1).pause ();
}
function mouseLeave(){
sound(1).play();
}

Check if a sound is still playing before playing it again. Check if a sound is done before going to next section of movie.

 //Check if a sound is still playing before playing it again.  If a play command is issued without checking, it will start over again (like a stutter).  isBusy() is a function that returns true(1) if it is playing and false (0) if not playing.  This if statement checks if isBusy() is equal to 0 (that is not playing). == in javascript means is equal compariosn.  The script only goes to the sound(1).play if the other sound is not playing
 (isBusy == 0)

function mouseUp()   {
if (sound(1).isBusy()==0 ){
    sound(1).play (member("a1"));
  }
}

Check if a sound is done before going to next section of movie (marker 'section2') otherwise go back to the beginning of the

function exitFrame()  {
    if (sound(3).isBusy()==0)
    {
     _movie.go("section2");
    } 
    else
    { 
     _movie.go("section1");
    } 
}



//  Keep a sound looping. This routine is placed in the exit frame scripts of a sequence.   It checks if the sound is done (isBusy()==0) and then starts it over if it has quit; otherwise it does nothing

function exitFrame()  {
    if (sound(3).isBusy()==0)
{  sound(3).play (member("a1"));  }

}

Start a new sound when sprite reaches a particular position

Check where your animation is - for example the sprite 4 has reached the right edge of the screen.  Play a new sound.  Assumes a different sound is already playing in channel 3
 
function exitFrame()  { 
   if (sprite(4).loch > 600)  {
       sound(3).member = "greeting";
   }
)

Control the volume and fade-ins and outs

Change the volume of a sound to low when entering a graphic sprite - back high when leave.  Volumes can have any value 0-255

function enterFrame()  {
    sound(4).volume = 128
}

function leaveFrame()  {
    sound(4).volume = 255
}

 

Fade a sound to a particular volume level over a certain length of time. Start playing when enter frame.  Fade to volume level 20 over 5 seconds.  (time is given in miliseconds - thousnadths of a second)

function enterFrame()  {
   sound(6).play(member "heartbeat") ;
   sound(6).fadeto (20,5000) ;
}

Set the sound level for all sounds  (values 0-7)
function startMovie()
{
_sound.soundLevel = 5;}
  }

Playlists. queues for sounds

You can setup a playlist.  When a sound finishes in a particular channel it will start playing the next sound.  One simple way is to use the queue command to add sounds.  A more complex way involves setting up Director lists. This is very flexible allowing particular start and end times.  (See the book for details)
 
Queue 3 sounds into a sound channel

function mouseUp(){
  sound(7).queue(member ("play1"));
  sound(7).queue(member ("laugh"));
  sound(7).queue(member ( "referee1"));
}

Each time you stop the sound.  The next play would start the next sound.  The other advantage of queues is that there is no delay in the sounds starting. 

sound(7).play()   -- starts play1
sound(7).stop()   -- stops play1
sound(7).play()   -- starts laugh etc

also this would play the next sound
function mouseUp()  {
sound(7).playnext();
}

Currenttime of a sound

Check where you are in a sound and do something such as change the image  Currenttime reports current time of playing sound in miliseconds.
 
Make various sprites visible as the sound proceeds. Assumes you have started the sound playing already in some channel.  You need to check for a range of times because the script may not executed when the sound is exactly at a particular place.  You would stretch this script to the script channel in every frame of a movie section so it would be checked all the time. 

function exitFrame() {
  var s = sound(3).elapsedTime;   // s is variable set to the elapsed time.
  member("cursound").text = s.toString();  // converts to text string to disaply - not critical
  if (s < 400) { sprite(9).member="r0"; }  // checks if less than 400 milliseconds
  if ((s>1000)&&(s<1200)){ sprite(9).member="r3";}  // check if between 1000 and 1200
                                           // javascript uses && to check for 2 conditions
                                           // in this example changes what visual member sprite displays
 if ((s>2600)&&(s<3100)){ sprite(9).member="r6";}
}

Set up property list for a sound - start, end, loops

//  queue the sound  - set the start & end in miliseconds
//  -- you need to get time from audacity
//  -- set the loop number of times

function mouseUp(){
sound(2).queue(propList("member",member("play1"),
 "startTime",1000, "endTime",1700, "loopCount",2));
  sound(2).play ( );
}


Change frequency - rateshift

Rateshift is undocumented feature that lets you change the pitch of the sounds.  the number after the rateshif parameter indicates the change from normal in semitones.  It can have value from -12 to +12.  The example would shift heartbeat to a higher pitch.  (Lingo not javascript example - not sure supported in Javascript)
 
sound(1).play([#member: member("heartbeat"), #rateShift: 41]

Timing Delays in Director

Often you want short delays before the next event happens.  For example, if you flash text on the screen you must give time for the visitor to read it.  Lingo moves so quick it might not be visible.  This is the Lingo/javascript routine to introduce a delay.  It uses a user-written routine called waiter.  ( You need to put this routine in the movie or frame script level so other routines can call it.)  It has a parameter which stands for how many seconds to delay - for example waiter(2) would delay for 2 seconds.

1a - current time in milliseconds
2a - calculate target time (tar) by multiplying by 1000  to convert to milliseconds
3a - set up while loop - waiting for current milliseconds to exceed the tar
4a = won't exit from routine until the required seconds have passed.  the words //waiting are not really necessary - they are comment to show what is going on.

The sample mouseup routine shows how it might work.  In this example it shows sprite 4 and then calls the waiter routine.   It then waits 1 second  (1000 milliseconds)  until waiter says it is done. It then makes sprite 4 invisible and shows sprite 5.
 
function waiter(target){
var cur= _system.milliseconds;   // 1a
var tar = cur +(target*1000);  // 2a

while (_system.milliseconds<tar)     //3a                                                
    {
        //waiting for time  //4a
    }
}



function mouseUp(){
sprite (4).visible = true;
   waiter(1); 
   sprite(4).visible = false ;
    sprite (5).visible = true ;
}