Debugging Realtime by Ear. Adding one more dimension

I am amazed by people who can pick out every single note and chord when listening to music, and others who can totally play by ear. However even the musically inept and tone-deaf of us can detect an odd note, especially if its in a tune we know, but often even in an unknown tune, we can detect an out of place note, that isn't in the scale, whether we know what a scale is, or even what key the song is in.

So what's this got to do with debugging? We'll mostly it’s the real time aspect. You are able to process a lot of information (notes), in context, and are able to discern real-time what is out of place and wrong.

Compare that to typical debugging. You might use checkpoints, and tracing through code, slowing down the execution often a million-fold, tediously stepping through each line of code, looking here and there.
Alternatively you might be processing log output, whether a debug stream in your IDE, console output, or something else. However just getting those messages to somewhere you can display can be hard when threading, and you aren't in the GUI thread etc.
Additionally you are having to interpret this, often after the fact, and you can often miss things when lots is going on. How often , especially when finding a rare threading bug, are you running something 10 or more times, and maybe logging 10 or so different events each time. Going through the log takes time, and sometimes you miss the cue.

So, is debugging with sounds going to change and revolutionize everything? No its just another tool in a really great toolkit we have these days.

I thank my friend Oisin Grehan (http://nivot.org ) for inspiring this as I don't think I've used sound in debugging since the my  Demoscene  days when I was coding MOD players. Mod Players . So naturaller the tracker syntax has inspired me a bit.

So how does this work. Well work out the steps you are listening to, and maybe things you particularly want to catch, play the notes over and over a few times so you know mentality what to expect, then just start running you code, and listen to what actually IS happening, and then maybe at certain times you might make a certain note MEAN something (like middle  C  for TRUE function result and middle A for FALSE), but I typically just use notices to indicate execution flow, and if I want to know some value, I ask windows Speech API to help me out.

function Play-Note([string]$note,[int] $duration = 5) 
{ 
  if (!($note -match '(\d+)')) { $note+='4' };[void]($note -match '([A-G#]{1,2})(\d+)') 
  [console]::Beep((440 * [math]::Pow([math]::pow(2,(1/12)), 
    (([int] $matches[2]) - 4)* 12 + $( switch($matches[1]) 
  {  'A'  { 0 }  'A#' { 1 }  'Bb' { 1 }  'B'  { 2 }  'C'  { 3 }  'C#' { 4 }  'Db' { 4 } 
     'D'  { 5 }  'D#' { 6 }  'Eb' { 6 }  'E'  { 7 }  'F'  { 8 }  'F#' { 9 }  'Gb' { 9 } 
     'G'  { 10 } 'G#' { 11 } 'Ab' { 11 } 
  }))),$duration * 100 ) 
} 

So two things. I’ve based the notes on common tracker syntax including the octave. so middle A is A4 , then you have things like F#3 etc. however if as with everything PowerShell we want pithy, so if you don’t put an octave number then it will be 4 by default.

play-note C ; play-note Eb ; play-note "C#”

also i included a duration, so if the want the note to be anything but the default half a second put that as a parameter

play-note Eb4 20

and you’ll get an E flat for 2 whole seconds. You may ask why I don’t use seconds or milliseconds, because those are our official measurements in this 1,000,000 3 grouped western world. Well the reason is pithiness (something i love in my scripts, but aren’t good about when it comes to blogging). Typically i want a note between say 300 milliseconds and 5 seconds. so if i used milliseconds i’d always have to have those 2 or 3 extra zeros, while if i used seconds I'd be doing things like 0.4 and 1.5. If Japanese and Chinese we often communicate number differently, and group them differently. so there is a word for 10,000 , so to say 15 thousand you may say 1 (character for 10,000) 5.

So what about voice. You can use a very simple function using the SAPI COM objects such as:

function Speak-words ([string]$words,[bool]$pause = $true) 
{   $flag = 1 
    if ($pause) {$flag = 2} 
    $voice = new-Object -com SAPI.spvoice 
    $voice.speak($words, [int] $flag) 
    # 2 means wait until speaking is finished to continue 
} 

Typically though i don’t create a $voice everytime , but kept a reference somewhere , like in my V2 module. Others however have done more impressive things with the voice in powershell ( http://poshcode.org/667 | http://huddledmasses.org/powershell-speaks/ ).

So now you may want a way to play more notes and speak more words together, in a pithy line. you can just use play-notes

function Play-Notes 
{ 
$defaultduration = 5;if($args[0] -is [int]) {$defaultduration = $args[0]} 
for($i = 0;$i -lt $args.length;$i++) 
 {    $duration = $defaultduration 
    if ($i -lt $args.length-1) { if ($args[$i+1] -is [int]) {$duration = $args[$i+1] } } 
    if ($args[$i] -is [string]) { 
        if ($args[$i].startswith("!")) { speak-words $args[$i].replace('!','') } else 
        { play-note $args[$i] $duration } 
        } 
 } 
} 

And with this you can simply pass in a list of notes, which will be played with a default duration, unless you choose to specify a duration after the note.

play-notes A B C 20 E 10 B 10

play-notes F5 2 E5 2 D5 2 C5 2 B5 2 A5 2 G 4 F5 2 E5 2 D5 2 C5 2 B5 2 A5 2 G 4

If you want to change the default duration to reduce the redundancy above, just put that number as the first parameter

play-notes 2 F5 E5 D5 C5 B5 A5 G 4 F5 E5 D5 C5 B5 A5 G 4

and finally if you want some speaking in there, just have your string start with an exclamation mark!

play-notes "!here we go now" Db5 Db Eb Gb Ab "C#" 6 !YEAH 

But of course most of the time you will have speaking, you’ll want it to say something you don’t know like a variable or the results of a formula.

play-notes A"!$([datetime]::now)" C

So you can get all these functions together at poshcode. ( Script | Download )  . We’ll time will tell if this will stay a habit of mine or be a fad. Additionally if you wanted to take this seriously you’d probably want to use something better than console.beep , maybe you’d use a full on MOD engine like http://fmod.org/ and having it running iringn a different process, and have a very cpu lightweight IPC going on, and different threads could play different channels, so between threads you could debug via Chords if you really have the ear for it.

WARNING, NOT A CUBICLE FRIENDLY DEBUGGING TECHNIQUE WITHOUT HEADPHONES UNLESS YOU WANT YOUR COLLEGUES TO DEBUG YOU.

Enjoy,

Karl

Posted Jan 30 2009, 09:30 PM by Karl Prosser
Filed under:
Copyright 2012 PowerShell.com. All rights reserved.