Xylophone gag project
From enfascination
(15 intermediate revisions by one user not shown) | |||
Line 1: | Line 1: | ||
I wrote a small program to help you blow people up on the piano. This project was inspired by the classic cartoon "Xylophone Gag" | I wrote a small program to help you blow people up on the piano. This project was inspired by the classic cartoon "Xylophone Gag" | ||
− | <pre>http://www.youtube.com/watch?v=YnJl6qAYdLs</pre> < | + | '''Youtube broadcast, starting at 5:45, until 6:51'''<pre>http://www.youtube.com/watch?v=YnJl6qAYdLs</pre><small><small>(if this specific video gets pulled, search for any of the cartoon titles identifying the gag in [http://tvtropes.org/pmwiki/pmwiki.php/Main/XylophoneGag this] article)</small></small> |
− | (if this specific video gets pulled, search for any of the cartoon titles identifying the gag in [http://tvtropes.org/pmwiki/pmwiki.php/Main/XylophoneGag this] article) | + | |
− | The goal was to | + | The goal was to apply machine learning techniques to digital audio to identify a player's mistakes playing a known melody. This is a course project[http://www.music.informatics.indiana.edu/courses/I547/] in only about 500 lines of code, so there are severe restrictions on its general utility. It works on monophonic, single instrument melodies, and works better if the melody is short and played on a wind instrument. It does not identify timing errors and wasn't tested on skipped notes, only wrong notes. To keep close roots to the gag, I only benchmarked the code on the classic tune for the Irish poem, "[http://en.wikipedia.org/wiki/Believe_Me,_if_All_Those_Endearing_Young_Charms Believe me, if all those endearing young charms]."[http://www.contemplator.com/ireland/believe.html] |
− | + | However, I do demonstrate the robustness of the code to identify mistakes across the melody, as played in different keys, at different tempos, and across a few instruments. Also different performers (thank you Nathaniel, Travis, Bugs Bunny and Yosemite Sam). For my simple test examples, and given the limits of the HMM that I built the code on, this system successfully identifies mistakes, avoiding both false positives and negatives (thinking there is a mistake when there isn't and thinking there is not a mistake when there is). | |
− | I modified a simple HMM | + | To implement this, I modified a simple HMM [http://www.music.informatics.indiana.edu/courses/I547/hw6_sln.r][http://www.music.informatics.indiana.edu/courses/I547/] written in [http://www.r-project.org R] to add rudimentary score following. I then introduced an obnoxious screech into the audio to indicate identification of each mistake. |
==the tune== | ==the tune== | ||
− | = | + | [[Image:charms_sheet.jpg|right|400 px|thumb|first page of Endearing Charms score[http://www.musicnotes.com/sheetmusic/mtdVPE.asp?ppn=MN0062193]. This project uses first five measures.]] |
− | + | [[Image:midi_notes_key.GIF|right|200 px|thumb| midi cheat sheet[http://www.phys.unsw.edu.au/jw/notes.html]]] | |
− | [[Image:midi_notes_key.GIF|right | + | Here is my representation of the melody in R, from the score, using the cheat sheet. I didn't actually use the timing info: |
+ | <pre> | ||
+ | eyc_orig_notes <- c(64, 62, 60, 62, 60, 60, 64, 67, 65, 69, 72, 72) | ||
+ | timing<- c(.25, .25, .75,.25, 0.5,0.5,0.5 , 0.5 , 0.5 , 0.5 , 0.5 , .75,) | ||
+ | </pre> | ||
+ | ---- | ||
==code== | ==code== | ||
===the code=== | ===the code=== | ||
+ | [[xylophone gag project code]] | ||
+ | [http://enfascination.com/forever/xylophonegag/endearing_charms_code_006.r] | ||
===modifications=== | ===modifications=== | ||
− | + | I added a few things to the HMM implementation here [http://www.music.informatics.indiana.edu/courses/I547/hw6_sln.r] | |
− | + | *I changed the highest and lowest "possible" notes, because my samples covered a range of keys, and tended to be higher. | |
+ | *i recorded on a bunch of instruments (the vanilla HMM was tested almost entirely on bass oboe data). Instruments include guitar, penny whistle, recorder and the Bugs Bunny and Yosemite Sam audio from the Youtube video above. | ||
+ | *I made a near note bias, editing the transition table to make it more likely that you will go from any note to a note within 6 half-steps of the current note. | ||
+ | *I shortened the minimum number of frames per note to four, to catch the shorter notes in the sample. | ||
+ | *I created another window length, the minimum number of frames that a note must be sustained to be considered an error. The error detection is only as good as the HMM it is built on. Noisy attacks, like on a piano, are very hard to identify correctly. To keep from labeling these identification errors as player mistakes, I made a minimum size of eight frames, below which a pitch cannot be labeled as an error. In my code, one frame is about two hundredths of a second. | ||
+ | *I added simple score following and an "error state" | ||
+ | **The error state allowed me to catch two kinds of mistakes. Sometimes a player realized they made a mistake and plays the right note after playing the wrong note. Sometimes they don't realize, or they accept the mistake and continue on to the next note, skip the correct note entirely. These two possibilities make it hard to follow a score, because you can't know which note a mistake mistook. My solution in the code works for many kinds of mistakes on this tune, but certainly doesn't generalize. | ||
+ | **The score following takes a simple midi representation of the tune, identifies the key of the audio and follows the tune as it is being played. It can handle silence cleanly. If a note occurs that should not have, for long enough to not be a bad attack or a squeaky note onset, the system enters an error state, looking for a return either to the current note, the next note, or the one after that. | ||
+ | **Best details on actual code modifications are in the well-commented code above. | ||
+ | |||
==examples== | ==examples== | ||
+ | In the images below, the horizontal axis is time (in frames of 2/100s of a second) and the vertical axis is recognized midi pitch (which you will see is jumpy). These are all graphs of a same tune. It rises in pitch. lines on the bottom edge of a plot represent silence. The canonical mistake, that bugs makes, is that the very last note should be C, but ends up too high or low. | ||
+ | ===caught mistakes=== | ||
+ | ====canonical player error (on penny whistle)==== | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos1112Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos1112Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos1112MarkedUp.wav Error-marked representation] | ||
+ | | | ||
+ | [[Image:FinalErrorPos1112Converted.jpg|right|400px|thumb| canonical mistake (on penny whistle) ]] | ||
+ | |} | ||
+ | ====canonical player error with detection mistake==== | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos41112Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos41112Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos41112MarkedUp.wav Error-marked representation] | ||
+ | | | ||
+ | [[Image:FinalErrorPos41112Converted.jpg|right|400 px|thumb|note detection error at time 200. Representation is flat.]] | ||
+ | |} | ||
+ | ====other error and mistake (on recorder)==== | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | The second note is intentionally wrong. The others are detected as errors due to mis-recognition from the original audio (or maybe I played it wrong on my recorder and can't tell) | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos2356Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos2356Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalErrorPos2356MarkedUp.wav Error-marked representation] | ||
+ | | | ||
+ | [[Image:FinalErrorPos2356Converted.jpg|right|400 px|thumb| notice wrong key (pitch shifted down 3 midi levels)]] | ||
+ | |} | ||
+ | |||
+ | ===good versions (no mistakes played and no mistakes found)=== | ||
+ | ====successful penny whistle (best suited to Irish tunes anyway)==== | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors01Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors01Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors01MarkedUp.wav Error-marked representation](notice that there are no high pitches (errors). This is the same as the recognized representation) | ||
+ | | | ||
+ | [[Image:FinalNoErrors01Converted.jpg|right|400 px]] | ||
+ | |} | ||
+ | ---- | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors02Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors02Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors02MarkedUp.wav Error-marked representation](notice that there are no identified errors) | ||
+ | | | ||
+ | [[Image:FinalNoErrors02Converted.jpg|right|400 px]] | ||
+ | |} | ||
+ | <!-- | ||
+ | ---- | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors03Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors03Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalNoErrors03MarkedUp.wav Error-marked representation](notice that there are no identified errors) | ||
+ | | | ||
+ | [[Image:FinalNoErrors03Converted.jpg|right|400px]] | ||
+ | |} | ||
+ | --> | ||
+ | ====Yosemite Sam frustrated on piano==== | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | Yosemite Sam's correct, lethal, attempt at the song, cut off just before explosion. | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalYosemiteOriginal.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalYosemiteConverted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalYosemiteMarkedUp.wav Error-marked representation](notice little errors on piano attack) | ||
+ | | | ||
+ | [[Image:FinalYosemiteConverted.jpg|right|400px|thumb|notice much lower key and faster play]] | ||
+ | |} | ||
+ | |||
+ | ===bad identifications=== | ||
+ | ====Bugs Bunny playing piano==== | ||
+ | Deferring to the holy law of triples, Bugs Bunny attempts the tune twice before Sam gets frustrated and gets it right (wrong) the third time. My attempt at catching Bugs Bunny's mistakes failed due to the limits of the simple recognizer that I built on top of, evident in the screenshots. This may be due to recording quality, or maybe the fact that it is played on piano. I am tempted to rule that out though, because I recognized Yosemite Sam fine, and he played on the same piano. | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalBugsBunny02Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalBugsBunny02Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalBugsBunny02MarkedUp.wav Error-marked representation] | ||
+ | | | ||
+ | [[Image:FinalBugsBunny02Converted.jpg|right|400px|thumb|notice all the detected silence, and sparsity of detected notes]] | ||
+ | |} | ||
+ | ---- | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalBugsBunny01Original.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalBugsBunny01Converted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalBugsBunny01MarkedUp.wav Error-marked representation] | ||
+ | | | ||
+ | [[Image:FinalBugsBunny01Converted.jpg|right|400px]] | ||
+ | |} | ||
+ | |||
+ | ====guitar==== | ||
+ | {| cellpadding="2" style="border: 0px;" | ||
+ | |- border="0" | ||
+ | | | ||
+ | Guitar was problematic. Probably due to the attacks. | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalGuitarOriginal.wav Original recording] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalGuitarConverted.wav Recognized representation] | ||
+ | #[http://enfascination.com/forever/xylophonegag/FinalGuitarMarkedUp.wav Error-marked representation] | ||
+ | | | ||
+ | [[Image:FinalGuitarConverted.jpg|right|400px]] | ||
+ | |} |
Latest revision as of 02:53, 27 April 2010
I wrote a small program to help you blow people up on the piano. This project was inspired by the classic cartoon "Xylophone Gag"
Youtube broadcast, starting at 5:45, until 6:51http://www.youtube.com/watch?v=YnJl6qAYdLs(if this specific video gets pulled, search for any of the cartoon titles identifying the gag in this article)
The goal was to apply machine learning techniques to digital audio to identify a player's mistakes playing a known melody. This is a course project[3] in only about 500 lines of code, so there are severe restrictions on its general utility. It works on monophonic, single instrument melodies, and works better if the melody is short and played on a wind instrument. It does not identify timing errors and wasn't tested on skipped notes, only wrong notes. To keep close roots to the gag, I only benchmarked the code on the classic tune for the Irish poem, "Believe me, if all those endearing young charms."[4]
However, I do demonstrate the robustness of the code to identify mistakes across the melody, as played in different keys, at different tempos, and across a few instruments. Also different performers (thank you Nathaniel, Travis, Bugs Bunny and Yosemite Sam). For my simple test examples, and given the limits of the HMM that I built the code on, this system successfully identifies mistakes, avoiding both false positives and negatives (thinking there is a mistake when there isn't and thinking there is not a mistake when there is).
To implement this, I modified a simple HMM [5][6] written in R to add rudimentary score following. I then introduced an obnoxious screech into the audio to indicate identification of each mistake.
Contents |
the tune
Here is my representation of the melody in R, from the score, using the cheat sheet. I didn't actually use the timing info:
eyc_orig_notes <- c(64, 62, 60, 62, 60, 60, 64, 67, 65, 69, 72, 72) timing<- c(.25, .25, .75,.25, 0.5,0.5,0.5 , 0.5 , 0.5 , 0.5 , 0.5 , .75,)
code
the code
xylophone gag project code [7]
modifications
I added a few things to the HMM implementation here [8]
- I changed the highest and lowest "possible" notes, because my samples covered a range of keys, and tended to be higher.
- i recorded on a bunch of instruments (the vanilla HMM was tested almost entirely on bass oboe data). Instruments include guitar, penny whistle, recorder and the Bugs Bunny and Yosemite Sam audio from the Youtube video above.
- I made a near note bias, editing the transition table to make it more likely that you will go from any note to a note within 6 half-steps of the current note.
- I shortened the minimum number of frames per note to four, to catch the shorter notes in the sample.
- I created another window length, the minimum number of frames that a note must be sustained to be considered an error. The error detection is only as good as the HMM it is built on. Noisy attacks, like on a piano, are very hard to identify correctly. To keep from labeling these identification errors as player mistakes, I made a minimum size of eight frames, below which a pitch cannot be labeled as an error. In my code, one frame is about two hundredths of a second.
- I added simple score following and an "error state"
- The error state allowed me to catch two kinds of mistakes. Sometimes a player realized they made a mistake and plays the right note after playing the wrong note. Sometimes they don't realize, or they accept the mistake and continue on to the next note, skip the correct note entirely. These two possibilities make it hard to follow a score, because you can't know which note a mistake mistook. My solution in the code works for many kinds of mistakes on this tune, but certainly doesn't generalize.
- The score following takes a simple midi representation of the tune, identifies the key of the audio and follows the tune as it is being played. It can handle silence cleanly. If a note occurs that should not have, for long enough to not be a bad attack or a squeaky note onset, the system enters an error state, looking for a return either to the current note, the next note, or the one after that.
- Best details on actual code modifications are in the well-commented code above.
examples
In the images below, the horizontal axis is time (in frames of 2/100s of a second) and the vertical axis is recognized midi pitch (which you will see is jumpy). These are all graphs of a same tune. It rises in pitch. lines on the bottom edge of a plot represent silence. The canonical mistake, that bugs makes, is that the very last note should be C, but ends up too high or low.
caught mistakes
canonical player error (on penny whistle)
canonical player error with detection mistake
other error and mistake (on recorder)
The second note is intentionally wrong. The others are detected as errors due to mis-recognition from the original audio (or maybe I played it wrong on my recorder and can't tell) |
good versions (no mistakes played and no mistakes found)
successful penny whistle (best suited to Irish tunes anyway)
|
|
Yosemite Sam frustrated on piano
Yosemite Sam's correct, lethal, attempt at the song, cut off just before explosion.
|
bad identifications
Bugs Bunny playing piano
Deferring to the holy law of triples, Bugs Bunny attempts the tune twice before Sam gets frustrated and gets it right (wrong) the third time. My attempt at catching Bugs Bunny's mistakes failed due to the limits of the simple recognizer that I built on top of, evident in the screenshots. This may be due to recording quality, or maybe the fact that it is played on piano. I am tempted to rule that out though, because I recognized Yosemite Sam fine, and he played on the same piano.
guitar
Guitar was problematic. Probably due to the attacks. |