Issue 50 June 6, 2008 | ||
Chorduroy: Revolution Once again we are returning to the chord generating stack to see if we can make it actually do something a little more useful, like actually showing you how to play these random lists of notes on an instrument. Now that our framework for the stack is laid out fully it's time to sort through the various ways of playing these chords and display this information. The version of the stack included with this newsletter has been given a few extra controls which will be required for laying out the chord information: The variations field indicates how many different arrangements of the currently selected chord can be played in the selected region of the fretboard. This field is non editable, the dropdown menu below it however allows you to select which of these variations is currently displayed. I should probably explain first of all that this program works out all the possible combinations of the chord notes using as many strings as possible, therefore there are further combinations that involve removing notes from each of the combinations. For example in the above diagram a C chord could actually be played using just the 3 notes from the A, D and G strings, or just the three notes from the D,G and B strings. So for the moment I'm going to ignore that aspect of the possible ways to play a chord and simply indicate all the combinations with as many strings used as possible. This way the user can choose to subtract which notes from a combination they wish to play. So as before the commands required to perform this stage are held in the script of the guitar fretboard group. The handlers we will look at are "matchChordNotes" and "getPermutations". Both of these are called by sending the appropriate message from the card script "refreshCard" command up to the fretboard group script. Below you can see the entire matchChordNotes handler: local tChordNotes, tFieldName, tNoteBins put the cChordNotes of this card into tChordNotes repeat with stringIndex = 1 to 6 repeat with fretIndex = 1 to 5 put "str" & stringIndex && "fret" & fretIndex into tFieldName repeat for each item tNote in tChordNotes if the text of field tFieldName is tNote then put tNote && tFieldName & "," after tNoteBins end if end repeat end repeat if line stringIndex of tNoteBins is empty then put "x" after tNoteBins end if put return after tNoteBins end repeat delete the last char of tNoteBIns return tNoteBins The purpose of this function is to return a list of which chord notes are present on each string, with each string's list being placed on a different line of the returned variable. This performs the most basic part of the processing which is eliminating any notes from each string that are not contained within the selected chord, since these are the only notes we are interested in. So as you can see above, each field is examined individually, cycling in a nested repeat through the columns and then the rows. For each field it then repeats through the items of the chord notes and checks for a match against the text of that current field. If it does match the name of that field (which incidentally indicates the string and fret number) it is placed in the appropriate line of the tBins variable which will eventually contain the return delimited list of what notes are present on each string. So going back to look at figure 1, after the call to matchChordNotes is made tNoteBins will contain: E str1 fret1,G str1 fret4, This list can now be returned and processed, obviously this particular list presents only a few possible combinations. send "matchChordNotes" to group "Fretboard" of this card put the result into tBins send "getPermutations tBins" to group "Fretboard" of this card So after the call has been made to the matchChordNotes function the returned value needs to be stored. This is achieved by putting "the result" into a variable on the line immediately succeeding the line calling the function. Once stored the variable can be passed to the next command which will calculate the chord combinations, getPermutations, which again is stored in the script of the fretboard group. local tResults, tResult, tChord, tInvalid, tTempResult put false into tInvalid put the cChordNotes of this card into tChord repeat for each item tNote1 in line 1 of pBins repeat for each item tNote2 in line 2 of pBins repeat for each item tNote3 in line 3 of pBins repeat for each item tNote4 in line 4 of pBins repeat for each item tNote5 in line 5 of pBins repeat for each item tNote6 in line 6 of pBins This command consists of six nested repeat loops that simply cycle through the available notes of each line and store the results in a return delimited list as follows. put tNote1 & comma & tNote2 & comma & tNote3 & comma & tNote4 & comma & tNote5 & comma & tNote6 into tResult One item from each line must be included in each combination. Lines without chord notes have an "x" character to store in place of a note. However this will produce some invalid combinations that do not include all the necessary notes required to produce the selected chord. Therefore each combination is cycled through to determine whether it is valid as follows: repeat for each item tNote in tChord if tNote is not among the items of tTempResult then put true into tInvalid end if end repeat Following this check the valid results are then placed into the tResults variable followed by a return character. At this point the number of lines of the tResults variable is placed into the "Variations" field. Next the variant chooser needs to be updated: local tChordVariants repeat with tChordCount = 1 to the number of lines of tResults put "variant " & tChordCount & return after tChordVariants end repeat delete the last char of tChordVariants set the text of button "chord variant chooser" to tChordVariants set the cChordVariants of button "chord variant chooser" of this card to tResults The control that allows the selection of the different chords is an "option menu". The contents of the menu that appears when you select one of these controls is controlled by the "text" of the button. In this menu I have chosen to represent each combination with a simple list, each item being named "variant x" where x is an integer. This is dealt with by the repeat loop above. However the control needs to be functional so I've also set a custom property of the button that contains "tResults". All that remains is to update the fretboard view with one of these combinations and highlight the relative notes. This is carried out by the "colorizeNotes" handler. lock screen local tPermutation put line (word -1 of the label of button "chord variant chooser") of the cChordVariants of button "chord variant chooser" into tPermutation So firstly we store the currently selected combination, by selecting the line of the custom property, which contains all the variations corresponding to the drop down selection as shown by the code above. Next we reset all the fields in the fretboard group to have black text. repeat with i = 1 to the number of fields of me set the foregroundColor of field i of me to black set the textStyle of field i of me to empty end repeat Finally we cycle through all the items of the currently selected combination and set the "foregroundcolor" of the corresponding field to red and apply a bold text style. repeat for each item tNote in tPermutation if tNote is not "x" then set the foregroundColor of field (word 2 to 3 of tNote) to red set the textStyle of field (word 2 to 3 of tNote) to bold end if end repeat unlock screen The control that allows you to select the chord variation simply contains the following script: on menuPick pItemName send "colorizeNotes" to group "Fretboard" of this card end menuPick So this covers the operation of all the controls present on this stack. Hopefully you've followed everything ok and you might even find a use for this stack. There are a few expansions I'd like to include, like an option to display the chord on a piano keyboard and also the option to include notes played on the open strings of the guitar. So it's possible you may not have seen the last of this newsletter series just yet . . . |