from wave import open as waveOpen from ossaudiodev import open as ossOpen import sys, tty, termios import random ver = "1.1" def playTone(myToneFile): # http://stackoverflow.com/questions/307305/play-a-sound-with-python s = waveOpen(myToneFile,'rb') (nc,sw,fr,nf,comptype, compname) = s.getparams( ) dsp = ossOpen('/dev/dsp','w') try: from ossaudiodev import AFMT_S16_NE except ImportError: if byteorder == "little": AFMT_S16_NE = ossaudiodev.AFMT_S16_LE else: AFMT_S16_NE = ossaudiodev.AFMT_S16_BE dsp.setparameters(AFMT_S16_NE, nc, fr) data = s.readframes(nf) s.close() dsp.write(data) dsp.close() def _getch(): # http://stackoverflow.com/questions/1052107/reading-a-single-character-getch-style-in-python-is-not-working-in-unix fd = sys.stdin.fileno() old_settings = termios.tcgetattr(fd) try: tty.setraw(sys.stdin.fileno()) ch = sys.stdin.read(1) finally: termios.tcsetattr(fd, termios.TCSADRAIN, old_settings) return ch def getNextRand(currentRand, randRangeMax): newRand = random.randrange(0,randRangeMax) while (newRand == currentRand): newRand = random.randrange(0,randRangeMax) return newRand # Setup dictionary of tones here # Full range of tones: fullRange = ( ("Low Bb", "low_Bb.wav"), ("Low B", "low_B.wav"), ("Low C", "low_C.wav"), ("Low C#", "low_C#.wav"), ("Low D", "low_D.wav"), ("Low D#", "low_D#.wav"), ("Low E", "low_E.wav"), ("Low F", "low_F.wav"), ("Low F#", "low_F#.wav"), ("Low G", "low_G.wav"), ("Low G#", "low_G#.wav"), ("Low A", "low_A.wav"), ("Low A#", "low_A#.wav"), ("Middle B", "middle_B.wav"), ("Middle C", "middle_C.wav"), ("Middle C#", "middle_C#.wav"), ("Middle D", "middle_D.wav"), ("Middle D#", "middle_D#.wav"), ("Middle E", "middle_E.wav"), ("Middle F", "middle_F.wav"), ("Middle F#", "middle_F#.wav"), ("Middle G", "middle_G.wav"), ("Middle G#", "middle_G#.wav"), ("Middle A", "middle_A.wav"), ("Middle A#", "middle_A#.wav"), ("High B", "high_B.wav"), ("High C", "high_C.wav"), ("High C#", "high_C#.wav"), ("High D", "high_D.wav"), ("High D#", "high_D#.wav"), ("High E", "high_E.wav"), ("High F", "high_F.wav"), ("High F#", "high_F#.wav")) middleRange = fullRange[7:21] lowMiddleRange = fullRange[0:21] soundDictionary = middleRange print "Intonation/Transcription Ear Developer " + ver print "\nSpace to play tone, 0 for answer, Enter for next tone, q to quit" kbValue = ord(_getch()) # set a random note at start random.seed() currentRand = random.randrange(0,len(soundDictionary)) currentSound = soundDictionary[currentRand-1] while 1: if kbValue == 32: print "Playing tone." playTone(currentSound[1]) playTone(currentSound[1]) elif kbValue == 13: currentRand = getNextRand(currentRand, len(soundDictionary)) currentSound = soundDictionary[currentRand-1] print "Switched to another tone." elif kbValue == 48: print "The answer is: " + currentSound[0] elif kbValue == 113: break kbValue = ord(_getch())So basically what it does is very simple, play back a specific sound sample, which I will try to use my ears and saxophone to match. In essence this will achieve two things.
First, figuring out a particular note will aid recognition of the particular note, and that will aid transcription. Secondly, with the playback, assuming I can figure out the note, if I can harmonize with the note should help with my intonation.
Hope it works :)
Edit: 27th September 2011
After some real world use, I found that randrange kept giving very close values for the small range I'm using, so additional code was used to ensure the previous tone would not be the next one as well.