Articles Archive
Articles Search
Director Wiki
 

Pitching an Idea

April 4, 2000
by Colin Holgate

Do you wish you could play sounds at a different pitch?

One of the behind the scenes things that happens with each Director release is that some structure is put into place for future features. Sometimes one of those future features will already be in place, but not fully tested, and therefore not supported or bragged about.

In Director 7 we had getPixel and setPixel, which were two useful sounding functions. I don't know how the information about them escaped from Townsend Street, but many people played with the feature, some even did useful things with them. This showed Macromedia that it was obviously an area that developers would like to see expanded. With Director 8, we now have Imaging Lingo, which goes a lot further than just making getPixel and setPixel officially supported functions.

So, what's in Director 8 that might hint at future expansion in Director 9? Well, there's this wonderful sound queue property called #rateshift. This time I do know how the information escaped from Townsend Street, but I'm not telling! I will tell you how to use it though.

The movie that accompanies this article is more documented than anything I've ever done before. There are probably more comments in there than in all my previous programming put together, so I'm not going to explain in detail how things are done, just go through the scripts and try to follow what I say there.

D8 download for Mac (2 MB) or Windows (1.9 MB).

This sample uses three Director 8 features, a multiple curve vector, sound pan, and the undocumented #rateshift property. I'll talk a little about each one.

Multiple Curve Vectors

On their own, Vector members are very useful. They can often fill the need when you would otherwise have to use a jaggy Shape member, or a Flash member just to get an anti-aliased curve on the screen. You can now use alpha channels with bitmaps, but they can be slow to manipulate, and don't scale quite like a vector graphic does.

As soon as people had the ability to draw vector graphics, they started to complain! The usual complaint was that to do something complex on the screen, you would need to take up a lot of sprite channels. With Director 8's multiple curve vectors, you can do quite complex things in one channel. Here's a movie I made that rotates a bunch of straight lines, where each line is a separate curve in one vector member, and therefore only takes up one sprite channel:

For the #rateshift example movie, I used a single vector to create the entire keyboard. The normal way to make a multiple curve vector would be to use the Vector window, and to draw as many separate curves as you need. The piano keyboard I made has 75 curves in it, and they are precisely placed. It would have been tedious to make it in the Vector window! Instead of spending hours in the Vector window, I built up a vertexlist for the vector, by working out the coordinates for each key. I've left the routine that I used in the example movie, you can look through the script to see how the calculations are done.

Making a multiple curve vector using Lingo is fairly easy, you just create a vertexlist that includes a #newcurve each time you want to start a new curve. Here's the start of the vertexlist for the piano keyboard:

[[#vertex: point(0, 0)], [#vertex: point(324, 0)], [#newCurve], [#vertex: point(324, 40)], [#vertex: point(0, 40)], [#newCurve], [#vertex: point(0, 0)], [#vertex: point(0, 40)], [#newCurve], [#vertex: point(9, 0)], [#vertex: point(9, 40)], [#newCurve]…etc]

Playing with Pan

You'll notice that I tend to use Director 6 syntax a lot. That's because I like it, it's more readable than dot syntax, and I can often use the same routines in my Director 6.5 work. It's possible to use Pan with Director 6 syntax, you just set the pan of the sound:

on exitframe
  
  set the pan of sound 1 to float(the mouseh - 320)/3
  go the frame
  
end

If you had a looped sound in channel 1, it would pan left and right, following the position of the mouse on the screen. With the above settings, it would be fully left or right at the edges of a 640 wide stage.

Scaling the pan range is important, you don't always want to make it hard left or hard right when the sound source is near the edges of the stage. In my piano example, I set the range to be -30 to +30. As the width of the keyboard on the screen is 326 pixel, that would pan the sound as if you were looking at the movie on a large screen monitor. That's what I wanted to make it seem like, so that the sound of the notes seem to come from the direction of the key that was struck.

Let's Pitch in

The unsupported property, #rateshift, can only be set up as part of a sound queue. Sound queues can be a bit intimidating at first. If you are familiar with property lists, it's a little less daunting. For what we're looking at here, the queue is about as simple as it gets:

sound(1).queue([#member:member("sound"),#rateshift:0])
sound(1).play()

The first line sets up sound channel 1 to play sound member "sound" at a #rateshift of 0. The second line sets it playing.

#rateshift is an integer that represents the number of semitones that you want to shift the sound. It's geared towards conventional music scales, and isn't easy to use for pitch shifting to any degree. Let's say that the original sound was a middle C piano note. This would play it back as the G above middle C:

sound(1).queue([#member:member("pianoC"),#rateshift:7])
sound(1).play()

because G is seven semitones up from C. This would play the E sharp below middle C:

sound(1).queue([#member:member("pianoC"),#rateshift:-7])
sound(1).play()

because E sharp is seven semitones below C.

Musicians everywhere are in shock as they read this! Not because it's a fabulous feature, but because they know that there isn't an E sharp, it's better known as F. I just wanted to make sure they were paying attention.

I think we should split now

One of the reasons that pitch shifting has been a long time coming is that some people think that pitch shifting means changing the pitch, but keeping the duration the same, and that's a little hard to do cleanly in real time. Other people think that it's changing the pitch and therefore the duration, but are worried that most sounds would sound strange if pitched too far from the original frequency. Both views are right, but it's easy to work around the second problem. You do that by making a keyboard split.

This isn't where you upset a piano until it feels obliged to leave, it's where you take a number of sound samples and then play the one that is closest in pitch to the key on the keyboard that you have hit. My example movie does this, with two different splits. The one that it starts with is for a set of piano samples. If you slowly go up the keyboard, you'll easily tell where the joins are, but if you just play away, you may not notice what's going on. The end result is that the sound is more realistic, because the sounds are only being altered by about half an octave. Just using one sound for the whole keyboard would not sound as convincing.

The movie also has a split for guitar samples. To go from one to another, press the letter P or G. You can also toggle between having to click to hear a note, and just having to point to hear the notes. To do that, press the space bar.

How fast can it be?

The keyboard example I made didn't take very long to put together. It also didn't really answer how fast could sounds be shifted. Would it be fast enough to play music? A lot of research later, I made a movie that could take MIDI files and play them. Here's how some fast consecutive notes can sound:

http://staff.funnygarbage.com/colin/midifast.dcr

What next?

My hope is that there will be a lot of interest in the new sound Lingo, and in #rateshift in particular. If that does happen, maybe Director 9 will have a whole bunch of Sonic Lingo commands and functions!

Copyright 1997-2017, Director Online. Article content copyright by respective authors.