Instrument Patches Demystified

From Uzebox Wiki
Jump to: navigation, search

Instrument Patches Demystified

Imagine if you will, your favorite metal song. Now imagine that played on a harpsichord, with a tuba bass line, and a rowdy percussion set consisting of various sized tin cans backed up with double bass drum action via a set of milk cartons. Even if all the notes are perfect, it doesn't sound right. If you do happen to enjoy the pursuit of excellence in milk carton drumming then it is probably you that are not right...it's fine, but that will have to be covered in another larger and sadder tutorial.


Foundational Knowledge

If Uzebox sound looks scary, please make sure you have read all of the following to get the most out of this tutorial. If you have a reasonable understanding of how the sound is generated skip to the next section as this may be painfully basic to some.

[1] [2] [3] Patch Commands Defined

The Uzebox sound engine is essentially a wave table synthesizer, which is a system of generating sound using very minimal storage space and processing power. A wide variety of sounds can be reproduced, and the trick is to use the right techniques to get the sound you want.

We are going to start at the most essential part of Uzebox sounds, the wave. This is the basic part of your sound, and we will look at the default wave 0 in the Uzebox kernel;a pure sine wave.

Ipd sine.png

Here we can see by the bottom scale that this sine wave is 256(8 bits)samples long, which means there are 256 values that represent an amplitude or loudness for each 1/256 fractional time period. If you were to listen to a looping sine wave like this you will end up hearing a very pure and smooth but ultimately not very musical sound. Check out [4] to hear a sine wave that sweeps across the entire human hearing range of frequencies.


There are other basic wave forms too, lets see how they compare against our sine wave.

Wavecomparison.png


Ok back to our sine wave. When we make music, the sound is changing often at very fast rates. These notes have different frequencies each having a distinct sound. Frequency is the amount of time it takes to run through the entire sine wave to the point that it repeats, that is, a sound that runs that wave in 1/100 of a second will be a much lower frequency than one that does it in 1/15000 of a second. Since our patch is based on this 256 sample wave, how are we making higher frequency waves out of the same wave? Instead of simply outputting each of the 256 bytes one by one in a row, we skip some to get through the wave faster. The more we skip, the faster we get back to repeating the wave, and the higher the frequency will be. We are basically making our sine wave have a shorter length. The following image shows this visually where red pixels indicate data that was sampled and green data that was skipped over

  • NEED IMAGE*

Now that we can control the frequency of the sine wave, we should be able to make any sound in the world out of it right? Since we can only use 1 sine wave per instrument, we will pretend that [5] does not exist because it is not practical on Uzebox. So the answer is simply no, not even close. Lets look at a the (simplified for clarity)wave form of a couple real world instruments.

Ipd realinstruments.png

As you can see, there is a lot more happening there than our sine wave has. The timing and amplitude of those fluctuations is what causes the instrument to have it's unique tonal qualities. If we played the trumpet wave through the Uzebox we would of course hear something that sounds similar to a trumpet. So how can we possibly make our sine wave look like that? Changing the frequency is not going to give us those fluctuations in wave shape that we need. The current sound engine only allows us to change the frequency, but the waveform is static. If this ever changes it will be covered in another section, but basically the only way is to have a waveform that is already similar to a trumpet. Lets figure out how we can do just that.

Making Waves

Pushing The Envelope

Now we have a wave that sounds similar to the instrument we are trying to make. This does not mean that our patch will sound like an instrument. Real instruments have several stages of sound, and certainly do not simply start and end with a monotone loop through our wave. In synthesizers like the Uzebox sound engine, we use something called an envelope to sound more like a real instrument. There are 4 basic parts that make up our envelope:

  • Attack time is the time taken for initial run-up of level from nil to peak, beginning when the patch is first started.
  • Decay time is the time taken for the subsequent run down from the attack level to the designated sustain level.
  • Sustain level is the level during the main sequence of the sound's duration, until the note is released.
  • Release time is the time taken for the level to decay from the sustain level to zero after the key is released.

If you would like further information on the ADSR envelope, please read [6]

So all we really need to figure out is how to generate the envelop we want with the kernels patch commands. Lets look at a generic instrument patch.

  • 0,PC_WAVE,1,
  • 0,PC_ENV_VOL,96,//start our attack at volume 96, we could also omit this and let the note volume from the midi handle it.
  • 0,PC_ENV_SPEED,-8,//after the attack, we have decay where the volume will drop for a while, before we reach the sustain level.
  • 3,PC_ENV_SPEED,0,//now we want to stop the volume decrease because we are at the sustain level.
  • 0,PC_NOTE_HOLD,0,//we stop any of the following patch commands until the note is released in the midi to sustain the note.
  • 0,PC_ENV_SPEED,-12,//set the speed that the patch will fade out at. The release time gets shorter the faster the volume drops.
  • 8,PC_NOTE_CUT,0,//let the volume lower at -12 per frame for 8 frames making the volume 0 and then end patch.
  • 0,PC_PATCH_END

You can see that it is fairly easy to do once you understand the concept. We have the ability to set volume to a static level, or also set it to increase or decrease at a constant value per frame. This is all we need to make an envelope. It will take some experimentation but you should be able to dial this in pretty quickly once you get the feel for it. If you REALLY wanted to make an excellent patch you could look at the waveform of the real instrument playing a note, and make a separate wave for each part of the envelope by putting the appropriate PC_WAVE value before each section. This would be a lot of work but currently is the best possible quality I can think of for ultimate sound.


All In The Details

I find that you can get pretty good sounding instruments without too much effort, depending on the song. But it is also one of those enjoyable things in life, where small details can make a large difference to improve the outcome. Briefly I will go over some tricks I have found useful in getting more complex sounds.

The primary "trick" I will mention is using PC_TREMOLO_RATE and PC_TREMOLO_LEVEL frequently. If you experiment quickly with this and enter random values, it might at first seem like tremolo is of no use and just makes things sound weird; for some songs you might want a simpler sound after all. But by using the appropriate tremolo frequency and intensity, you can modify the base waveform into something more complex. Essentially the kernel will modulate the current wave selected by PC_WAVE according to kernel wave 0(pure sine wave). It depends highly on what you are after. Here is an example from the game [Columns]

//Lead UNTIL solo
const char patch04[] PROGMEM ={ 
0,PC_TREMOLO_LEVEL,170,     
0,PC_TREMOLO_RATE,180, 
0,PC_WAVE,4,
0,PC_ENV_VOL,96,
0,PC_ENV_SPEED,16,
1,PC_NOTE_HOLD,0,
0,PC_ENV_SPEED,-8,
8,PC_NOTE_CUT,0,
0,PATCH_END
};
..
const char patch07[] PROGMEM ={//SOLO PATCH
0,PC_TREMOLO_LEVEL,170,     
0,PC_TREMOLO_RATE,180, 
0,PC_WAVE,4,
0,PC_ENV_VOL,98,
0,PC_ENV_SPEED,16,
1,PC_NOTE_HOLD,0,
0,PC_ENV_SPEED,-8,
8,PC_NOTE_CUT,0,
0,PATCH_END
};


Here I experimented and found that I wanted that "warble" sound to make the lead instrument more pronounced. Experimenting with different values should give you a good understanding of it. I would expect to recompile 5-10 times to fine tune this..but getting just the right sound is what it is all about. Another example of what I think is a very versatile bass guitar sound, which gained much more "character" with tremolo:

//bass instrument - title melody
const char patch08[] PROGMEM = {
0,	PC_WAVE,			4,
0,	PC_TREMOLO_RATE,	222,
0,	PC_TREMOLO_LEVEL,	128,
0,	PC_ENV_VOL,		33,
4,	PC_ENV_SPEED,		-1,
2,	PC_ENV_SPEED,		-2,
0,	PC_WAVE,			8,
14,	PATCH_END,			0,
};

An even more advanced case comes to light when you have a song where 2 separate channels play the same notes to provide more depth. Here, through a lot of experiment, you can devise different tremolo rates for each one that cause desired and predictable "interference" with each other(the different speed of traversals, up and down volume, through kernel wave 0). This can do neat things like introduce beat frequencies at key moments in the song. This is all experimentation, but if you like the art side of things you will probably find you can do some subtle but interesting things here. There really is no one perfect thing here, but all these details can add up to a more interesting instrument.

As a passing note, you might think there are instruments you want no tremolo at all. Think again!! You need not take my advice, but I would implore you to try very subtle and low frequency tremolo to give the ever slight "imperfection" to the sounds and make them seem more natural. To my ear, a more instruments than not are improved with something as simple as this:

//bass instrument - gameover melody
const char patch07[] PROGMEM = {
0,	PC_WAVE,		8,
0,	PC_TREMOLO_RATE,	1,
0,	PC_TREMOLO_LEVEL,	64,
0,	PC_ENV_VOL,	52,
25,	PC_ENV_SPEED,	-1,
10,	PATCH_END,		0,
};

More Than One Way To Skin A Cat

I want to make it very clear that I do not necessarily promote the skinning of any feline, though if necessitated by hunger then I guess it is moral..ok.


I have made a lot of Uzebox song conversions, and a few originals over the years; probably over 100 completed if you can believe it. In more recent times I discovered something that I initially thought was simply invalid. This is because just a quick experiment or two will usually end up with a very bad sounding instrument so one moves on and forgets the curiosity. There are lots of combinations that sound terrible, and a few that sound good.


What I am talking about here, is using more than 1 PC_WAVE command in an instrument patch. Now, this can elevate your patches to a much higher level because like real instruments that have a complex wave form that varies after the initial attack, so too can your patches. You are not stuck to 1 monotone waveform for the entire envelope. You can for example, emulate a wood wind instrument that has a harsh initial attach followed by a hollow echo like tone as it fades;you simply cannot do this otherwise, as you pick one wave for the whole thing.


It however can be quite hard to get all things lined up for this to work. Because you will be playing 1 wave form, then at a certain point abruptly transition into a different wave form, there can be noticeable pops or clicks that sound like percussion(which could be used as a feature in some cases). This highly depends what wave you start with and what you are going to. I especially find the results moving from PC_WAVE,4 to PC_WAVE,8 or vice versa to fit a lot of situations:

Let's look at an example:

//bass instrument - title melody
const char patch08[] PROGMEM = {
0,	PC_WAVE,			4,
0,	PC_TREMOLO_RATE,	222,
0,	PC_TREMOLO_LEVEL,	128,
0,	PC_ENV_VOL,		33,
4,	PC_ENV_SPEED,		-1,
2,	PC_ENV_SPEED,		-2,
0,	PC_WAVE,			8,
14,	PATCH_END,			0,
};
//lead instrument - title melody
const char patch09[] PROGMEM = {
0,	PC_WAVE,			4,
0,	PC_TREMOLO_RATE,	222,
0,	PC_TREMOLO_LEVEL,	128,
0,	PC_ENV_VOL,		28,
4,	PC_ENV_SPEED,		-2,
0,	PC_WAVE,			8,
14,	PATCH_END,			0,
};

Other combinations can also work, it really depends on what your starting volume is, the speed of decay, timing before the change, what notes will be played in the song, and often hiding the transition with tremolo. You can understand then when you have all the different timing, envelope, wave, and tremolo options available that the combinations are endless and it is basically an art form. If you had a bunch of working instruments and thought you had it all figured out, you could always implement PC_SLIDE into your patches. If you are at that point, I don't think you need any further tutorial from me ;)