
Music Information Retrieval Systems
by William Birmingham, Colin Meek, Kevin O'Malley, Bryan Pardo, and Jonah Shifrin


Listing One

on run_viterbi()
	set args to UNIX_VS_PATH & UNIX_FILE_DELIM & PT_FILE & " " & VETERBI_UNIX_PATH & UNIX_FILE_DELIM & "dirBeatles.txt" & " " & DEFAULT_PLAYLIST & " " & VETERBI_UNIX_PATH
	set cmd to VETERBI_UNIX_PATH & UNIX_FILE_DELIM & VETERBI_APP & " " & args
	my my_log(cmd)
	
	tell application "Terminal"
		set theResult to do shell script cmd
	end tell
	my my_log(theResult)
	
	if the 1st word of theResult is equal to "error" then
		handle_error(theResult, VITERBI)
	end if
	
	set aList to theResult
	return aList
end run_viterbi



Listing Two

-- The time for recording in seconds.
property RECORD_TIME : 15

property MAC_FILE_DELIM : ":"
property UNIX_FILE_DELIM : "/"

property SOUND_STUDIO_WINDOW_NAME : "untitled"
property WAV_FILE : "untitled"
property PT_FILE : "untitled.notes"
property V_FILE : "vs.vit"

property PT_APP : "pitch"
property VETERBI_APP : "viterbi"

property DEFAULT_PLAYLIST : "MyPlayList"
property APP_FOLDER : "VocalSearch"
property ENABLE_LOGGING : 1

property VITERBI : 1
property PITCH_TRACKER : 2

tell application "Finder"
	set diskName to (name of startup disk)
end tell

global MAC_VS_PATH
global UNIX_VS_PATH
global VETERBI_UNIX_PATH

set MAC_VS_PATH to diskName & ":" & APP_FOLDER
set UNIX_VS_PATH to "/" & APP_FOLDER
set VETERBI_UNIX_PATH to UNIX_VS_PATH & "/viterbi"

-- Main program.
display dialog "When you see the recorder, sing your melody.  You have " & RECORD_TIME & " seconds of recording time." & return & return & "Press OK to begin or Cancel to quit." buttons {"Cancel", "OK"} default button 2

if the button returned of the result is "Ok" then
	my record_input()
	my run_pitchtracker()
	set playlist to my run_viterbi()
	my create_playlists(playlist)
end if

-- ****************************************************************************
-- Record the user's search. using StoundStudio.  Result is wav file called untitled.
-- ****************************************************************************
on record_input()
	set fname to MAC_VS_PATH & ":" & WAV_FILE
	tell application "Finder"
		
		try
			delete file (fname)
		on error
			delay 0 -- noop
		end try
	end tell
	
	tell application "Sound Studio"
		set doc to (make new document with properties {sample rate:44100, sample size:16, channels:1})
		activate
		record doc
		delay (1 * RECORD_TIME)
		stop doc
		set fname to MAC_VS_PATH & ":" & WAV_FILE
		save doc in file fname as class WAVE
		close doc saving no
	end tell
	tell application "iTunes"
		activate
	end tell
	
end record_input

-- ****************************************************************************
-- ****************************************************************************
on run_viterbi()
	display_msg("Searching for matching songs...", 2)
	set args to UNIX_VS_PATH & UNIX_FILE_DELIM & PT_FILE & " " & VETERBI_UNIX_PATH & UNIX_FILE_DELIM & "dirBeatles.txt" & " " & DEFAULT_PLAYLIST & " " & VETERBI_UNIX_PATH
	set cmd to VETERBI_UNIX_PATH & UNIX_FILE_DELIM & VETERBI_APP & " " & args
	my my_log(cmd)
	
	tell application "Terminal"
		set theResult to do shell script cmd
	end tell
	my my_log(theResult)
	
	if the 1st word of theResult is equal to "error" then
		handle_error(theResult, VITERBI)
	end if
	
	set aList to theResult
	return aList
end run_viterbi

-- ****************************************************************************
-- Run the pitch tracker, which converts the wav file to notes.  The notes are written to
-- a text file called "untitled.notes".  This is the file that is passed to the 
-- viterbi program.
-- ****************************************************************************
on run_pitchtracker()
	display_msg("Running pitch tracker...", 2)
	set cmd to UNIX_VS_PATH & UNIX_FILE_DELIM & PT_APP & " " & UNIX_VS_PATH & UNIX_FILE_DELIM & WAV_FILE
	my my_log(cmd)
	
	tell application "Terminal"
		set theResult to do shell script cmd
	end tell
	my my_log(theResult)
	
	if the 1st word of theResult is equal to "error" then
		handle_error(theResult, PITCH_TRACKER)
	end if
end run_pitchtracker

-- ****************************************************************************
-- ****************************************************************************
on create_playlists(the_list)
	
	display_msg("Creating playlist...", 2)
	if 1st word of the_list is equal to "error" then
		display dialog "Error processing requesti."
	else
		tell application "iTunes"
			activate
			set playlist_name to the 2nd word of the_list as string
			set this_playlist to make new playlist
			set the name of this_playlist to playlist_name
			repeat with i from 3 to (number of words in the_list)
				set songName to word i of the_list as string
				my my_log(songName)
				tell source "Library"
					tell playlist "Library"
						duplicate (every track whose name is songName) to this_playlist
					end tell
				end tell
			end repeat
		end tell
	end if
end create_playlists


-- ****************************************************************************
-- Displays a message for n seconds.
-- ****************************************************************************
on display_msg(msg, n)
	display dialog msg buttons {""} default button 1 giving up after n
end display_msg

-- ****************************************************************************
-- Displays a message and exits the script.
-- ****************************************************************************
on my_exit(msg)
	display dialog msg buttons {"Cancel"} default button 1 with icon stop
end my_exit

-- ****************************************************************************
-- Display a log message if logging is enabled, ENABLE_LOGGING set to 1.
-- ****************************************************************************
on my_log(msg)
	if ENABLE_LOGGING is equal to 1 then
		log msg
	end if
end my_log

-- ****************************************************************************
-- Display an error and exit the program.
-- ****************************************************************************
on handle_error(msg, type)
	set errStr to ""
	if type is equal to VITERBI then
		set errStr to errStr & "Viterbi error: "
	end if
	if type is equal to PITCH_TRACKER then
		set errStr to errStr & "Pitch-tracker error: "
	end if
	
	repeat with i from 2 to (number of words in msg)
		set tmpStr to word i of msg as string
		set errStr to errStr & " " & tmpStr
	end repeat
	my_exit(errStr)
end handle_error






