Warning: Table './devblogsdb/cache_page' is marked as crashed and last (automatic?) repair failed query: SELECT data, created, headers, expire, serialized FROM cache_page WHERE cid = 'http://www.softdevblogs.com/?q=aggregator/categories/8' in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc on line 135

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 729

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 730

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 731

Warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/bootstrap.inc on line 732
Software Development Blogs: Programming, Software Testing, Agile, Project Management
Skip to content

Software Development Blogs: Programming, Software Testing, Agile Project Management

Methods & Tools

Subscribe to Methods & Tools
if you are not afraid to read more than one page to be a smarter software developer, software tester or project manager!

Requirements
warning: Cannot modify header information - headers already sent by (output started at /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/database.mysql.inc:135) in /home/content/O/c/n/Ocnarfparking9/html/softdevblogs/includes/common.inc on line 153.

Managing Programmers

From the Editor of Methods & Tools - Tue, 02/09/2016 - 15:24
Programmers are not like the other kids. They cannot and should not be managed like normal people if your intent is to produce high quality software. The things you would do to make the process go faster will actually make things go slower. This session gives you insight on the care and feeding of programmers, […]

Successful Software Development Project Failures

From the Editor of Methods & Tools - Mon, 02/01/2016 - 15:10
Software development projects have always been challenging. The most referenced source for metrics about project success is the Standish Group yearly CHAOS report. According to this source, around 30% of software development project were considered as a “failure” in the recent years. The failure rate of larger projects is a little bit higher than the […]

Software Development Conferences Forecast January 2016

From the Editor of Methods & Tools - Tue, 01/26/2016 - 09:34
Here is a list of software development related conferences and events on Agile project management ( Scrum, Lean, Kanban), software testing and software quality, software architecture, programming (Java, .NET, JavaScript, Ruby, Python, PHP), DevOps and databases (NoSQL, MySQL, etc.) that will take place in the coming weeks and that have media partnerships with the Methods […]

Software Development Linkopedia January 2016

From the Editor of Methods & Tools - Mon, 01/18/2016 - 15:44
Here is our monthly selection of knowledge on programming, software testing and project management. This month you will find some interesting information and opinions about organizational debt, product owner types, flat structures, mature developers, keeping your head cool, working with UX, technical requirements management, software architecture, group problem-solving techniques and thinking slow in software development. […]

Social Side of Code, Database CI and REST API Testing in Methods & Tools Winter 2015 issue

From the Editor of Methods & Tools - Mon, 01/11/2016 - 14:29
Methods & Tools – the free e-magazine for software developers, testers and project managers – has published its Winter 2015 issue that discusses the social side of code, database continuous intergration and testing REST API. Methods & Tools Winter 2015 issue content: * Meet the Social Side of Your Codebase * Database Continuous Integration * […]

Quote of the Month January 2016

From the Editor of Methods & Tools - Wed, 01/06/2016 - 16:19
Testing by itself does not improve software quality. Test results are an indicator of quality, but in and of themselves, they don’t improve it. Trying to improve software quality by increasing the amount of testing is like trying to lose weight by weighing yourself more often. What you eat before you step onto the scale […]

Software Architecture for Rookies

From the Editor of Methods & Tools - Wed, 12/23/2015 - 17:10
How frequently have you encountered people who are neither coding- nor tech-savvy discussing software architecture? How frequently are they decision-makers? Yes, it happens, and everyone who experiences it knows what it causes. The point is to find a way to talk about software architecture with all interested stakeholders (even if they are business/product people who […]

Software Development Conferences Forecast December 2015

From the Editor of Methods & Tools - Mon, 12/21/2015 - 16:01
Here is a list of software development related conferences and events on Agile project management ( Scrum, Lean, Kanban), software testing and software quality, software architecture, programming (Java, .NET, JavaScript, Ruby, Python, PHP), DevOps and databases (NoSQL, MySQL, etc.) that will take place in the coming weeks and that have media partnerships with the Methods […]

Ukulele Fun for XMas !

Ukulele

This post is part of the F# Advent Calendar in English 2015 project. Check out all the other great posts there! And special thanks to Sergey Tihon for organizing this.

Hi something fun and not too technical for end the year !

As everyone knows, the favorite instrument of Santa Claus is Ukulele ! So let's play some music, and especialy some Ukulele !

First thing first, let's create functions for notes. We start with C at octave 0, and have a progression by half tones.

So C is 0, D is 2, E is 4.

Since there is only a half tone between E and F, F is 5.

F is 7, A is 9, B is 11, and we reach next octave at 12, which is C 1 :

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
open System

let C n = 12 * n
let D n = C n + 2
let E n = C n + 4
let F n = C n + 5
let G n = C n + 7
let A n = C n + 9
let B n = C n + 11 

For sharps and flat, lets define two functions that had and remove a half tone

1: 
2: 
let sharp n = n + 1
let flat n = n - 1

We can now create names for each note :

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
let Cd = C >> sharp
let Db = D >> flat
let Dd = D >> sharp
let Eb = E >> flat
let Fd = F >> sharp
let Gb = G >> flat
let Gd = G >> sharp
let Ab = A >> flat
let Ad = A >> sharp
let Bb = B >> flat

There is no E sharp or F flat because it is F and E respectively, same thing for B and C...

Will create a structure with a custome comparison/equality that doesn't take the octave into account by using a 12 modulus, this will prove usefull to work with chords:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
[<Struct>]
[<CustomComparison>]
[<CustomEquality>]
[<StructuredFormatDisplay("{Display}")>]
type Note(note : int) =
    member __.Note = note
    
    override __.GetHashCode() = note % 12 

    override __.Equals other =
        match other with
        | :? Note as other ->
            note % 12 = other.Note % 12
        | _ -> false

    static member names = 
        [| "C"
           "C#"
           "D"
           "D#"
           "E"
           "F"
           "F#"
           "G"
           "G#"
           "A"
           "A#"
           "B" |]
    member __.Display = 
        let name = Note.names.[note % 12]
        let octave = note / 12
        sprintf "%s %d" name octave

    override this.ToString() = this.Display
        
    interface IEquatable<Note> with
        member __.Equals other =
            note % 12 = other.Note % 12
    interface IComparable<Note> with
        member __.CompareTo other =
            compare (note % 12) (other.Note % 12) 
    interface IComparable with
        member __.CompareTo other =
            match other with
            | :? Note as other -> 
                compare (note % 12) (other.Note % 12)
            | _ -> 1 

    static member (+) (string: Note, fret: int) =
        Note (string.Note + fret)

let notes = List.map Note

Ukulele Strings

A Ukulele has 4 strings.

The funy thing is that the 1st one is higher than the second one, where on most string instruments strings are in progressive order.

This is simply due to the limited size of the Ukulele, a low first string would not sound good, so it is adjusted to the next octave.

This gives use the following:

1: 
let strings = notes [G 4;C 4;E 4; A 4]

Chords

Instead of hard-encoding ukulele chords, we will compute them !

So a bit of theory about chords.

Chords are defined by their root note and the chord quality (major, minor).

The chords start on the root note, and the chord quality indicates the distance to other notes to include in the chord.

On string instrument, the order and the height of the actual notes are not really important for the chord to be ok. So we can use a note at any octave.

Now, let's define the chord qualities.

First, Major, uses the root note, 3rd and 5th, for instance for C, it will be C, E, G, which gives intervals of 0, 4 and 7 half tones from root.

1: 
2: 
3: 
let quality = notes >> Set.ofList

let M n = quality [n ; n + 4; n+7] 

Then, Minor, uses the root note, the lower 3rd and 5th. For C it will be C, E flat, G, so intervals of 0, 3 and 7 half tones for root.

1: 
let m n = quality [n; n + 3; n+7] 

The 7th adds a 4th note on the Major:

1: 
let M7 n = quality [n; n + 4; n+7; n+11 ]

Frets

As on a gitare, a ukulele has frets, places where you press the string with your finger to change the tone of a string.

0 usually represent when you don't press a string at all, and pinching the string will play the string note.

When pressing fret 1, the note is one half tone higher, fret 2, two half tone (or one tone) higher.

So pressing the second fret on the C 4 string give a D 4.

Our first function will try pressing on frets to find frets for notes that belong to the chord

1: 
2: 
3: 
4: 
5: 
let findFrets chord (string: Note) =
    [0..10]
    |> List.filter (fun fret -> 
        Set.contains (string + fret) chord)
    |> List.map (fun fret -> fret, string + fret)

The result is list of pair, (fret, note) that can be used on the strnig

The second function will explore the combinaison of frets/note and keep only those that contains all notes of the chords.

Ex: for a C Major chord, we need at least a C, a E and a G.

using frets 0 on string G, 0 on string C, 3 on string E, and 3 on string A, we get G, C, G, C.

All notes are part of the chord, but there is no E... not enough. 0,0,0,3 is a better solution.

The function explore all possible solution by checking notes on string that belong to the chord, and each time remove a note from the chord. At the end, there should be no missing note.

At each level sub solutions are sorted by a cost. Standard Ukulele chords try to place fingers as close to the top as possible. So lewer frets are better.

The cost function for a chords is to sum square of frets. If there is any solution, we keep the one with the lowest cost.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
let rec filterChord chord missingNotes solution stringFrets  =
    match stringFrets with
    | [] -> 
        if Set.isEmpty missingNotes then 
            Some (List.rev solution)
        else
            None
    | string :: tail -> 
        string
        |> List.filter (fun (_,note) -> 
            chord |> Set.contains note)
        |> List.choose (fun (fret,note) -> 
            filterChord chord (Set.remove note missingNotes) ((fret,note) :: solution) tail)
        |> List.sortBy(fun s -> 
            List.sumBy (fun (fret,_) -> fret*fret) s)
        |> List.tryHead
       

making a cord is now simple.

Compute the note in the chord using quality and root.

For each string, map possible frets the belong to the chord, then filter it.

1: 
2: 
3: 
4: 
5: 
6: 
7: 
let chord root quality =    
    let chord = quality (root 4)
    strings
    |> List.map (findFrets chord)
    |> filterChord chord chord []
    |> Option.get
    

We can now try with classic chords:

1: 
let CM = chord C M

and the result is:

[(0, G 4); (0, C 4); (0, E 4); (3, C 5)]

Now C minor:

1: 
let Cm = chord C m

which is exactly what you can find on a tab sheet:

[(0, G 4); (3, D# 4); (3, G 4); (3, C 5)]
1: 
2: 
3: 
4: 
5: 
6: 
7: 
chord D m
    
chord A M
chord A m

chord G m
chord E M

Printing chords

To print chords, we will simply use pretty unicode chars, and place a small 'o' on the fret where we should place fingers:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
let print chord  =
    let fret n frt = 
        if n = frt then 
            "o" 
        else 
            "│"
    let line chord n  =
            chord 
            |> List.map (fst >> fret n)
            |> String.concat ""       
    printfn "┬┬┬┬"
    [1..4] 
    |> List.map (line chord)
    |> String.concat "\n┼┼┼┼\n" 
    |> printfn "%s"

Let's try it

1: 
chord C M |> print

It prints

┬┬┬┬
││││
┼┼┼┼
││││
┼┼┼┼
│││o
┼┼┼┼
││││

Another one

1: 
chord G M |> print

and we get

┬┬┬┬
││││
┼┼┼┼
│o│o
┼┼┼┼
││o│
┼┼┼┼
││││
Playing chords

We can also play chords using NAudio.

You can find NAudio on nuget.org

For simplicity I will use the midi synthetizer:

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
#r @"packages\NAudio\lib\net35\NAudio.dll"

open NAudio.Midi
let device = new MidiOut(0)
MidiOut.DeviceInfo 0
let midi (m:MidiMessage) =  device.Send m.RawData

let startNote note volume = 
    MidiMessage.StartNote(note, volume, 2) |> midi

let stopNote note volume = 
    MidiMessage.StopNote(note, volume, 2) |> midi

let sleep n = System.Threading.Thread.Sleep(n: int)

Now we can define a function that will play a chord.

The tempo is used as a multiplicator for a the chord length.

Longer tempo means slower.

For better result we introduce an arpegio, a small delay between each note. Don't forget to remove this time from the waiting length...

The direction indicate if the cords are strumed Up, or Down. In the Up case we reverse the chord.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
type Direction = Dn of int | Up of int

let play tempo arpegio (chord, strum)  =
    let strings, length = 
        match strum with 
        | Dn length -> chord, length
        | Up length -> List.rev chord, length 

    strings
    |> List.iter (fun (_,(n: Note)) -> 
        startNote n.Note 100 ; sleep arpegio )

    let arpegioLength = 
        List.length chord * arpegio

    sleep (length * tempo - arpegioLength)

    strings
    |> List.iter (fun (_,(n: Note)) -> 
        stopNote n.Note 100 )

To strum a chord, we give a list of length, and a chord, and it will apply the cord to each length:

1: 
2: 
3: 
4: 
5: 
6: 
let strum strm chord =
    let repeatedChord = 
        strm 
        |> List.map (fun _ -> chord)
    
    List.zip repeatedChord strm

Now here is Santa Clause favorite song, Get Lucky by Daft Punk.

First the chords :

1: 
2: 
3: 
4: 
5: 
6: 
7: 
8: 
9: 
let luckyChords = 
    [ //Like the legend of the Phoenix,
      chord B m
      // All ends with beginnings.
      chord D M
      // What keeps the planets spinning,
      chord (Fd) m
      // The force from the beginning.
      chord E M ]

Then strum, this is the rythm used to play the same chord, it goes like, Dam, Dam, Dam Dala Dam Dam:

1: 
2: 
let luckyStrum = 
    [ Dn 4; Dn 3; Dn 2; Dn 1; Up 2; Dn 2; Up 2]

and the full song :

1: 
2: 
3: 
let getLucky =
    luckyChords
    |> List.collect (strum luckyStrum)

And now, let's play it :

1: 
2: 
3: 
4: 
getLucky
|> List.replicate 1
|> List.concat
|> List.iter (play 130 30)

And the tab notations for the song !

1: 
2: 
luckyChords
|> List.iter print

┬┬┬┬
││││
┼┼┼┼
│ooo
┼┼┼┼
││││
┼┼┼┼
o│││
┬┬┬┬
││││
┼┼┼┼
ooo│
┼┼┼┼
││││
┼┼┼┼
││││
┬┬┬┬
│o││
┼┼┼┼
o│o│
┼┼┼┼
││││
┼┼┼┼
││││
┬┬┬┬
o│││
┼┼┼┼
│││o
┼┼┼┼
││││
┼┼┼┼
│o││
Conclusion

I hope this small thing was entertaining and that it'll get you into ukulele !

For excercise you can:

  • implements more chords
  • Better printing
  • add more liveliness and groove by adding some jitter to the strum...
  • add the lyrics for Karaoke !
  • try with other songs !
  • try the same for a 6 string gitar !

Now it's your turn to rock !

Categories: Architecture, Requirements

Software Development Linkopedia December 2015

From the Editor of Methods & Tools - Fri, 12/11/2015 - 09:52
Here is our monthly selection of knowledge on programming, software testing and project management. This month you will find some interesting information and opinions about hiring software developers, mobile testing, self-organization, technical debt, Agile testing, product prioritization, menu design, project estimating, Agile learning and Devops in large organizations. Blog: How to Onboard Software Engineers – […]

Quote of the Month December 2015

From the Editor of Methods & Tools - Wed, 12/02/2015 - 08:58
Now more than ever, we need to unleash the talent of individuals, teams, and organizations. This might be the only hope we have to not just survive but thrive. But, too often, we put a wet blanket over the fire of innovation and motivation. In the midst of uncertainty, we attempt to control outcomes by […]

Software Development Conferences Forecast November 2015

From the Editor of Methods & Tools - Mon, 11/23/2015 - 17:14
Here is a list of software development related conferences and events on Agile project management ( Scrum, Lean, Kanban), software testing and software quality, software architecture, programming (Java, .NET, JavaScript, Ruby, Python, PHP), DevOps and databases (NoSQL, MySQL, etc.) that will take place in the coming weeks and that have media partnerships with the Methods […]

Software Development Linkopedia November 2015

From the Editor of Methods & Tools - Thu, 11/19/2015 - 17:55
Here is our monthly selection of knowledge on programming, software testing and project management. This month you will find some interesting information and opinions about software development teams, software engineering management, metrics approaches, UX personas, tools for distributed retrospectives, exploratory testing, Agile principles and load testing. Blog: How to Make the Leap from Engineer to […]

Quote of the Month November 2015

From the Editor of Methods & Tools - Tue, 11/10/2015 - 15:31
Because we are working in such small increments, the only thing we need to come up with at a Retrospective is something to try out for the next few weeks: an experiment. Because we are only going to try the experiment for a limited amount of time, any negative impact is controlled by the fact […]

Grady Booch: The Future of Software Engineering

From the Editor of Methods & Tools - Fri, 11/06/2015 - 10:21
No matter what future we may envision, it relies on software that has not yet been written. Even now, software-intensive systems have woven themselves into the interstitial spaces of civilization, and we as individuals and as a species have slowly surrendered ourselves to computing. Looking back, we can identify several major and distinct styles whereby […]

Software Development Conferences Forecast October 2015

From the Editor of Methods & Tools - Fri, 10/30/2015 - 13:34
Here is a list of software development related conferences and events on Agile project management ( Scrum, Lean, Kanban), software testing and software quality, software architecture, programming (Java, .NET, JavaScript, Ruby, Python, PHP) and databases (NoSQL, MySQL, etc.) that will take place in the coming weeks and that have media partnerships with the Methods & […]

Quote of the Month October 2015

From the Editor of Methods & Tools - Mon, 10/26/2015 - 10:39
The man/month likes the software architect because he can do without thinking. The software architect likes the man/month because he can think without doing. Source: Emanuel Chenu, http://emmanuelchenu.blogspot.fr/2009/02/lhomme-mois-v1.html (translated from French)

Thu, 01/01/1970 - 01:00