SoftwarePractice.org: Home | Courseware | Wiki | Archive

B9 Foley Effects Editor

From SoftwarePractice.org

Contents

Requirements

Project Description

This project is to design and implement a foley and sound effects editor for movie soundtracks. The foley track is used to create the sounds made by the actors in the film. Traditionally, the foley sounds are created specifically for a particular scene by using various props to create sounds like shoes walking, doors slamming, and so on.

The sounds effects crew works a little differently to the foley crew. They are less concerned with intimate sounds made by an actor (such as footsteps and chairs creaking), and more with "big" sounds like explosions and machine noises. They make use of an extensive library of pre-recorded sounds, including some purchased from other companies. Some sound effects will also be recorded or electronically synthesized specifically for a particular film.

This project is to implement an editor that must be possible to record sounds and add them to a library of sound clips. Then, specific clips from the library can be added to a "PlayList." The PlayList is a list of episodes, where each espisode consists of the sound clip ID, the time at which it is to be played, its volume.

The program is able to store an arbitrary number of espisodes, each of which can be played back at any time. To play the PlayList, the program plays back each sound at the appropriate time.


Team Memebers

  • David Lannan
  • Trung Tran

Stakeholders

  • Foley Artists
  • Foley Editor
  • Sound Effects Crew
  • Actors
  • Producer
  • Director
  • System Administrator
  • Film Studio

Use Scenarios

Record Sound

Chewie likes to record multiple takes of his voice so George can choose the right sound for the emotion. Mike records 25 takes of this sound for George, although gets bored at the reptitiveness.

Upload Sound

Mike places recorded sounds requested by George, who is indecisive as to which sound he liks of Chewies voice, into a central online library.

Position Sound

George wants to hear Luke's lightsaber in the right hand speaker as it extends on the right hand side of the screen, and then swoosh to the left.

Play track at specific time

George wants to try the sound he likes of Chewies scream at specific points in the clip, when Chewie is screaming at Han.

Use Case

Use Case Diagram Image:B9_Use_Case_Diagram.JPG

Record Sound

User Action                    System Responsibility
1. User press Record button
   from the Libray interface
                               2. Prompts a frame
3. User press Record to 
   start
4. User start recording
   sounds
4. User press Stop button
                               5. Sounds are saved to system


Load clip to FoleyPlayer

User Action                    System Responsibility
1. User select a clip from
   the Library interface
2. User press Load button 
   from the Library interface
                               3. Loads selected clip to the FoleyPlayer


Load all clips to FoleyPlayer

User Action                    System Responsibility
1. Load all button is pressed
   from the Library interface
                               2. All the clips are loaded to FoleyPlayer


Add clips to Libray

User Action                    System Responsibility
1. User press Add button from
   the Library interface
                               2. Ask user to select a clip
3. User selects a clip         
                               3. Prompts to ask the User to give a name for the selected clip
4. User enter a name and
   press OK
                               5. Add the selected clip with the given name to Library


Delete clip

User Action                    System Responsibility
1. User select a clip
2. User press Delete button
                               3. The selected clip is deleted from the Library

Add starting time to Episodes

User Action                    System Responsibility
1. User selects sound to be 
   played
2. User sets time to be 
   played in seconds
                               3.System stores information for when
                                 clip should be played

Play Episodes

User Action                    System Responsibility
1. User enters starting for
   clips from the FoleyPlayer
   interface
2. User presses to play 
   episodes
                               3. Playing back episodes at specific times


Stop

User Action                    System Responsibility
1. User presses stop in the    2. Stops playing back the foley
   FoleyPlayer interface


Tools and Assumptions

Java and BlueJ are the main applications to develop the project. Jave Media Framework is used to playback soundclips and video clips which are added to a Library.

Since only one movie clip can be added to the Foley Effects Editor, the Video user interface can only be handle for a movie at a time. However, the Foley Effects Editor can be use for multiple movie soundtracks.

CRC Modelling

CRC Cards

Responsibilities | Collaborations

VideoUI

Interface to show video      | JMF
and sound clips playing      | FoleyPlayer 


LibraryUI

Interface allows users to    | FoleyUI
manage clips in the Libary   | Libray


RecordUI

Interface to let users       | FoleyUI 
record a sound with a name


FoleyUI

Main interface allows users  | Track
to open LibaryUI, stop and   | FoleyPlayer
play sound IDs at theirs     | SoundClip
starting time. Users can use | Library
recoring button to record a  | LibraryUI
sound
 


Playlist

Contains sound events        | SoundEvent
                             | FoleyPlayer
                             | VideoUI
                             | LibraryUI


Episode

Represent an episode         | Jave Media Framework (JMF)
of a clip to be play         | 
at its starting time         


JMF

Use Jav Media Framework      | FoleyPlayer
to play clip ids             | VideoUI
                             | SoundClip
                             | LibraryUI


Library

List of sound clip id's | SoundClip


Sound Clip / Temp Sound Clip

A sound clip location | Library - save clip id to library


FoleyPlayer

Init and show main GUI  | Sound Clip
                        | Track
                        | JMF
                        | Library

Initial Class Diagram

Image:B9_Initial_Class_Diagram.jpg


Class Specifications

The attributes and method specifications are written in UML notation. Each method may have a pre/post conditions which specify the desired behaviour of each method. + is represented for a public attribute or a public method. And - is represented for privated method or arttribute.

Class Diagram

Image:B9_Class_Diagram.jpg

VideoUI

Purpose: To play back in sync with a movie video

class VideoUI extends JFrame
Attributes:
-visualComponent: Component

Methods:
+VideoUI()
--Constructor

+addVisual(Player: player)
purpose: to display video 
pre: player<>null
post: set the visualComponent to true


RecorderUI

Provide an interface that allow users to record sound and save it to a selected locations

class RecorderUI extends JFrame implements Runnable, ActionListener
Attributes:
-recordButton, stopButton: JButton
-filenameLabel: JLabel
-fileOut: File
-fileType: AudioFileFormat
-format: AudioFormat
-mike: TargetDataLine
-thread: Thread

Methods:
+RecorderUI()
--Constructor
pre:
post:filenameLabel, recordButton and stopButton are created and shown

+getNewFile()
purpose: create a new file for the recording sound to be saved
pre:
post: let soundFileName = getSoundFile()
      then file = File(soundFileName)
      return file

+startRecording()
purpose: recording a sound in a corrected format
pre:
post: try
        mike = getLine AudioSystem
        then open mike to getBufferSize
      catch
        if error then set the recordButton to false
        set the foreground filenameLabel to red while recording a sound

+stopRecording()
purpose: stop recording a sound when the button is pressed
pre:
post: set the foreground filenameLabel to blue
      stop the mike thread then close

+run()
pre:
post: start the mike thread
      try
        write(sound, fileType, fileOut) to the AudioSystem
      catch 
        print try error

+getSoundFile()
purpose: ask users for a directory location of a recording sound to be saved
pre:
post: open a file diaglog to ask user where to save the recording sound
      then return the name + pathname of the recording sound

+actionPerformed (event ActionEvent)
purpose: manages the action events from the recorderUI
pre:
post: if event = start_record then
        startRecording() is called
      else if event = stop_record then
        stopRecording() is called

FoleyUI

This is the main interface where users can open a Library interface to add, load or delete clips. It also allows the user to manage control the playlist of a foley composition.

class FoleyUI extends Frame ActionListener
Attributes:
-libraryUIButton, exitButton, playButton, stopButton, recordButton: Button
-control: Component
-lblClipNameList, lblClipTimeList, lblClipControlComponent: Label
-clipNameList, clipTimeList: List
-recorderUI: RecorderUI
-playlist: PlayList
-libraryUI: LibraryUI


Methods:
+FoleyUI(foleyPlayer: FoleyPlayer)
--Constructor
pre: foleyPlayer <> null
post: self.foleyPlayer = foleyPlayer
      libraryUIButton, exitButton, playButton, stopButton, recordButton, clipNamList and clipTimeList are   
      created and shown

+actionPerformed(event ActionEvent)
purpose: manages the various action events from the foleyUI
pre:
post: if event = library UI then
         set the visible of the libraryUI is true
      else if event = play button then
         let playList = creatPlayList in
         foleyPlayer.start(playList)
         controlComponentY= COMP_START_Y
      else if event = stop button then
         foleyPlayer.stop(playList)
         controlComponentY = COMP_START_Y
      else if even = record button then
         create and shown the record user interface
      else if even = exit button then
         exit the System

-creatPlayList(): Playlist
purpose: create and returns a playlist object
pre:
post: let playList: Playlist in attribute playlist is created
      for each element in clipNameList and clipTimeList
         playlist.addEpisode(clipNameList.getItem(), clipTimeList.time)
      return playList

+addToPlayList
purpose: to display the clip playlist and time in the FoleyUI interface
pre:
post: clipNameList.add()
      clipTimeList.add()
      
+removeFromPlayList(String item)
purpose: to update the clipNameList in the FoleyUI interface when a clip is deleted
pre:
post: for each element in the clipNameList
        if clipNameList.getItemCount() = item then
           remove clipNamlist(i)
           remove clipTimeList(i)


+addControlComponent(Player player)
purpose: to a component so users can ajust the volume
pre:
post: let comp = player.getControlPanelComponent()
      if  comp <> null then
         add(comp)
          

LibraryUI

Provide an interface that allows users to manage clips to be use in the library

class LibraryUI extends JFrame implements ActionListener
Attributes:
-addButton, deleteButton, loadButton, loadAllButton: JButton
-library: Library
-clipNameList: List
-foleyUI: FoleyUI

 
Methods:
+LibraryUI (Library library, FoleyUI foleyUI)
--Constructor
pre:
post: this.library = library
      this.foleyUI = foleyUI
      addButton, deleteButton, loadButton, loadAllButton and clipNameList are created, initialized and shown

+actionPerformed (ActionEvent event)
purpose: manage the action events from the libraryUI interface
pre:
post: if event = addButton then
         show a file diaglog to allow users to select a clip
         let pathname = filedialog.getDirectory()
         flag false
         while flag
            open a panel to ask users to enter a name for the selected clip
            if there is a name then
            flag true
      else if event = deleteButton then
         let name = clipNamList.getSelectedItem
             selectedIndex = clipNamList.getSelectedIndex
             if a clip is highlight then
                remove the selectedIndex in the clipNamList
                deleteClip(name) is called
                removeFromPlayList(name) from the FoleyUI is called
     else if event = loadButton then
        let name = clipNameList.getSelectedItem
            loadClip(name)is called
            addToPlayList(name) from the FoleyUI is called
     else if event = loadAllButton then
        for every name in the clipNameList
            loadClip (name) is called
            addToPlayList (name) from the FoleyUI is called

-addClip(String pathname, String clipName)
Purpose: creates and adds a clip object to the Libray based on the file in pathname
pre:
post: addClip(pathname, clipName) from the Library is called

-deleteClip(String clipName)
Purpose: deletes the clip with name clipName from the Library
pre:
post: deleteClip(clipName) from the Library is called

-loadClip(String clipName)
Purpose: load the clip with name clipName to the FoleyPlayer
pre:
post: loadClip(clipName) from the Library is called

-getLibrary()
Purpose: to return the Library
pre: 
post: return library
             

FoleyPlayer

It initialises and shows the FoleyUI GUI, and is responsible for playing back foley compositions

class FoleyPlayer implements Runnable
Attributes:
-library: Library
-foleyUI: FoleyUI
-player: Player
-playerThread: Thread
-playList: PlayList


Methods:
+FoleyPlayer()
--Constructor
pre:
post: A new Library object is created
      A new FoleyUI object is created and made visible
      A new VideoUI object is created

+run()
pre:
post: start(playList)

+startPlayer(PlayList pList)
pre:
post: if playerThread = null then
         playerThread = Thread(this)
         playList = pList
         start the playerThread

+start(PlayList playList)
Purpose: call the player to play back clips
pre: playList<>null
post: for each episode in playList JMFstart(player) is called every time an episode needs to be played
      and addControlComponent(player) from the FoleyUI is also called for each episode needed to play

+stop(PlayList playList)
pre: playList<>null
post: for each episode in playList JMFstop(player) is called to stop

+getLibrary()
pre:
post: return library

+main(String[] args)
pre:
post: FoleyUI is created as frame

Library

Contains a collection of movie soundtracks for the foley track composition

class Library
Attributes:
clips: ArrayList

Methods:
+Library()
--Constructor
pre:
post: the clips has been created as an array

+addClip(String pathName, String name)
Purpose: to add a new sound clip to the library
pre: pathName<>null
post: a new SoundClip(pathName, name) is added to the next free position of the array clip

+getClipNames(): String[]
Purpose: returns the names of the sound clips in the array list
pre:
post: let clipnames = String[clips.size]
      for every single clip in the arraylist, an array containing of each sound clip in the 
      library returned.

+loadCLip(String clipName): Boolean
Purpose: load a selected clip with the input name to the foley track composition
pre: clipName<>null
post: for every clip in the arrarylist of clips
          let clip:SoundClip = the clip in clips 
          pathname: String = getPathname() in the clip
          if pathName equal to clipNam or clip.getName() equal to clipName
             if clip.load() successfull, then return true
      else return false

+loadAllClips(): Boolean
Purpose: load all clips in the library to the foley track composition
pre:
post: for every single clip
          clip:SoundClip = (SoundClip)clips.get()
          if clip.load() is fail, then return false
      else return true

+deleteClip(String clipName)
Purpose: to delete a selected clip from the library
pre: clipName<>null
post: for every single clip in the arraylist of clips
         let clip:SoundClip = (SoundClip)clips.get(i)
         if the clip in the arrarylist of clips equal to clipName, then the clip is deleted

+getClipPlayer(String clipName: javax.media.Player
Purpose: return player of the clip with the name equal to clipName
pre: clipName<>null
post: for every single clip in the arraylist of clips
        let clip:SoundClip = the clip in the arrarylist with name equal to clipName
           return clip.getPlayer()

+getClips():ArrayList
Purpose: to the return the all clips in the arrarylist of clips
pre:
post: return clips

+getClip(int clipNumber): SoundClip
Purpose: returns the number of clip in the SoundClip of the clips array
pre: clipNumber < the size of the array clips
post: return the clipNumber in (SoundClip)clips


JMF

Java Media Framework is used to play back sound and movie files

class JMF
Attributes:

Methods:
+static load(File file): Player
Purpose: creates, returns and loads a Player to the specific sound file
pre:
post: let listener = ControllerAdapter of the ControllerListener
      stop(event) method is created
      player = Player of the event getSource()
      player.setMediaTime

      use file paramete to locate the media file and build a URL object to describe the file
      creates a Player for the media file by calling Manager.createRealizedPlayer
      register the new Player by calling addControllerListener(listener)
      prefetch the new Player then
      returns the new Player

+static start(Player player): Player
Purpose: starts the input player
pre:
post: player.start() then
      returns the player

+static stop(Player player): Player
Purpose: stops the player
pre: 
post: if player <> null then
         try
            player.stop()
            returns the player
         catch
            player.start()
      else returns the player
      returns the player

SoundClip

Represents a sound clip in the library

class SoundClip
Attributes:
-player: Player
-file: File
-name: String
-pathName: String

Methods:
+SoundClip(String name, String pathName)
--constructor
pre:
post: a new File object is created based on pathName and assigned to file
      this.name = name
      this.pathName = pathName

+load(): Boolean
pre:
post: let player = JFM.load(this.file)
      if player = null then
         returns true
      else
         returns false

+getPathname(): String
Purpose: to return a pathname
pre:
post: returns this.file.getPath()

+getName(): String
Purpose: to return a name
pre:
post: returns this.name

+getPlayer(): Player
Purpose: to return the player
pre:
post: returns this.player


PlayList

Containning set of episode objects of the Foley composition

class PlayList
Attributes:
episodes: ArrayList

Methods:
+PlayList()
--constructor
pre:
post: a new Episode is created as an ArrayList 

+addEpisode(String name, Integer tm)
Purpose: a new Episode is added to the list
pre:
post: if name = null then
      add a new episode object with name andm time to the next free position of the array episodes

+getEpisode(int episodeNumber): Episode
pre:
post: if the episodeNumber >= the size of the array episodes then
         return null
      else
         return the array episodes.get(episodeNumber)

+getEpisodes(): ArrayList
pre:
post: returns the array episodes


Episode

Represents an episode in the Foley composition where the episode have a name and its starting time to be played

class Episode
Attribute:
clipName: String
time: Integer

Methods:
+Episode(String clipName, Integer time)
--Constructor
pre: There is a sound clip with name = clipName exists in the Library
post: this.clipName = clipName
      this.time = time

Sequence Diagrams

Load a selected clip to the FoleyPlayer

Image:LoadClip_SequenceDiagram.jpg

Add sound clip to the Library

Image:AddClip_SequenceDiagram.jpg

Graphical User Interface

Main FoleyPlayer interface

Image:FoleyPlayer_Interface.JPG

  • The "Openning LibraryUI" button is used to open the Library user interface
  • The "Record" button is used to open a recorder that allow user to record a sound
  • The "Exit FTC" button is used to exit the program
  • The "Play Episodes" button used to play back clips that added to the FoleyPlayer
  • The "Stop Playing" button is used to stop playing back clips in the FoleyPlayer
  • The "List of Episodes" column is the list of sound clips which are added to the FoleyPlayer
  • The "Starting time" column is displayed the starting time of each sound clip. User can enter a strating time for a clip by clicking the row (in Starting time column) which is parralle to the clip
  • User can ajust the volume in the "Control Component" panel

The Library user interface

Image:Library_Interface.JPG

  • The "Add" button is used to add a sound clip to the Library
  • The "Delete" button is used to delete a from the Library. User selects a clip from the clipNameList panel then hit the delete button
  • The "Load" button is used to load a selected sound clip with a name to the FoleyPlayer. User selects a clip in the clipNamList panel then click the load button
  • The "Load All" button is used to load every single clip in the clipNameList panel to the FoleyPlayer. This is designed if user wants to load all the clip at once.

The Recorded user interface

Image:Recorder_Interface.JPG
User uses this interface to record a sound

The Video interface

Image:Video_Interface.JPG
This is to display a movie clip which is loaded to the FoleyPlayer

Test Cases

Load clips to FoleyPlayer

Assume Foley Main Screen Loaded

1. Press the "LibraryUI" Button - Library window opens

2. Press the "Add" Button in Library Window - File window opens

3. Browse to selected a file (a clip) and click Open, then the Clip name window opens - File window closes

4. Enter a name for the clip, then press OK - Clip name window closes

5. Return to the LibraryUI window, highlight or select file (clip ID) to be loaded and click the "Load" button - The clipID is loaded to the Foley Main Screen

6. Repeat from step 2 to 5 for multi files (or clips)

Add starting time for Episodes

Assume Foley Main Screen Loaded

1. Assume files (clips) with IDs are loaded to the Foley Main Screen

2. In the "Starting Time" label (or colume), select a clip to be played that has been loaded - The "Enter Start Time" window opens

3. Type a time (in seconds >=0) for playing of track, then press the "OK" button - The "Enter Start Time" window closes

4. Repeat Steps 2&3 for multiple clips

Play Episodes

Assume Foley Main Screen Loaded

1. Check that files have been loaded to main Screen and timings set

2. Press the "Play Episodes" button to see episode play with foley sounds

Team member comments

Due to the lack of human resource (only 2 members), system tests and unit tests have not been developed. And all the sequence diagrams are not showing

Instructor comments

Initial class diagram is empty - ? I need to see more activity from this group please... thanks :) JohnR 11:30, 9 September 2006 (UTC)

Class diagram appears to have nothing to do with the rest of this documentation. Foley effects generator versus some kind of medical patient record system ???? --Dawsonj 20:27, 7 October 2006 (UTC)

Personal tools