conceptual inertia

mediocrity at its finest

patch 3

without comments

All right, time to get back at it. I need to tie up a loose end and finish playing with objects found in the Tutorial Zero Video. – specifically, the (pseudo) random object and counter object. I love random. It’s one of the first functions you use when learning to program. Here’s the trivial patch:

randompatch

The right inlet specifies the range, in this example random numbers will be generated from 0-9.

You can also feed it a seed value, in which case you’ll be able to reproduce the “random” output.

randomseed

With a seed of 42, you’ll get the following output: 1, 2, 9, 1, 2, 4, …

Now, the counter object. Have a look at the help file for this object:

counterhelp

It may look a little complex but play around with it, read the comments, and before long, it’s understandable. The function of the counter object is simple, but the I/O makes its usage flexible.

One thing I noticed, these message objects have no connectors!

messageobjs

Hmm…what happens if I drop into Edit mode:

countereditmode

The connectors are definitely there, messing up the joint. That’s a handy cleanup feature, now how do I turn it on in my patches? After a little hunting, I discovered that, once you select a connector, you can go to the Object menu and “Hide on Lock”.

objectmenu

And the seed connector is now hidden:

hiddenconnector

Here’s another discovery, if you’re on a reference page and you click the “Contents” button at the bottom, it displays this monster menu:

referencecontents

Which could prove useful for systematically going through the entire reference docs. However, you can’t open the above window from the home page, you have to be on a reference page, otherwise, it just displays:

homepagecontents

That’s one way to get to the reference pages, but what about the .maxhelp files? How can I see a list of all the .maxhelp object files? You can find them in the following directories:

  • Max5/Cycling ’74/max-help
  • Max5/Cycling ’74/msp-help

Great. Maybe I’ll painstakingly read each and every one in alphabetical order after I finish the tutorials. Why on earth would you do such a thing? As G.I. Joe says, “Knowing is half the battle.” Eventually, after I begin building patches in earnest, knowing of an object’s existence is…half the battle!

Spent the rest of the day surfing the Cycling ’74 forum (about 7 months worth of postings) and watching youtube vids on max/msp. I probably spent one to many hours browsing the forum but I did pick up a few tidbits of info. For example, the ability to cut ‘n paste a patch as text. Simply copy the patch text from the forum post and inside max select File->New From Clipboard. Yay!

As for youtube vids, I found these the most interesting:

Well, it’s about time to digg into the tutorials after poking around haphazardly. I’ll be back when I finish them. Later!

Written by admin

January 3rd, 2009 at 9:44 pm

Posted in max/msp

patch 2

without comments

Now what? Time for some coffee…as I mull over my next direction. My ultimate plan is to read every ounce of documentation. However, before I delve too heavily into the docs, I want to see what online resources are available online at Cycling ’74.

I checked out every link on the interesting work page, but if you really want to get a sense of the max/msp community at large and what’s possible check out the C74 Perspectives channel on youtube.

I’ll definitely want to come back and read these articles and interviews, once I have a deeper understanding of max/msp itself. For now, I think I’ll check out some more videos before returning to the help docs. It’s a chance to discover what’s new in Max 5, although I don’t even know what’s old! Of course, I’m going to continue documenting my trivial discoveries because it’s fun and keeps me motivated.

patching and workflow

Right off the bat, keyboard shortcuts. “Type n and get an object box at the current cursor position, m for message box, and so on.”. Trying out the “and so on” part:

  • b for button
  • c for comment
  • f for flonum
  • i for number
  • t for toggle button

There’s a Presentation mode to which you can add objects:

addtopresentation

Here, I’ve added 3 objects to presentation mode:

metrowithpresentation

The object’s size or location in Presentation mode doesn’t have to correspond to its size or position in Edit mode:

metropresentation

debugging

I’m interested to see what kind of debugging capabilities max/msp has. I don’t imagine we’ll be stepping thru lines of code, but something more robust than console output would be great.

First, simple error messaging. Trying to send a “foo” string to a number input results in an error – which is correct. And our initial suspicion of the Max window being a console output is verified.

fooerrormsg

Wow. Max/msp supports watches and breakpoints, what a nice surprise. Now, let’s see if we can get a demo of watchpoints up and running. The first thing, would be to bring up the watchpoints window…

debugmenu1

watchpointwindow

But what to do isn’t clear to me yet. Time to drop into the help docs and do a search for “watchpoints”, which turns up this promising looking result:

watchpointssearch

So, a watchpoint monitors messages being passed thru patch cords. In that case, lets attach a slider to a number and then a watch var between them.

addingwatchpoint

The newly added watchpoint:

watchpoint1

While running the patch, you can see the value traced to the window:

watcher2

I’ll cover signal probes, and breakpoints later on. I’m not ready to utilize all the debugging facilities just yet, but knowing of their existence is half the battle.

integrated documentation

Ah…integrated docs, probably the number 1 reason I chose to pickup max 5. It looks as if the integrated help system has even more functionality, starting with the Clue window.

windowmenu

You know, before we get into the Clue window, one of the things I hate about Mac is the mess of floating windows.

windowmess

Flash CS3 has a great panel docking/flyout mechanism. I wish max/msp had something similar. Imagine it, a toolbar of objects on the left side, with zoom and pan (hand icon) tools. A maximized patcher surface, where multiple patch windows appear in tabs across the top. On the right and bottom sides, docked panels for the max window, clue window, etc.

And while I’m thinking about UI, I’ve got to say, the single worse UI design choice in max is the placement of the forward/back buttons for the help docs. Every single browser has these buttons located at the top left – it’s called spatial memory people! I always find myself instinctively moving the mouse up and to the left, before I remember, damn…it’s at the friggin bottom. </rant>

Back to the Clue window. Hovering your mouse over the item in question reveals only a title.

bufferclue1

Only when drop into edit the object text, does a description appear.

bufferclue2

I’m not sure if this was intended or is a bug. Either way, the Clue window doesn’t appear to be useful, we’ll see.

Clicking on the left inlet of an object reveals a reference menu. Below, I’ve clicked on the left inlet of a Number object:

inletclick

The listing of attributes, messages, and actions is quite nice. Clicking on the top-most attribute bgcolor inserts a message object and connects it to the number’s inlet.

bgcolor1

I replace the args with a red color and test it out.

bgcolor2

The quick ref panel might be handy.

The last thing to note is given a selected object, it will then appear in the Help menu.

helponselected

Until next time!

Written by admin

January 3rd, 2009 at 9:42 pm

Posted in max/msp

patch 1

without comments

As my exploration of max/msp continues, I think I’ll simply increment the patch count in the post title.

Last time, I had this <sarcasm>awesome</sarcasm> patch:

maxmetroslider1

Now, what I’d like to do is change the range of the slider from its default 0-127. Option click the slider and the .maxhelp has an example.

maxsliderhelp

Now I’m wondering what type of object the “size $1″ button is. So, lets quickly drop into Edit mode and Option click it and quickly jump back out, so as not to disturb things. If you do mess things up, not to worry, it’ll prompt you to save the changes to which you should obviously say no.

Ok, so “size $1″ button is actually a Message object. So, ‘size’ is the message and $1 is a placeholder for an argument, received from the number box. I have a feeling the Message object is going to be quite common and very useful. If you open up the Slider reference doc and scroll down a bit, you can see that ‘size’ is an attribute of the Slider object with a well written description. Size is a float to indicate the number of steps (range) and the default value is 128 or 0-127.

metro1

Even with such a trivial patch, I noticed a couple of UI usability issues. First, when I toggled the bang, the button didn’t flicker because the slider was set to 0. Second, if I want the range 0-500, I have to remember to set the Number box to 501. I wonder if it’s possible to add a +1 object…

plusone

Nice, you can have objects that do basic arithmetic. Another problem is preventing users from selecting a negative number. How do I do that? Wait a minute…the Number box in the Slider .maxhelp has a 30-90 range. How did they do that?If you drop into Edit mode and mouse over the left hand side of the object, a little “i” icon appears.

inspectoricon

Clicking it opens the following window, where the ‘Value’ tab reveals what we’re looking for! Is it me or is this UI fairly intuitive?

numberinspector

I guess the “i” stands for Inspector. I also discovered you can open this window by using a keyboard shortcut (Command-I) or right clicking on the object.

My original goal was to change the slider range and the objects above the slider accomplish that goal in an indirect, clunky way. However, now that I’m aware of the Inspector, I can now simplify things by delete the objects and setting the range directly. I would like the range to go from 250 to 1000 ms.

sliderrange

The ‘Output Minimum’ is 250 and the ‘Range’ is 751. Remember, range indicates the number of steps inclusive. For example, a minimum of 0 with 4 steps would give you what range?

Finally, the patch I initially had in mind:

slidermetropatch

I wonder if I could hook this up to a MIDI slider on my controller? Woah.

First, I’ll need to install the latest M-audio drivers for my midi interface and then configure it using the ‘Audio MIDI Setup’ util that comes with OS X, which is kind of like a patcher window itself:

audiomidisetup

A good post about the ‘Audio MIDI Setup’ util can be found here. As you can see, I’ve added a device for my Radium 49 midi controller. This is optional, but allows  programs to display the controller as “Radium 49″ instead of “MIDISPORT 8×8/s Port 1″.

Back to max/msp. Now, I imagine the first thing I would need to do is configure MIDI.

midisetupmenu

And would you look at that…everything looks to be in order already!

midisetupwindow

And now, if I just start typing “midi” in a new object…

midiin

Intellisense is awesome.

Hmm…the sliders move during testing, but they’re acting a little crazy, why? It’s almost as if their range is very small within the 751 units available. Oh yeah, it’s MIDI…duh. 7 out of 8 bits are used for payload, and 2^7 = 128 or 0-127. If you don’t believe me, type 2^7 into Google. So, I need to revert the range settings to the sliders default values:

sliderangealtered

And voila! The patch works nicely.

midimetro

That was ridiculously easy. Glancing at the midiin object help docs, I can see there’s a lot more to learn and I’ll certainly revisit it. For now, I’m still in the exploration stage – it’s about pushing buttons and trying things out, without fear, to see what happens.

Until next time!

Written by admin

January 3rd, 2009 at 2:36 pm

Posted in max/msp

patch 0

without comments

Purchased a copy of Max/MSP today over at Cycling ’74. I decided to go with version 5′s new hotness over Pd. User interface does matter. Documentation, tutorials, and a slick integrated help system are even more important.

After installation, it took under 5 minutes before I was creating and experimenting with my first patch. Here’s how it went down.

The first thing I did was open the help file.

maxhelpmenu

And prominently displayed in the upper right corner is a listing of tutorials…

maxhelptuts

The documentation is also available online, so you can view the above page here.

I think Max/MSP – when loaded the first time – should display the help documentation or better yet, a window to play the Tutorial Zero Video. Instead, they simply show the Max window, which could be a little disconcerting for first time users.

maxwindow

The Tutorial Zero Video is short and sweet. I only watched a portion of it before I was playing around with the button and metronome objects. Behold! The “Hello Metro” patch in all it’s glory!

maxhellometro

I love it; because I have an appreciation for the amount of work it would take to code something similar.

Now, depending on your preference, you may want to toggle on ‘Segmented Patch Cords’ from the Options menu.

maxoptionsmenu

Which means the difference between these two layouts. The second one (with segmented patch cords) looks more organized but can be time consuming.

maxsegmentedcords

Or you could do this, to give it that printed circuit board look…

maxalternativesegmentstyle

Or this awesomeness…

maxmetroman

The Zoom tool is a little awkward at first.

maxzoomtool

I guess I was hoping for a Zoom tool similar to the one found in Adobe products – where you also hold down the space bar to pan around.

Enabling grid snapping at the bottom of the window is handy.

maxenablesnap

As are Align commands in the Arrange menu.

maxarrangemenu

Ok, enough of that, back to the patch. When hovering over an inlet/outlet, a tooltip appears. This is the first stage of help integration.

maxtooltips

Even better is Alt or Option clicking an object (ie. the metro object). This launches a window that displays a .maxhelp file for the object – the second stage of help integration. What’s really cool about this window is that it contains working patches that you can play with.

maxmetrohelp

It’s too bad you can’t Option click the patcher items even further…wait a minute. Maybe you can’t Option click items because the patch is running. I wonder what happens when you drop into Edit mode…

maxmetrohelpedit

Aha! I discovered your magic, it’s just another patcher window. (Yeah, I’m a little slow sometimes.) Well, I’m gonna lock that sucker back up because I don’t want to mess around editing the help files.

At the top right is a link to open a detailed reference manual – the third stage of help integration. You can view the reference for the metro object here. Awesome.

So, now I want to hook up a horizontal slider object to my metro object. Add a slider…

maxsliders1

Hmm…the slider is vertical by default. That number above the icon sure looks interesting. I wonder what would happen if I clicked it…

maxsliders2

Shaweet. Now I’ll quickly add a number box to view the output of the slider. The new patch looks like this…

maxmetroslider1

It appears the default range of the slider is 0-127, which is quite handy for MIDI.

Well, that’s all for now. Until next time!

Written by admin

January 2nd, 2009 at 10:49 pm

Posted in max/msp

jack

without comments

From time to time, Jack winces at the thought, “Jack of all trades, master of none.”

A love of learning keeps Jack motivated. A lot of shiny toys make it hard to hold Jack’s attention for long. Jack accrues skills over time, revisiting points of interest in an iterative fashion. Given enough time Jack should become a master in all fields, but time and progress wait for no man.

At times, the sheer amount of stuff to learn makes Jack depressed. During such times a little voice in the back of Jack’s mind whispers, “focus”. “Specialization is dangerous,” he argues, “look at the Panda bear! Look at the Cheetah! Specialization is great for short-term gains. Over the long-term, it’s detrimental.”  ”Yes”, whispers the voice, “but your life is half over. You will never be a success unless you focus on the one”. Jack resists, Jack is stubborn.

Eventually, Jack submits, “But what to focus on? How can I commit to just one thing? What if I choose to eat nothing but Bamboo and I’m faced with deforestation? What if I choose to run fast and prey can still outpace me?” The voice whispers back, “Jack of all trades, master of one.”

Written by admin

January 1st, 2009 at 7:00 pm

Posted in blather

C# finite state machine (fsm)

with one comment

Take a look at the following output:

The above output was generated by an Orc entity with an associated finite state machine (FSM). Although a FSM can be used for many things, in game development it’s typically used to model character behaviour. Why? It’s simple and easy to debug.

Let’s have a look at Main to get a high-level feel for using an Orc entity:


static void Main(string[] args)
{
    Orc o = new Orc();

    o.Event = OrcEvent.Wander;
    o.UpdateState();

    o.Event = OrcEvent.Eat;
    o.UpdateState();

    o.Event = null;
    o.UpdateState();

    Console.ReadLine();
}
 

In a real game loop the UpdateState method would be called once per frame. Continuing with a top-down approach, let’s see the components that make up an Orc entity. First, we find a enum to represent simple event identifiers.


enum OrcEvent
{
    Eat,
    Wander
}
 

Events can trigger a change in state. It’s possible to use a table to map events to associated states. For example, the OrcEvent.Eat maps to the EatState and the OrcEvent.Wander maps to the WanderState. However, states don’t always have a 1-to-1 correspondence. For example, an OrcEvent.SeeEnemy could map to an AttackState. Here we see a transition table specific to Orcs:


class OrcTransitionTable : Ai.StateTransitionTable
{
    public OrcTransitionTable()
    {
        base.table.Add(OrcEvent.Eat, new EatState());
        base.table.Add(OrcEvent.Wander, new OrcWanderState());
    }
}
 

The base type StateTransitionTable handles housekeeping chores for the table:


abstract public class StateTransitionTable
{
    protected Dictionary<object, IState> table = new Dictionary<object, IState>();

    public void SetState(object evt, IState state)
    {
        table.Add(evt, state);
    }

    public IState GetState(object evt)
    {
        Ai.IState i = null;

        try
        {
            i = table[evt];

        }
        catch (KeyNotFoundException)
        {
            return null;
        }

        return i;
    }
}

What exactly is IState? It’s an interface with 3 methods for state processing:


public interface IState
{
    void Enter(Entity e);
    void Execute(Entity e);
    void Exit(Entity e);
}
 

Each method takes an entity type as a parameter. When switching states, the Exit method is called for the current state. The new state’s Enter method is then called. The current state is then assigned the new state. Execute is called once per frame to perform state processing.


abstract public class Entity
{
    protected Ai.StateTransitionTable transitionTable = null;
    protected IState currentState = null;

    public void UpdateState()
    {
        if (currentState != null)
            currentState.Execute(this);
        else
            System.Diagnostics.Trace.WriteLine("zero state");
    }

    public object Event
    {
        set
        {
            if (value == null)
            {
                currentState.Exit(this);
                currentState = null;
                return;
            }

            IState i = transitionTable.GetState(value);

            if (i != null)
            {
                if (currentState != null)
                    currentState.Exit(this);

                currentState = i;
                currentState.Enter(this);
            }
        }
    }
}
 

Implementing an Orc entity is trivial:

  • Inherit from Ai.Entity
  • Set the transition table in the constructor
  • Start adding methods for the new character

class Orc : Ai.Entity
{
    static Orc()
    {
        transitionTable = new OrcTransitionTable();
    }

    public void Drool()
    {
        Console.WriteLine("drooling...");
    }
}
 

Of course, an entity will need a variety of states to transition to. To create a new state type implement the IState interface. For example, here are a few Orc-related states:


class EatState : Ai.IState
{
    public void Enter(Ai.Entity e)
    {
        Console.WriteLine("entering eat state");
    }

    public void Execute(Ai.Entity e)
    {
        Console.WriteLine("executing eat state");
    }

    public void Exit(Ai.Entity e)
    {
        Console.WriteLine("exiting eat state");
    }
}

class OrcWanderState : Ai.IState
{
    public void Enter(Ai.Entity e)
    {
        Console.WriteLine("entering wander state");
    }

    public virtual void Execute(Ai.Entity e)
    {
        Console.WriteLine("executing wander state");

        Orc o = e as Orc;

        if (o != null)
            o.Drool();
    }

    public void Exit(Ai.Entity e)
    {
        Console.WriteLine("exiting wander state");
    }
}

class CustomizedOrcWanderState : OrcWanderState
{
    public override void Execute(Ai.Entity e)
    {
        base.Execute(e);

        Console.WriteLine("unique orc personality here...");
    }
}
 

Those are the basics of implementing a finite state machine for character control. You can download the source code here.

Written by admin

January 13th, 2007 at 6:57 pm

Posted in code

game of life

without comments

Conway’s ‘Game of Life’ produces some interesting patterns from a few simple rules. This demo utilizes WPF with simple styling and animation.

One day I’ll have to learn how to record, edit, and post videos online. Until then, it’s nothing but a static screenshot for you:

You can download the source here.

Written by admin

January 13th, 2007 at 3:47 am

Posted in code

live drummers vs. drum machines

without comments

I hear the following statement from time to time: “Live drummers sound better than drum machines.” And I have to agree, a live drummer certainly has a feeling that isn’t easily replicated. However,  I also realize that machines will eventually outperform humans in every endeavour.

So why do live drummers currently sound better than drum machines? Is it because they’re slightly off-time? If this were true, I think a lot more people would sound like world-class drummers. Professional drummers spend countless hours training muscle memory for millisecond accuracy. Of course, nothing is perfect and professional drummers are, on occasion, slightly off. So, it wouldn’t hurt if drum machines were slightly off as well.  For example, one could using the following algorithm:

  • First, determine if a note should be slightly off-time by generating a random number between 0 and 1. If the variable is greater than a user-defined value (ie. 0.95) the note’s timing will be slightly off.
  • If the note’s timing is going to be slightly off, will it be pushed forward or back? Have another user-defined setting with three possible values:
    • Forward
    • Random
    • Back
  • How far will the note be pushed? Once again, a user-defined setting. This one defines an upper limit or the maximum distance that a note can be pushed off time without sounding bad. The sequencer will then choose a random distance between the upper bound and it’s original placement (where the user entered the note value in the first place).

I don’t think being off-time is highly desirable and has only a minor impact on imparting feel. I believe the real difference between live drummers and drum machines are frequency dynamics. For example, a number of things happen every time a live drummer taps a ride cymbal or hits a drum:

  • Change in velocity.
    • Most beginners enter all note values at 127. Only later do they discover the impact of accents and fluctuating velocities. However, adjusting velocities can be tedious work and few users take the time to really sculpt velocity nuances.
    • A drum machine could have a list of velocity templates or curves (one per pitch) that users could apply to the entire sequence. At the very least it’s a starting point for further refinement. Perhaps it’s even possible to:
      • offset a template or curve by entering a phase value, which results in a change of note accents
      • layer templates or curves and perform simple operations on them like intersection, addition, or subtraction.
    • Changes in volume are not enough. Each drum sound must be multisampled, so that a change in velocity results in a subtle change of the sound.
  • Change in physical location.
    • Hitting a drum in a different location results in a different sound. Physical modeling or multisampling can be used to accomplish this to various degrees.
  • Change in frequency.
    • A previous hit affects the current hit. For example, tapping a ride cymbal that is already vibrating is going to give you a slightly different sound.
    • Drum kit components are in constant fluctuation – causing constructive and destructive interference patterns – which provide you with a rich dynamic texture. On the other hand, most drum machines use static samples – there’s no change in sound from one hit to the next.

Again, I think frequency dynamics and subtle variations in performance are what really differentiate live drummers from drum machines. If drum machines want to compete, they need to become less rigid.

Written by admin

August 21st, 2006 at 6:14 am

Posted in blather

win32 nostalgia

without comments

Remember the first time you learned Win32 programming? I thought I’d post a couple of old demos I made during my first encounter with Win32 many, many, years ago.

The above image is from the demo called Elasticity. Drag the square and then let it go. The square will snap back to the origin as if it were attached to an elastic band.

The next image is from the demo called Swarm. It tries to mimic a swarm of fruit flies chasing your cursor.

I cleaned up the source just enough so that it would run. You can download the source for Elasticity and Swarm here.

Written by admin

July 2nd, 2006 at 4:48 am

Posted in code

kondo tool

without comments

Here’s a little tool I made for fun to control my Kondo KHR-1. It hasn’t been thoroughly tested, so don’t be surprised if any “features” pop up. You can download the source here.

Written by admin

June 21st, 2006 at 12:17 pm

Posted in code