Here’s a little tid-bit that I’d like to make note of. In a previous MASM32 windows development tutorial, I needed a random number generator and was able to dig this one up from the archives.
First of all, you need to make sure we’re using the 586 instruction set - at least!
; minimum instruction set requirement.586
Shortly, it will become clear why we need the 586 instruction set. To support the random number generator, we need a bit of state in the shape of two double-words.
; calculation stateprng_xDD0; current seedprng_aDD100711433
These two variables allow the random number generator to know where it’s up to for the next iteration. Changing the initial seed of course will change the sequence of random values that are produced by this routine. The actual function that produces the random number look like this:
PrngGetPROCrange:DWORD; count the number of cycles since; the machine has been resetrdtsc; accumulate the value in eax and manage; any carry-spill into the x state varadceax,edxadceax,prng_x; multiply this calculation by the seedmulprng_a; manage the spill into the x state varadceax,edxmovprng_x,eax; put the calculation in range of what; was requestedmulrange; ranged-random value in eaxmoveax,edxretPrngGetENDP
There it is. That first instruction RDTSC is what we need to turn the 586 instruction set on for. This mnemonic stands for Read Time-Stamp Counter. It will take the number of cycles since the machine has been reset and put this count into the EDX:EAX pair (as the time stamp counter is a 64bit value). From there some calculations are performed to ensure the consistency of state between random value retrieves and also capping to the requested range.
So, not much of tutorial here - just a neat layout of setup code for a few mode X modes I’ve come across now and then.
First of all, just some formalities. Setting Mode X tweaks to the VGA is a massive port-out exercise. Creating the following macro cut down on my code heaps.
I will have an update to this post. There are some nuances that I’d much prefer explain to you with a couple of nice code blocks rather than how I’m just going to throw it into the page.
These chunks will be helpful in page selection and optimizing page draws to multiple pages at once.
I play a lot of music. I mean a lot of music. Guitar, Bass, Piano, Drums, Harp – what ever I can get my hands on, I’ll give it a go. So, the neurons in charge of keeping my technical side in check may have made their way into the creative side of my brain.
The net result was me creating a project that mashes mathematics, data analysis and music theory into a few classed called musica.
So what?
Yeah, basically.. But, I am who I am - so it’ more of a matter of “why not?”.
I’d previously tried building a Ruby on Rails application to give me graphical representations of musically related elements on screen. A scale is a pattern of intervals realised once a root note is put in place. This scale can then be harmonised at every step of the scale by employing every second note from the specific step. How complex these harmonised chords are will depend on how many steps you include in the chords that you build.
The most interesting part of this library, I think, is its distinct lack of database. It has made the code quite verbose in parts but I intend to fix this, even if it does mean employing an intermediary database at a later stage.
What can it do?
The major, harmonic & melodic minor scales (and all of their modes) are statically provisioned. You can use these in code to perform operations like voicing a scale when used in conjunction with a Note object.
Immediately, we can get information about notes:
>>> Notes.by_distance(0)
<musica.notes.Note object at 0x10f961090>
>>> Notes.by_distance(0).__unicode__()
'c'
Information about scales:
>>> Scales.scales[0]
<musica.scales.Scale object at 0x10f963090>
>>> Scales.scales[0].name
'Ionian'
>>> Scales.scales[0].intervals
[<musica.intervals.Interval object at 0x10f961950>, <musica.intervals.Interval object at 0x10f9619d0>, <musica.intervals.Interval object at 0x10f961a50>, <musica.intervals.Interval object at 0x10f961a90>, <musica.intervals.Interval object at 0x10f961b10>, <musica.intervals.Interval object at 0x10f961b90>, <musica.intervals.Interval object at 0x10f961c10>]
Voicing a scale (in this instance voicing Ionian (major) over C)
>>> steps = Scales.scales[0].voice(Notes.by_distance(0))
>>> for s in steps:
... print 'note: ' + s['note'].__unicode__() + ', interval: ' + s['interval'].short_name
...
note: c, interval: PU
note: d, interval: M2
note: e, interval: M3
note: f, interval: P4
note: g, interval: P5
note: a, interval: M6
note: b, interval: M7
Still so much to do …
Still, we need to get chords harmonising from these voiced scales. These are just patterns after all. An intelligent chord builder would also be of value I think. Something where we don’t have to explicitly map out chord names to interval sets statically. Just knowing that a root, major third and perfect fifth are a major chord.