Guitar Tutor Design
(New page: Domain Design) |
m (Reverted edits by Ebybymic (Talk); changed back to last version by Jason Clutterbuck) |
||
(33 intermediate revisions by 2 users not shown) | |||
Line 1: | Line 1: | ||
− | [[Image:GuitarTutorDomainDesigh1.jpg|thumb|Domain Design]] | + | I like to play guitar and like any musician I would like to play it much better. My music theory is reasonably good so last year I did a jazz course and picked up a bit of experience playing on stage. I'm not so good at improvisation yet and so I have decided to create a tool that will help me improve . It seems like a good idea for an OO project and so here it is. |
+ | |||
+ | [[Guitar Tutor Report]] | ||
+ | |||
+ | [[Image:GuitarTutorDomainDesigh1.jpg|thumb|Domain Design 1]] | ||
+ | ==Scenarios== | ||
+ | '''Chord Chart Practice.''' | ||
+ | * The user loads a chord chart for the song they want to practice. | ||
+ | * The user presses the start button. After a short pause the program will count in two full bars then an indicator will start to scroll along the chart to mark progress in time with the tempo. | ||
+ | |||
+ | * The user plays notes on the instrument. These notes and their duration are recorded on the chord chart . Notes are coloured one colour for correct and another for incorrect. | ||
+ | |||
+ | * The chart is repeated X (default 3) times or until the user presses the start button a second time. | ||
+ | |||
+ | |||
+ | |||
+ | Chord charts can be of the form ABA, ABAC, ABB, etc. with repeats. | ||
+ | |||
+ | The first obvoius change is that ''Bar'' needs to be abstract with concrete classes for the first, last and intervening bars as well as a bar for the start of a repeated section and the end of a repeated section. | ||
+ | |||
+ | Chords can be of the form: Major, (Major7, Major6, Major6-9, MAJOR7#11), Dominant7, (Dominant9 Dominant13), Sus(b7), minor (minor7, minor9, minor11, minor13), Diminant#5/#9, Dominant#5/b9, Half-diminished, Diminished, augmented Major7, augmented7 and minor major7 to name a few. | ||
+ | Not sure how to represent these yet. Maybe an enum, maybe a class hierarchy. | ||
+ | |||
+ | To implement the timing for the indicator to move across the chart a ''Metronome'' class must be introduced that will be watched by the ''Chart'' class. The ''Metronome'' class will have the ''Tempo'' and the ''TimeSignature'' to work out the ''Beat'' from. The [[Observer|Observer pattern]] might solve this timing problem. | ||
+ | |||
+ | Initially the chart will just be a simple text file but eventually the files will be in [http://www.musicxml.org/ MusicXML] and maybe other formats will be useful. The [[Strategy|Strategy pattern]] would leave the program in a state that is easily extended in this direction. | ||
+ | |||
+ | |||
+ | |||
+ | == Class responsibilities== | ||
+ | |||
+ | {| cellpadding="5" | ||
+ | |||
+ | |width="15%"|'''Class Name''' | ||
+ | |width="35%"|'''Class Responsabilities''' | ||
+ | |width="15%"|'''Super Class''' | ||
+ | |width="15%"|'''Collaborations''' | ||
+ | |width="20%"|'''Notes''' | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Chart'' | ||
+ | | | ||
+ | * Add Notes | ||
+ | * Draw self | ||
+ | * Load self | ||
+ | * Start play | ||
+ | * Stop play | ||
+ | * Update display to show beats passing | ||
+ | | | ||
+ | |''Bar'', ''Tempo'', ''TimeSignature'' | ||
+ | | | ||
+ | |||
+ | |-valign="top" | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Instrument'' | ||
+ | | | ||
+ | * Produce notes from input. | ||
+ | | | ||
+ | |''Chart'', ''Metronome'' | ||
+ | |Is the note passed to the chart for insertion when it it begins creation or after the end has been detected? | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Main'' | ||
+ | | | ||
+ | * Initialise all components and create program structure. | ||
+ | | | ||
+ | |''Chart'', ''Instrument'' | ||
+ | | | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Metronome'' | ||
+ | | | ||
+ | * Know the elapsed time, | ||
+ | * Click for each beat. | ||
+ | | | ||
+ | |''TimeSignature'', ''Tempo'' | ||
+ | |Watches system clock. | ||
+ | The metronome is polled by ''Instrument'' when notes are created and [[Observer|observed]] by ''Chart'' so the chart is notified for each beat. | ||
+ | Maybe a good candidate for a separate thread. | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Tempo'' | ||
+ | | | ||
+ | * know the speed of the tempo, | ||
+ | * Draw self | ||
+ | | | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Bar'' | ||
+ | | | ||
+ | * Draw Self | ||
+ | * Add notes | ||
+ | * Know ''TimeSignature'' | ||
+ | * Know the next bar | ||
+ | * Draw progress marker | ||
+ | | | ||
+ | |''Note'', ''TimeSignature'', ''Bar'' | ||
+ | |Abstract class. | ||
+ | |-valign="top" | ||
+ | |''Pitch'' | ||
+ | | | ||
+ | * Know the octave | ||
+ | * Know the <strike>note</strike> tone | ||
+ | | | ||
+ | | | ||
+ | | There are only a handful of tones (12, 21 with aliases) and humans can only hear ten octaves., | ||
+ | These two components may be represented [[flyweight]] or [[Enum idiom]] | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Scale'' | ||
+ | | | ||
+ | * <strike>Know root note</strike> | ||
+ | * Know if a note is valid for this scale given the root note and a note to test | ||
+ | | | ||
+ | | | ||
+ | |There are only a handful of scale types. | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Note'' | ||
+ | | | ||
+ | * Draw self | ||
+ | * know pitch | ||
+ | * know start time | ||
+ | * know note length <strike> know stop time</strike> | ||
+ | * Know validity (coloured different in interface) | ||
+ | |||
+ | | | ||
+ | |''Pitch'' | ||
+ | |The word note is used in ''Pitch'' making it a bit ambiguous so a new term must be found for in ''Pitch'' | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Chord'' | ||
+ | | | ||
+ | * Know correct scale | ||
+ | * Know root note ''Contained in scale? Maybe scales should be root independent.'' | ||
+ | * <strike>know notes in chord. ''This is for played chords not written chords. Does this suggest a new class?''</strike> | ||
+ | | | ||
+ | |"Scale'',the note component of ''Pitch''(maybe ''Tone''?) | ||
+ | |Only using 7th, Major7th, Minor7th, Half diminished and Diminished chords this implementation | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Time Signature'' | ||
+ | | | ||
+ | * Draw self | ||
+ | * Knows how many beats in bar | ||
+ | * Knows what type of beat | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Tie'' | ||
+ | | | ||
+ | * Draw self | ||
+ | * Know Start note | ||
+ | * Know end note | ||
+ | |||
+ | |-valign="top" | ||
+ | |''StartRepeatBar'' | ||
+ | | | ||
+ | * Accept control from ''EndRepeatBar'' or previous bar | ||
+ | |''Bar'' | ||
+ | | | ||
+ | |-valign="top" | ||
+ | |''EndRepeatBar'' | ||
+ | | | ||
+ | * Know how many times repeat occours | ||
+ | * Pass control onto nextbar and reset repeat count | ||
+ | '''or''' | ||
+ | * Pass control on to ''StartRepeatBar'' | ||
+ | |''Bar'' | ||
+ | |||
+ | |-valign="top" | ||
+ | |FirstBar | ||
+ | | | ||
+ | * Know time signature | ||
+ | * Draw ''TimeSignature'' | ||
+ | |''Bar'' | ||
+ | |''TimeSignature'' | ||
+ | |-valign="top" | ||
+ | |''LastBar'' | ||
+ | | | ||
+ | * End playback | ||
+ | '''or''' | ||
+ | * Return to beginning of ''Chart'' | ||
+ | |''Bar'' | ||
+ | |||
+ | |-valign="top" | ||
+ | |''NormalBar'' | ||
+ | | | ||
+ | |''Bar'' | ||
+ | | | ||
+ | |Illnustrates the confliction tensions between [[Avoid concrete base classes]] and [[Eliminate irrelevant classes]] or maybe it is [[Avoid inheritance for implementation|avoiding inheritance for implementation]] | ||
+ | |||
+ | |||
+ | |-valign="top" | ||
+ | |''LastBarEndRepeat'' | ||
+ | | | ||
+ | * Return to begining of repeat | ||
+ | '''or''' | ||
+ | * Return to begining of song | ||
+ | '''or''' | ||
+ | * End playback | ||
+ | |''Bar'' Maybe this should inherit from ''LastBar'' or ''EndRepeat'' or both | ||
+ | | | ||
+ | |Maybe Multiple [[Inheritance]] is not always a bad thing looks like I have to break the [[Once and only once]] principle some might say [[Don't repeat yourself]]. I have a friend who once said [[Duplicate code smell]]. There is a solution I'm sure | ||
+ | |||
+ | |-valign="top" | ||
+ | |FirstBarStartRepeat | ||
+ | | | ||
+ | * Accept control from EndRepeatBar or previous bar | ||
+ | * Know time signature | ||
+ | * Draw TimeSignature | ||
+ | |''Bar'' Maybe it should extend ''FirstBar'' or ''EndRepeat'' or ideally both. | ||
+ | |''TimeSignature'' | ||
+ | |See note for ''LastBarEndRepeat'' | ||
+ | |-valign="top" | ||
+ | |||
+ | |} | ||
+ | |||
+ | '''<u>CRC Cards are COOL!</u>''' | ||
+ | |||
+ | |||
+ | [[Image:GuitarTutorDomainDesigh2.jpg|650px|Domain Design iteration 2]] | ||
+ | |||
+ | ====Further Problems:==== | ||
+ | |||
+ | * What should be done about isomorphic chords, scales, notes. The [[Enum idiom]] seems to take care of most of this. | ||
+ | * Maybe the note type should be represented in a class hierarchy. What happens then with notes that are too big to fit into the remaining portion of a bar? What happens if the notes are added on creation rather than completion? | ||
+ | * should there only be one of each type of ''Note'', ''Chord'', ''TimeSignature''? [[Flyweight]]? | ||
+ | * How do I associate the chord changes with the right beat in the bar? Every bar | ||
+ | * What am I going to do about triplets?( do I need to do anything right now?) | ||
+ | * Is my use of enums adequate or is it just going to create unnecisary conditional hierarchies? | ||
+ | * Introducing the concept of a curser will help solve the problem of keeping track of drawing coordinates for positioning each bar. So does extracting the view away from the domain implementation. Life gets so much easier when you find a package like jm.gui.cpn which is a java package for displaying musical data in a gui. [[Don't reinvent the wheel]] | ||
+ | * How am I going to implement the GUI here? I guess [[model view controller]] might be a good place to start looking. I don't need MVC because there is no controller so i just need to implement [[Interface segregation principle ]]. | ||
+ | * Can repeat be extracted to somewhere else? maybe the [[Decorator|decorator pattern]]. It looks as though it will be best represent this as a container with specialised behaviour. If i break it down like this i am heading towards having a bar object and a hierarchy of flow control containers. that could be a better way to look at it maybe. | ||
+ | * It might just be my naivety but I'm wondering how much is to much when it comes to the depth of a recursion introduction opporation. | ||
+ | * there might be a nice way of only updating and redrawing the bars that have changed. | ||
+ | |||
+ | |||
+ | |||
+ | == Class responsibilities (Take 2)== | ||
+ | |||
+ | {| cellpadding="5" | ||
+ | |||
+ | |width="15%"|'''Class Name''' | ||
+ | |width="35%"|'''Class Responsabilities''' | ||
+ | |width="15%"|'''Super Class''' | ||
+ | |width="15%"|'''Collaborations''' | ||
+ | |width="20%"|'''Notes''' | ||
+ | |||
+ | |-valign="top" | ||
+ | |''Chart'' | ||
+ | | | ||
+ | * Add Notes | ||
+ | * Draw self | ||
+ | * Load self | ||
+ | * Start play | ||
+ | * Stop play | ||
+ | * Update display to show beats passing | ||
+ | * Know how many times the chart has been played | ||
+ | | | ||
+ | |''Bar'', ''Tempo'', ''TimeSignature'' | ||
+ | | Taking the counting of full repetitions of the chart out of bar so there is no need for start and end bar specialisation. | ||
+ | |||
+ | |-valign="top" |
Latest revision as of 03:17, 25 November 2010
I like to play guitar and like any musician I would like to play it much better. My music theory is reasonably good so last year I did a jazz course and picked up a bit of experience playing on stage. I'm not so good at improvisation yet and so I have decided to create a tool that will help me improve . It seems like a good idea for an OO project and so here it is.
Contents |
Scenarios
Chord Chart Practice.
- The user loads a chord chart for the song they want to practice.
- The user presses the start button. After a short pause the program will count in two full bars then an indicator will start to scroll along the chart to mark progress in time with the tempo.
- The user plays notes on the instrument. These notes and their duration are recorded on the chord chart . Notes are coloured one colour for correct and another for incorrect.
- The chart is repeated X (default 3) times or until the user presses the start button a second time.
Chord charts can be of the form ABA, ABAC, ABB, etc. with repeats.
The first obvoius change is that Bar needs to be abstract with concrete classes for the first, last and intervening bars as well as a bar for the start of a repeated section and the end of a repeated section.
Chords can be of the form: Major, (Major7, Major6, Major6-9, MAJOR7#11), Dominant7, (Dominant9 Dominant13), Sus(b7), minor (minor7, minor9, minor11, minor13), Diminant#5/#9, Dominant#5/b9, Half-diminished, Diminished, augmented Major7, augmented7 and minor major7 to name a few. Not sure how to represent these yet. Maybe an enum, maybe a class hierarchy.
To implement the timing for the indicator to move across the chart a Metronome class must be introduced that will be watched by the Chart class. The Metronome class will have the Tempo and the TimeSignature to work out the Beat from. The Observer pattern might solve this timing problem.
Initially the chart will just be a simple text file but eventually the files will be in MusicXML and maybe other formats will be useful. The Strategy pattern would leave the program in a state that is easily extended in this direction.
Class responsibilities
Class Name | Class Responsabilities | Super Class | Collaborations | Notes |
Chart |
|
Bar, Tempo, TimeSignature | ||
Instrument |
|
Chart, Metronome | Is the note passed to the chart for insertion when it it begins creation or after the end has been detected? | |
Main |
|
Chart, Instrument | ||
Metronome |
|
TimeSignature, Tempo | Watches system clock.
The metronome is polled by Instrument when notes are created and observed by Chart so the chart is notified for each beat. Maybe a good candidate for a separate thread. | |
Tempo |
|
|||
Bar |
|
Note, TimeSignature, Bar | Abstract class. | |
Pitch |
|
There are only a handful of tones (12, 21 with aliases) and humans can only hear ten octaves.,
These two components may be represented flyweight or Enum idiom | ||
Scale |
|
There are only a handful of scale types. | ||
Note |
|
Pitch | The word note is used in Pitch making it a bit ambiguous so a new term must be found for in Pitch | |
Chord |
|
"Scale,the note component of Pitch(maybe Tone?) | Only using 7th, Major7th, Minor7th, Half diminished and Diminished chords this implementation | |
Time Signature |
| |||
Tie |
| |||
StartRepeatBar |
|
Bar | ||
EndRepeatBar |
or
|
Bar | ||
FirstBar |
|
Bar | TimeSignature | |
LastBar |
or
|
Bar | ||
NormalBar | Bar | Illnustrates the confliction tensions between Avoid concrete base classes and Eliminate irrelevant classes or maybe it is avoiding inheritance for implementation
| ||
LastBarEndRepeat |
or
or
|
Bar Maybe this should inherit from LastBar or EndRepeat or both | Maybe Multiple Inheritance is not always a bad thing looks like I have to break the Once and only once principle some might say Don't repeat yourself. I have a friend who once said Duplicate code smell. There is a solution I'm sure | |
FirstBarStartRepeat |
|
Bar Maybe it should extend FirstBar or EndRepeat or ideally both. | TimeSignature | See note for LastBarEndRepeat |
CRC Cards are COOL!
Further Problems:
- What should be done about isomorphic chords, scales, notes. The Enum idiom seems to take care of most of this.
- Maybe the note type should be represented in a class hierarchy. What happens then with notes that are too big to fit into the remaining portion of a bar? What happens if the notes are added on creation rather than completion?
- should there only be one of each type of Note, Chord, TimeSignature? Flyweight?
- How do I associate the chord changes with the right beat in the bar? Every bar
- What am I going to do about triplets?( do I need to do anything right now?)
- Is my use of enums adequate or is it just going to create unnecisary conditional hierarchies?
- Introducing the concept of a curser will help solve the problem of keeping track of drawing coordinates for positioning each bar. So does extracting the view away from the domain implementation. Life gets so much easier when you find a package like jm.gui.cpn which is a java package for displaying musical data in a gui. Don't reinvent the wheel
- How am I going to implement the GUI here? I guess model view controller might be a good place to start looking. I don't need MVC because there is no controller so i just need to implement Interface segregation principle .
- Can repeat be extracted to somewhere else? maybe the decorator pattern. It looks as though it will be best represent this as a container with specialised behaviour. If i break it down like this i am heading towards having a bar object and a hierarchy of flow control containers. that could be a better way to look at it maybe.
- It might just be my naivety but I'm wondering how much is to much when it comes to the depth of a recursion introduction opporation.
- there might be a nice way of only updating and redrawing the bars that have changed.
Class responsibilities (Take 2)
Class Name | Class Responsabilities | Super Class | Collaborations | Notes |
Chart |
|
Bar, Tempo, TimeSignature | Taking the counting of full repetitions of the chart out of bar so there is no need for start and end bar specialisation. |