Rottytooth

Monday, January 05, 2009

Velato "Hello, World!" tutorial

The GUIDO Notation System is a very intuitive notation for music, so I'll use it for the coding examples. To convert GUIDO scripts to MIDI files, there's the gmn2midi converter. There are plenty of other notation systems (such as LilyPond) which work equally well.

In GUIDO, notes are represented in the format G0/2, where G is the note, 0 is the octave (equivalent to octave 5 in MIDI), and /2 represents a half-note. If the octave is not provided for a note, it uses the previous note's octave -- same for note durations. Rests are underscores. Comments are Pascal-style (* *) and can be used to track commands within the .gmn file.

The actual program

Okay, let's start with printing the 'H' character to the screen. The Velato command to print a character is Major 6th, Major 5th. If we're writing in C, this is the progression C A G (we always have to start commands with the command root note, which, in this case, is C, as we're starting the program with it).

Looking at the expression list in this post, The expression for a char value is 3rd, 4th. The first 3rd could be major or minor, but since we've used E already, we'll use that, as opposed to E& (which is the GUIDO representation of E-flat).

This we follow with the ASCII value of 'H'. This happens to be 72 (there's a list here), which we represent as "a d#" (we get this from the number of half-steps up from the command root, starting up a half-step, and excluding the Perfect 5th -- it's probably easier to just write it out once and refer to it, like the chart in the last post, here). Unfortunately, we ended up using a d# (equivalent to e&) after all. We can make this more palatable by making it part of a chord, either by combining it with the notes ahead or behind it, or with notes in additional tracks which are not part of the program.

We end the integer with a Perfect 5th, which is G. This gives us the complete command:

[ c a g e f a d# g ]


Click to hear actual midi file

After creating a .mid file with gmn2midi, we use Vlt to compile, and see this abstract syntax tree. This helps us verify that we used the correct notes, and didn't end up with some command we didn't intend:
Program

DeclareFunction

PrintToScreen

CharConstant

Now, let's make it sound a bit better.

We can turn this into several chords: a C6 and an F7. Since we're at the end of a command, we can add a C after (that's our command root), which will be interpreted as No-ops. In Guido, we use curly brackets to indicate notes played together -- the notes of the chord are seperated by comma.

This would give us this:

[ {c-1/4, a1, g0, e } { f/4, a, d#1} _/8 
{ g0/4., c1 } ]


midi file

This is an equivalent command (both print the letter 'H'), but the second is a bit more musical. In addition to creating chords, I've also spread the notes into several octaves and altered the rhythma bit.

Next, let's change the command root note to an F. We do this with a Major 2nd interval, followed by the new root note. In this case:

c d f


Now we write the next command (to print 'e'), starting from F instead of C. The first part of the command is the same, only transposed:

f d c a b&


In ASCII, 'e' is 101, which is g f# g -- we end with a Perfect 5th to indicate the end of an integer, so that's a "c" again. The whole command is:

f d c a b& g f# g c


We can combine this with the previous command ('c d f') and make it a bit more musical:

c0/16 d1 f {f-1/8, d1, c0, a} 
{b&1/4, g-1, f#0} _/8 { g0/4., c1}


entire song so far

It's not going to win us any awards for composition yet, but at least it sounds intentional, instead of a bunch of random notes.

Let's change the command root to B& for a bit of a change, and print the next character, the first 'l'.

The two commands are:

f g b& (* change of command root *)

b& g f d e& c b a& f (* print 'l' *)


Or, once we change the rhythm and octaves:

f0/16 g1 b& (* change of command root *)

{b&-1/8, g1, f0, d} {e&1/4, c0, b0} a&1/8
{f/4, b&} b&0 (* print 'l' *)

entire song so far

The rest of the notes are selected using the same technique. We're not going to win any Grammys with our final program, but it's at least somewhat musical (in a free-form jazz sorta way) instead of random notes. With more time and effort, the song could be further composed into something more pleasing. I'll post any further re-workings of the song here.

Complete "Hello, World" program midi file

GUIDO source for complete program

Here's the program as sheet music. Keep in mind that this set of notes is *not* the actual program; if a MIDI file is created from this progression of notes, the concurrent notes might be interpreted in a different order in the file, and create an invalid program.

Labels: ,

Sunday, January 04, 2009

Velato commands

Here is the complete list of commands currently implemented in Velato. For an introduction to the language, see the previous blog post.

List of Commands

All statements start with the command root, followed by one of the following commands. Intervals are from the currant command root note.
command second note third note followed by...
Change Root Note Major 2nd
New root note
Let (assignment) Minor 3rd
Variable as single note, then expression
Declare variable Minor 6th
Variable as single note, then type
Blocks Major 3rd

While
Major 3rd
End While
Perfect 4th
If
Perfect 5th
Else
Major 6th
End If
Major 7th
Special Commands Major 6th

Print to screen
Perfect 5th Expression to print



List of Other Expressions

If an operation is expecting an expression, the list that follows will determine what expression is interpreted. Expressions do not start with the command root note, but all intervals are still determined from it.

Expressions don't differentiate between perfect/diminished, major/minor, so that they can be diatonic to the scale used in the rest of the command. For example, if you're in C, this helps you avoid having a progression like C E C Eb, which could sound random or unmusical, depending on context. The programmer can pick which of the two intervals fits the song better.
expression first note second note third note followed by...
value 3rd (maj/min)


variable
2nd
Name of varaible (since note)
pos. (+) int
5th
Single note for each digit, ending with Perfect 5th to mark end of number
neg. (-) int
3rd
Single note for each digit, ending with Perfect 5th to mark end of number
char
4th
Char as ASCII int: single note for each digit, ending with Perfect 5th to mark end of number
pos. (+) double
6th
Single note for each digit, first Perfect 5th to mark decimal point, second Perfect 5th marking end of number
neg. (-) double
7th
Single note for each digit, first Perfect 5th to mark decimal point, second Perfect 5th marking end of number
conditional 2nd


=
2nd

>
3rd

<
4th

NOT
5th
(also used for NOT < (indicating greater than or equal to) and NOT =
AND
6th

OR
7th

procedural 6th


grouping
6th

(

6th
)

2nd
math operation 5th


simple
5th

+

3rd
-

2nd
*

5th
/

4th
% (mod)

6th
exponential / other
7th

power

2nd
log

3rd

The only interval without a choice is a 4th. There is no augmented 4th, a tritone is always interpreted as a diminished 5th.

Each number of half-steps is interpreted as a unique interval -- so that there are no enharmonic intervals that may lead to ambigous commands. If an expression requires a 4th, only the Perfect 4th can be used, not an augmented 4th (tritone), which is considered a Diminished 5th in Velato. If a 3rd is required, either the Minor 3rd or Major 3rd can be used.

This is the interval list used by Velato:
2nd Minor 2nd 1 half-step
2ndMajor 2nd 2 half-steps
3rdMinor 3rd 3 half-steps
3rdMajor 3rd 4 half-steps
4thPerfect 4th 5 half-steps
5thDiminished 5th 6 half-steps
5thPerfect 5th 7 half-steps
6thMinor 6th 8 half-steps
6thMajor 6th 9 half-steps
7thMinor 7th 10 half-steps
7thMajor 7th 11 half-steps


Types:

When a type needs to indicated (such as in a variable declaration), this table shows how they are indicated:
type note
int 2nd
char 3rd
double 4th



Numbers:

Individual digits in a number are determined by half-steps from the command root, excluding the Perfect 5th.

In C, these are the numbers tied to each note:
c# d d# e f f# g g# a a# b
0 1 2 3 4 5 - 6 7 8 9


Characters:

All characters are entered by their ASCII int. You can find a table of ASCII values here.

That's pretty much it. There are a few commands/expressions not yet implemented in Velato -- when they become available, I'll add them to this post.

The next post will be a walk-through of how to write programs in Velato.

Labels: ,

Introduction to Velato

Velato is a programming language which uses MIDI files as source code. Commands are determined by the intervals between notes.

Download Velato compiler for Windows.

Velato commands

All commands in Velato are expressed strictly by the pitch and order of notes. With the exception of variable names (more on this below), only the interval between notes is relevant, rather than the pitch itself.

The range of pitches is the alphabet in which Velato commands are written. This means that time signature, key signature, measures, rests, repeat marks, even note durations, are ignored by the code. If two notes are played as a chord, with no delay between the sounding of the notes, the one which appears first in the MIDI file is interpreted first, as if they had not been played simultaneously.

The commands and expressions themselves are determined by intervals from a command root note, which is the first note of the song. Therefore, a valid Velato program in one key can be translated to any other key, with no effect on the program. To allow versatility in Velato composition, the key can also be changed between any two commands within the song (using the "change command root" command). This allows the programmer to choose a starting pitch that better fits the flow of the song.

Also, additional tracks can be added to the MIDI file, which will be ignored by the compiler. This can allow any Velato program to be accompanied, without affecting the program.

For example: "C A G E D D", in the key of C, prints the variable D to the screen. In the key of G, the same command would be "G E D B A D". The actual definition of the print command are the set of intervals: Root (in the first case C), Major 6th (from root), Perfect 5th. The remaining three notes determine that it's variable D to print to the screen. Note that we did not transpose the final D, which is the name of the variable. For commands and expressions (except variables), octave is ignored, so an A in any octave has the same meaning. Also, notes are determined by pitch, not the actual written note, so G# and Ab are equivalent.

As mentioned above, variables are an exception. They are specific to octave and are not determined by interval; so command root changes do not affect them. This allows the program to have as many variables as there are notes allowed in the MIDI specification. This also makes programs less confusing to follow (having a different pitch for the same variable throughout a song would be confusing).


Commands
  • Commands are made up of a series of notes.

  • Commands can be of any length. All commands start with the Command Root.

  • Intervals of the notes, following the command root, determine the command.

  • Octave is ignored for commands (as is duration). So if a minor third from A is required, a C in any octave can be sounded.

The Command Root Note
  • The command root note is not necessarily the root of the current key (or root of a chord).

  • The command root note is defined by: the first note of the song, to begin with. Then, whenever the command is played twice in a row, the following note is the new command root.
Expressions
  • Any notes from the end of a command to the beginning of the next are interpreted as an expression.
Numbers
  • All numbers are assigned in base 10.

  • Numbers are relative to the command root, and are not specific to an octave (so if a D represents a 1, it will do so in every octave).

  • Command root is reserved for the end of the statement, and has no meaning in number assignment.

  • One fifth above command root is end of int, or decimal point of double (second time would be end of double).

  • All the other half steps from command root are digits of the number

  • The next half-step up is zero, and numbers increment with each half-step, up to 9. At that point, we hit the command root in the next octave.

  • For example:

    • if C is the command root, then the number sequence must end on a G (a perfect 5th up from the command root). Any G in the scale will suffice.

    • If this is a double, and we wish to use a decimal point, it is represented by the first G, while the second G completes the number.

    • Let's encode the number 458. Our command note is C, so four half-steps up is E. Five is F, and Seven is A. Then we finish on G to end the sequence.
Variables
  • Any note can be a variable as well as a command, determined only by syntax.

  • Variables can be assigned to any note.

  • Variables can only be called by a command that does not start with (have a command root note) the same note as the variable note.

  • So if the variable is assigned to Middle C, the command root note for the command calling it cannot be a C.

  • A variable can be re-declared, erasing the value and type of the variable it is replacing.
Statements
  • Statements in Velato always begin with the command root note, then a command, and then (in some cases) additional expressions.

  • If an expression starts with the command root note, it is interpreted as a command, and will be matched to the Command List below.
Functions
  • Functions are not yet implemented in Velato. They will work much like variables (in that they are represented by single notes, with no special meaning for interval or octave). They will be allowed to use the same "names" (pitches) as existing variables.
Other missing features
  • Arrays (including arrays of char for strings), and a ReadLine() special command. Also, right now there is no method for handling input. I'm hoping to address these, plus improve the error messages version 0.2.
The following blog post will list all Velato commands.

Labels: ,

Saturday, December 13, 2008

Photoshop Truncating Glitch

This is a tutorial on producing glitched images, by exploiting a bug in older versions of Photoshop.

PLEASE NOTE: I've only completed this successfully with Photoshop 6. Recent versions of Photoshop (like CS3, CS4) have been tested and do not have this "problem". If anyone tries this method with other versions of Photoshop, or other image editing programs, please let me know how it turned out, and I'll post updates here.
UPDATE: Only works in Photoshop 6 (and perhaps earlier versions). Thanks stAllio!, for testing version 7.

You'll also need a program to directly edit binary data. I use XVI32, which is freeware, and can be downloaded here.

Here's an overview of this glitch process. We'll go through each of these steps individually:

1) Truncate a JPEG.
2) Open the truncated file in Photoshop.
3) Save many copies of the truncated file. Photoshop will fill in the missing data with distorted versions of the image in the cache, creating the mosaic-like effect.
4) View the saved images, selecting the ones with the most interesting results.



So, let's go through each of these steps.

Step 1) First, select the JPEG you want to use. When selecting an image, keep in mind that only the top of the image (I usually use the top third to top half) will appear in the final image. Here is the file I'm starting with:



This is not the most exciting image in the world, so let's run it through the glitching process and see if we end up with something more interesting.



If you're using XVI32 to truncate the file, these are the steps:

∙ Open XVI32, and open the file (File / Open).

∙ Select Edit / Block <n> Chars. Choose an arbitrary amount, about 20% to 50% of the file (judge how much to use by which part of the image [from the top] you want to use). Keep in mind that 1kb is 1024 bytes. My example file was 2733k, which is equivalent to 2798592 bytes. I selected 1000000, which is ~27% of the file. It's best to experiment with this, try different values, until you come up with as much of the image as you'd like to use.



∙ With these bytes selected (the selected values will show in red), choose Edit / Clipboard / Copy



∙ Then create a new file with File / New

Edit / Clipboard / Paste (pasting these values into the new document)

File / Save As



∙ Provide a new file name, ending with .jpg extension.


Step 2) Next, open the truncated file in Photoshop. You'll get a warning: "The document may be damaged (the file may be truncated or incomplete). Continue?". Click OK.



You'll see an incomplete image. Most of the image (everything after where it was truncated) is black. However, if you move the window around, you can see Photoshop filling in the rest of the image.



Be aware that what you see on the screen is not how the file will actually look when you save it out. In fact, each time you save it, that missing part of the image will be filled with a random, mosaic-like distortion of whatever is sitting in the cache, different each time.


Step 3) Save the file. I suggest you save many copies before closing (I usually save at least 20). Save each as a JPEG. Hang onto the truncated copy of the image, so can re-open it and save out more copies, if you're not happy with the first set of images.


Step 4) Now reopen each one in Photoshop to see the results.

Here are several images produced from my truncated image:




Combining two images together

The example below shows another approach, effectively combining two images together. This is done by truncating one image, and combining it with a second, complete image. You'll open both images in Photoshop. In the example, I've truncated the cemetery image, and am leaving the gas pump complete. Click on the complete image, to make it the active window, then click on the truncated image and immediately save it out. Since the complete image (in this case, the gas pump) was the last image loaded before saving out the other file, it is in the cache. Effectively, I've combined the two images together:



+

=



And that's it. For those who experiment with this technique, or find ways to take it further, let me know how it turns out.

Labels: , ,

Wednesday, November 19, 2008

Houses on Fire

Click the button below the image to generate another distribution of houses, some of which are on fire.

Thursday, November 08, 2007

When calling .NET code from COM, how is the proper version of the .NET Framework determined?

The answer? Often it isn't! However, there's a way to force it to load the version you want.

Had a very annoying problem with VBA code (running in Excel) trying to load a .NET assembly (via a COM reference to a type library) and failing. It was a .NET 2.0 assembly. The strange thing was: on some machines it would load properly, while on others it would give the generic "xxxxxx or one of its dependencies could not be found" error at runtime.

To fix the problem, I went to one of the machines where I was getting the error, and broke out the under-appreciated Assembly Binding Log Viewer (a.k.a. fuslogvw -- it's installed with Visual Studio). This tool tracks which assemblies are loaded, and who the caller of each is; it's great for resolving bad references.

A few things to note about using fuslogvw:

  1. You're best off setting a custom log path -- the default path will not work on most machines -- and it will not tell you that it failed, the log will simply be empty.
  2. Set it to log all binds to disk, including successes, for the full picture of what's being loaded.
  3. When you're done, disable the log so it won't slow down assembly binding when you don't need it.

I set fuslogvw to log and ran my test VBA code in Excel. Then I refreshed the log and saw the assembly binding failure. The first few lines of output gave the whole story:


*** Assembly Binder Log Entry (11/7/2007 @ 11:24:07 AM) ***

The operation failed.
Bind result: hr = 0x80131107. No description available.

Assembly manager loaded from: C:\WINNT\Microsoft.NET\Framework\v1.1.4322\fusion.dll
Running under executable C:\Program Files\Microsoft Office\Office\EXCEL.EXE
--- A detailed error log follows.

The assembly manager for the 1.1 version of .NET was used. It attempted to load a 2.0 assembly, and failed.

I found very little on the web to address this (which is why I decided to post this). The fix is to set an Environment Variable for the default assembly manager to load: COMPLUS_Version, which should be set to the version of the .NET Framework you want: in this case v2.0.50727. Of course, Environment Variables can be set via the registry at: HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment .

When making these changes, just be sure it doesn't break other apps that use COM Interop. :)

More info: Basic info on how the runtime locates assemblies here.

Labels: ,

Tuesday, July 25, 2006

A short poem by me and cabbagemoth

Anyone want ice cream?
I like ice cream

My favorite flavor is wicker
My second favorite flavor is dog
My third favorite flavor is boron

My favorite topping is shredded credit card applications
My second favorite topping is good old sand

I like food that is yellow or purple
I name all my food "William"
I think if all food ate other food, they would mostly eat
peanut butter
I like bananas, but not grapes. Grapes are assholes

Anyone want ice cream?

Labels: , ,