*** MUS171 #06 01 20 (Lecture 06)
Here's a thing I'm going to forget to tell you, so I'll tell it to you now while only the early birds are here while I'm thinking of it.
You can set the screen size of tables.
So if the "one size fits all" size that you're all used to is not what you really want...
Like in this example you can do something else.
In this case my table is too fat and it's not tall enough.
So if I do that one, then I have...
Oh, maybe that's too tall for my screen. Anyway. ... Yeah, not good.
All right lets make it 400 pixels tall and 100 pixels wide.
No, looks like I have 300 pixels.
All right, there it is.
My reason for doing that was because the bigger you make something vertically, the more accurately you can control it with a mouse, assuming you're controlling all the way down to the pixel, which is the way tables work.
Actually they maintain floating point values, which are to high precision.
But when you're editing you can only push them onto a pixel value, which might or might not be available, but it's more likely to be available the bigger you make the thing.
So that's a trick.
This is just a review from last time.
Right now what we're doing is we're looking at the first seven values of this table.
Bring this up to here.
And the reason I know that we're doing that is because I'm taking this phaser which goes from zero to one in value and multiplying it by seven.
Which means now you're going from zero to seven.
And then values from zero to seven truncate down to values from zero to six, when you truncate them to the greatest integer below them.
And as a result you're looking at the first seven values of the table which are numbered 0, 1, 2, 3, 4, 5, 6. And the others are just there in case you want them later.
You don't have to have them in fact I could resize the table to seven values now, but I might decide that I want a different size sequence later, and I can do that just by changing the number.
And now we're looking at 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 .. nine out of the twelve values.
Notice that it gets faster as I ask it to use use more values.
That's just because the frequency that I'm giving the phaser is setting the period for the entire sequence and the more notes I stuff in there, the faster the notes are going to be going.
Or to put in another way; the more you multiply the phaser by, the faster the output is changing within time, because the more it travels all told.
Student: So what's the "0.7" ?
That is the frequency in hertz of this phaser.
Student: What units is that, .7 of what?
Let's see ... it does 0.7 of that sequence every second.
So if I set this to 1, it's one cycle per second, if I set it to 2, it's two cycles per second.
So here's 1: [tones] If I say 2 it'll go twice as fast.
Oh, so right now it's every second. 2 is not every two seconds, but every half-second.
So 0.7, what's that? That's one over 0.7 seconds in period.
And I don't know why I chose that value.
Actually I know why; I tried 0.5 and it was too slow for my taste.
So the purpose.... does everyone understand how this example works?
Or, can you formulate questions if you don't? ... Yeah??
Student: Why would you have both the multiplier (and the adder +~) after the phasor?
Right, OK, so the multiplier is taking the phaser's output and re-scaling it so that it goes from zero to seven in this case.
And the adder, I'm not using at this point, I'm adding zero which isn't doing anything.
But if I wanted to instead of looking at the first seven points, look at the points two through eight or three through nine, I would add something to the scaled value and that would be reading at that place in the table.
Student: Is that a phase-shift?
... Oh boy -- it's sort of a phase shift, but it's also... it's just a shift-shift.
Student: So it's like a range-shift maybe?
Right, yeah. This is worthy of... What's the right word? This is worthy of just mastering in it's own right.
This is the general formula for "I want a range and I want it to be seven wide and I want it to start at zero."
In general, if you have something that goes from zero to one and want it to go from A to B, you multiply by (B - A), which is the size of the range, and then you add A to slide it over to where you want it to go.
And you do this all the time in computer music.
You can do the opposite as well, which is you have something that's going from A to B, where A and B are numbers, and you want it to go from 0 to 1. ... Because you then want to give it another range, say.
So, to do that you would subtract A to make it start at 0, and then it goes from 0 to (B - A), and you would divide by (B - A), so that goes from 0 to 1 . ... Yeah?
Student: So, if you add 3, start with 3 will it stop or wrap around?
It'll... Neither. If I give it 3, instead of going 0,1,2,3,4,5,6 it would go 3,4,5,6,7,8,9 .
Student: What if you don't have enough values?
Sure I do. I've got twelve numbers in here.
Student: What if you don't have them?
Oh, if I didn't?
Then, OK, then it's up to the object tabread~ to figure out what to do with when I give it a number that's out of bounds.
And what it does is it simply clips it.
That's to say it simply limits it.
So it doesn't wrap around.
You could make it do that.
In fact, if you wanted to make it do that, you would, before this, you would say, "modulo twelve." (mod 12) Which you all learned about in high school, right?
So "mod" is a good object.
And you would do something somewhat different in signal-land.
Because mod works great for integers, but for floating point you might want to have something that's defined a little bit differently from mod.
So, that gets us down to there, and then it's just the same stuff that you know about from before.
The reason I'm bringing this up today is because I want to use this as the starting point, because it might be nice to know different ways of getting values in and out of tables, of which there are a half dozen.
And I was having trouble figuring out which one to show you, so I just decided to show you all of them.
At least, all of them that I could think of.
And because actually it's pedagogically valuable to know them.
And we're all about pedagogy here.
So here goes.
I have a list.
The first thing that you might want to know about is a wonderful object called "tabwrite."
In fact, I told you about this, but I didn't tell you all about how to use it -- without a tilde.
And then we give it the table name, which I'll just get from here.
And this is a thing which takes two numerical values, which I'll start out by using the number boxes to specify.
And here (right inlet) you say which value in the table you want, "3" say, and here (left inlet) you say what you want it (that value in the table) to be.
And, tada, you're moving value three around in the table.
So, you can see this thing is going up and down as I'm doing this.
This would be kind of--what's the right word?-
- "hideous" to have to make a patch that did this to every single value of the table.
Because you would need a different tabwrite object for every number that you wanted to set, which would be ugly.
So, you want to do it a little bit more smart than that, for which you will need some objects that might generously be referred to as glue.
So, there's some glue involved in using things like tabwrite most effectively. Glue.
So, suppose I wanted the values to be the following, which I'll stick in a message box.
Is this what I want to do?
I'm not going to use this message box yet.
I'm just going to have these values here so that you can see them.
Do I want seven of these things?
... Yeah. Let's have seven of them.
So, now... I'm just making multiples of 110, because since I spend a lot of time in music studios, I like things to actually belong to the western scale.
And 110 is an A.
So, these are easy numbers to just sort of fetch out of nowhere that happen to have at least some reasonable western meaning.
And suppose I want to get these values into this table, what would I do?
Technique number one.
We could use tabwrite.
But of course, I don't really want to type all this stuff in.
I want to just have it in a message box.
How would I get that to happen?
Well, there are things that you can do.
One thing is this. ...
Message box....
Saying that the first number is going to be 990, is the same thing as putting a zero here (right inlet) and then putting a 990 there (left inlet).
And a short-hand for doing that, in Pd anyway, is you can give it a list of values.
And what this means to an object like this...
What does an object like this mean?
-- An object, except for a couple of exceptional objects -- will take a list of numbers and interpret them to mean, "Put those numbers in the inlets."
So, this is saying, "Set the value at slot zero of the table to the number 990. So, this thing jumps up to there.
OOh ... I don't have a good range with for numbers, do I?
Let me change my range, slightly.
So, let's go up to 1,500 Hz.
And this is OK, except of course now I can't do this any more.
I can just click it.
So, it might be nice to know how to do this, but do it in a way that has a variable associated with it, so that I can make that not be a thing that's known already.
So, that's one thing that I want you to just wonder about for a second while I show you something else, which is this:
Now, I can say, here are a bunch of message boxes.
And if I had all seven of these that correspond to these numbers, and gave their locations, and if I set them all in sequence to tabwrite, then I would set the table to these values.
So there's the first one, there's the second one.
Oh, I didn't connect it.
There's the second one, there's the third one.
That's ugly.
And of course, now yow know that if you just wanted to have some way of doing them all...
In fact, I can bash it to something nonsensical like that:
(all values set to 98 via a message-box to tabwrite~)
... I could just give myself a button that activated all these message boxes.
A message box actually will respond to any message at all -- so a bang would be perfectly all right -- and will output its contents.
So now, (let's bash it again) ... if I whack this button it puts all the values in the table. ... ... Yeah??
Student: Could you connect the other message boxes to the first message box, that sort of thing?
You can do that.
I didn't do that because I was afraid of confusing people, but you could do this:
I wouldn't regard this as terribly good style.
But why?
Because, in fact, what this is doing is confusing.
Because I'm sending this message to this message box which is ignoring it.
Someone could look at that and wonder what on earth I was doing.
So it's a little bit better to do it the way that I did it, but you could indeed do it that way. ...
Oh, come on.
Let me select this other thing....
This is still a little bit ugly.
So let me show you the next thing that's a little bit less ugly, which is this.
I can always say, still using tabwrite.
I can say, "Pass the following messages, please."
OK, I'll keep going.
OK, I'll stop there because I'm going to run out of screen.
Now, what this is, is four messages in a single box which are "dellimited," or separated by, commas.
So commas are special characters in Pd.
There are four special characters in Pd.
The comma, the semicolon, dollar signs, and spaces.
Spaces you know about because you just use them to separate things.
Commas separate things, but in a way that means to a message box, "Let there be another message now," and it's going to start here, with this thing.
So this is different from this message box because this contains one message with seven numbers and this now contains four separate messages which will all be sent in sequence.
I have to tell you about how long it takes this to happen, but that's perhaps for a little bit later.
It doesn't take any time for this to happen, is the short answer.
And so this is now a short-handish way of saying, "OK, go ahead and send these four messages that do this thing."
Furthermore you know what order they happen in -- and here (with the bang to separate message boxes) you don't actually know what order these three things went off in because it really is just whatever order I connected these things in.
The order that the things happen in is sometimes very important.
And I've been avoiding getting into situations where the order matters, but I'm going to start making situations like that today, because that's part of the "glue." ...
Questions about this? ... Yeah??
Student: What are the table properties there now for tab.1.20.a
So this is the important stuff ... there are twelve points in it and Y --the vertical axis is running from 1500 to -1. (I made it -1 so you can see 0). And there are twelve points in it.
And this is the screen size of the table which I changed also.
Other questions about this? ... Everybody's clearly happy.
Let me show you another thing that will save you some typing.
If you really just want to put a bunch of numbers in the table, another short-handish way of doing it is to say...
Hmm, should I tell you this? ... Yeah, I can tell you this.
Second technique of doing things, the second flavor of glue that exists in Pd that you'll want to know about:
And I'm going show this to you now because it easily confuses with what I'm doing now, and it's different.
So right now what I'm doing is I'm sending messages to this object tabwrite.
You can also send objects straight to this -- straight to this object. (the table itself) And then you're not talking to a particular auxiliary object like tabwrite or tabread~, or what-not.
You're talking straight to whatever the table itself thinks that it likes to do with messages.
And what it does is design for what it is.
And how you get a message to it is you say "Send."
So let's get an object, and the object is going to be send, and then I'm going to give it the name of the table as an argument.
And then I can actually send it a message which consists of the following stuff.
It has a place in the table that we want to put a value in, and then it has the numbers that I want the table to have.
Student: So the number "990" is the starting point where you want the sequence of stuff?
That's right.
So this is now...
that's on the horizontal axis.
"Starting point 0, please."
And these numbers -- any number of numbers that you wish -- are the numbers that you're going to put into the table.
This is a good thing because now there's an easy way just to write numbers into the table.
So this -- sorry I have to think about something here.
I'm going to have to start saving parts of this patch because it's too big for the screen.
Well maybe this is just what it is for now. ...
OK, so here's technique number one, down here is what looks like a far better technique.
Oh, I don't need this any more.
That was just to make the example, but here's the thing that actually did it which has all the information.
Sorry, I'm just cleaning up. ...
OK, so "send" is the thing which will allow you to send a message to any named objects.
The only object that you've seen so far that has a name is this:
array or table.
Another thing that can have a name is an object whose only purpose is in fact to have a name, which is called "receive."
So, let me give it a different name.
Oh, you know what?
This belongs in a different patch.
I'm going to save this patch.
(starting patch "3.send-receive-etc.pd")
This is going to be two and then three is going to be send and receive...
and some other stuff.
Let's see, we don't need this.
By the way I'm going to get rid of this because...
I'll try to develop this as I do it.
OK, so first off, send and receive as objects.
So, well I don't want to use the word "foo," that's too frequent.
So, dog. So here's a message that we're sending to dog.
In fact so that we can see it, I'll use a number box. (Ctrl-3.)
And then I'm going to say "receive dog," and it gets an outlet.
Oh, so "send dog" only got an inlet and didn't get any outlets.
Receive dog gets an outlet and no inlets.
And now I have this going on.
So now what you've got is:
I was able to put values in the table by sending to the name of the table, but I can also put values into "receive" by sending messages to "receive."
And to be a little bit more parallel to what I did, something a little bit more similar to what we saw above was, I was sending a list of numbers like this and a number box will take a list of numbers and it will pick off the first number, as it can only deal with one.
This is all going to require five objects. ... ... Yeah??
Student: How could you receive the whole list?
... Yeah, how could you retrieve all that?
OK, this is another topic...
... Yeah ... Which I'll get to in a moment.
I'm afraid to talk about it right now.
OK, so send and receive are useful because by now you've probably noticed that your patches are starting to have lots and lots of cords, many of which are short because things are local, usually.
But occasionally your patch, no matter how hard you try to figure out how to lay it out, will have a line like this:
(draws a very long connection, all the way across the screen)
And one way of dealing with that is simply to put a send object up here and put a receive object down there, and that way you get the connection and not the awful line going through the patch.
Later you'll find that it's even better than that because you can have patches that have multiple windows in them, and send and receive is a good way to get from one window to some remote, not very directly related window. ...
... Yeah?
Student: So can you send and receive between different patches?
Yeah. So for instance, here's a new patch and here's an object.
I'll give it the same name, and then I'll hook it up to the number.
Now over here, I say send dog.
(values change from "receive dog" in the new patch).
By the way, one thing that you can like about Linux is that you can do this.
(changing numbers in one patch and seeing changes in the other)
In your computers you have to click this thing (the main patch) to the front and you won't see this (the patch hidden behind it).
Most people hate that though.
... Yeah?
Student: You said it was wireless though?
Yeah. It's a wireless connection.
And because it's wireless, it even works from window to window.
Oh, and this is why I've been giving the tables all these funny names, because the tables will confuse themselves across patches just as the send and receives do.
So if you use the same send and receive name in two different patches and have them open, they will get tangled up into these messages.
... Yeah?
Student: Can you send and receive between different computers?
You have to work harder to do that. [laughing]
And furthermore, the timing semantics will be different if you have two different computers.
If you do it in one computer it's instantaneous, but there will be network delay if you do it across two.
The objects you need are "netsend" and "netreceive," instead of just "send" and "receive."
... Yeah?
Student: So it's all just one giant namespace?
... Yeah, right, which makes it even easier to get confused, because your patches could be things you develop in different years, right?
Or, by different people.
And they could still be talking to each other and getting you in trouble.
Student: Only if the patches are running?
Only if the patches are open -- in the same Pd. (
You can also run several copies of Pd, in that case you'll get away with it.)
But at the same time it will turn out to be good practice some time in the future to figure out how to localize your send and receive names so that your patches don't crosstalk on that.
That will be a thing later on in the quarter.
All right, so, next thing I want to tell you about is packing and unpacking.
This is partly in response to one question I think.
But it's partly also just a thing we need.
So the question was, how could you actually retrieve all this stuff if you wanted to?
Actually there are two related questions.
First off:
"I know how to send a variable message with one number in it, but I don't know how to send a variable message with more than one number in it."
Which for instance you would want to do if you wanted to change...
let's close this now.
We don't want to save this.
So now suppose I want to have a number box that changes this fourth number in the table?
Well, we could go back to what we were doing.
Let's see, of course it erased it, but I'll put it back.
tabwrite, without a tilde though by the way.
If it's a tilde it wants to take a signal and it will write the signal sequentially into the table.
But without the tilde it needs two numbers which are where you write into the table and what you write into the table.
So if I want to change the number at location three which is the fourth number here to some new value like 1,000, I have to type three there and I have to type 1,000 there.
It would be nice to be able to do this and move it up and down without having to set this, or whatever.
Or, to be able to have this thing be controlled programatically by something else for instance, that sort of thing.
So ... ways of doing that:
There are two things that you can do to get this to happen.
The first is just using a message box.
Oh no, let me tell you the other way first because you need this first.
So one thing you can do is you can pack and unpack messages that have multiple numbers in them.
So the way of putting two things together...
I'm going to get rid of this because we already have it. ...
So I'll go back to patch number two and show you some stuff about that signal processing network a little bit later.
But first off, here's a thing.
I'll get two numbers and I will pack them into a message using an object which is called "pack."
And then just to show you what's...
Oh, so just to show you what's happening the easy way...
I'll say "print."
And then we will see packed messages.
So as a rule in Pd, when you throw things into inlets that are not the first inlet -- If it is not a tilde object, if it's a control object, like pack, you put things in the inlet and it changes the object, it advises the object, in some sense.
It changes its internal state.
But output in general, or whatever the thing does, is typically engendered by putting something in the first inlet:
So now we get this message out, "2 79."
So it has two numbers in it, and this message is those two numbers packed into a single message which you could call a list.
It's a list of numbers.
So I can change this all I want and nothing happens, but then as soon as I put in another value in here (the first inlet), I get to see another pair of numbers.
And now I have that... that hasn't helped me yet, has it?
Oh, here is the thing that might help me.
If I want to have a way just to write into location 4 of the table, one thing I can do is say "pack 0 4" and then I will a put a number in there.
And nothing happens...
oh, because I'm not doing anything with it -- duh .
OK, where is my tabwrite here?
To try to avoid confusion, I will make a different copy of the tabwrite object, and now I have got a message box.
It is being converted into a message which is this value and 4. I should print it, so you can see it.
I told you about print, but I didn't tell that you can actually give it an argument to specify what you print.
Sometimes you need that.
So now what is happening is that I put a 450 in and this becomes the message "450 4". I could change the value of 4 by putting a message in that inlet or I can just leave it and it would just say whatever it is, space 4. Yeah?
Student: Is 0 -- where you have "pack 0 4" -- specifying how many values there are?
Oh, thank you.
Zero is there simply to say the initial value of this inlet is zero.
But in fact it is never used because in fact I immediately override it by sending it values.
But if I didn't put it there, it would just be packing the message which consists of 4. And then I would just be generating a single number.
All right, now you know how to do something that you didn't know how to do before, unless you've been looking ahead, which is I've been making these...
OK, so what I'm going to do is save patch number two as patch number four.
And I don't know what it's going to be named, maybe "table-pitch-again" again
(saving "4.table-pitch-again2.pd")
Do you remember that I was making myself a message box to start the thing, and then another one to stop it?
Now I can do that much better.
This is ugly because this value is not in decibels, it's in linear units.
And I would love to be able to use dbtorms to be able to specify that number in decibels.
But db2torms only has a single number that goes in and a single number that goes out.
Here's dbtorms:
(Lets see, can I get rid of this? )
I'll have to go back to this later, but for right now I'll just leave it like that.
So, recall that dbtorms does this:
dbtorms ... You put a number in and out comes the amplitude that you would need to have that number of dB in your signal.
This is a perfectly good way of turning things on and off.
So 70 dB is about .03 as I was explaining last time...
By the way if your going to do this...
I'm just going to disconnect this before I do the next thing.
Make this wide.
Perfectly reasonable numbers of decibels, like 160, are very bad numbers of amplitude.
So it would be very easy for me -- notice I've disconnected this for this very reason.
So I'm sitting here at zero, say, and let's turn it on to 70 or so.
Whoops, just 70. (mouse had generated a value of about 150)
If I did that, I might have just destroyed my speakers.
So if your going to do this, take this message box --I suggest you take this message box and fix the upper limit to something _reasonable_. Oh, let me show you that slower.
So the message box, atom boxes also have properties.
It has a width...
But you can specify a lower and upper value.
If those values are both, that means the thing is just whatever it is, and it can be positive or negative or anything.
But if I give it values that are non-zero, it would interpret that as a range.
And that range will be enforced, which is good.
But what this means is I have something that I can mouse at very conveniently.
So getting the thing to be zero, is that.
Whereas if I did that to a regular old unvarnished message box like this?
I'll turn it off and it will do that: (message box value mouses to -194), which is stupid.
At least, that would be stupid for a value in decibels.
Zero is perfectly good for "Just turn me off."
So it's a convenience to have it so that your number box goes to zero when you drag it all the way down to the bottom.
And to do that you set the range of the number box to be the values that you believe will be reasonable. ...
And then, if you repent later and say, "I really want 90 dB," you can always type it in. --
It won't enforce the range.
It's simply a thing that detects how the mouse operates on it.
So, this is now a good volume control except for one little thing:
and the one little thing is that it clicks when you turn it off and on.
That's why I was using these things (line~) that have time values.
Of course, when you have message boxes for the time values you have to decide what the thing was in advance.
But now that we have the pack object, we can do it all, right.
We can now say "pack 0 50". And now, what's going into this multiplier is the output of line~ which is getting messages which are "0.2 50" -- those two numbers -- and that will turn the line on and off in a way that will not click.
So, this is a correct -- or at least a not incorrect -- way of managing gains in dB.
You can do even better than this, but this is the first time I've shown you how to do it well enough that you would actually want to do this to someone else who had to use your patch.
Are there questions about how this works?
... Yeah?
Student: Can you explain the two numbers in the pack?
Yes. So, the two numbers in the pack serve to do two things; they initialize the values of the inlets in the pack.
So, this value is initialized to zero and this value's initialized to 50. They also serve to tell you how many inlets the pack will have because,
you won't have to do this any time soon, but some day you might have to have a message that has six or ten values in it and you can tell pack to have more than two things by doing that.
If you just say "pack," by default it assumes you mean "two" (inlets). If you want something else, give it numbers, numbers which will initialize the inlets, but by the way will also supply how many inlets you want. ...
And you had a question, too?
Student: Yes. Is the number box after dbtorms affecting the value that goes to pack?
No. It's just so you can see it.
And furthermore, there are differences of opinion about whether this is good style.
So, there are people around who will pontificate about the proper programming style in Max and Pd, more in Max, actually, than Pd.
The Pd community is kind of forgiving that way.
But some people say that you shouldn't do this because someone could walk up to your patch and do this:
(type in a new value into the number box) -- And this would be in a bad state now.
Because if I "moused" on this thing, it would suddenly jump from 0.3 to whatever I just made here, which wouldn't agree with it, right?
And that might not be a good thing. ... Yeah??
Student: Can you make the other boxes un-editable, so you can't edit them?
Inedible? Oh, un-editable.
I don't think they're edible ... But you can't, no.
Oh, wait a second. ... No, you can't really.
You could set the range to be from two values that are equal, but then if you touched it, it would jump to that value.
So, actually, yeah, they're always going to be editable.
But one thing that you can do that sometimes helps people--and this is programming style, you can do it or not--is make the thing hang like that.
(is not in series with "pack" any longer.)
So, that it is clear that it is only there for the purposes of showing me what the number is, and it's not there for you to mouse on.
That won't stop you from mousing on it, but at least you can tell that mousing on it is not going to do anything for you.
So, there are people who argue strongly that you should do this, instead of what I just did.
And me, I'm agnostic about it.
I do it sometimes one way and sometimes the other.
Other questions?
So, that is pack and unpack, which we use for two different purposes.
Actually, pack seems to get used a lot more than unpack, because there are objects which you have to send messages to that have more than one number in them or more than one argument, as you might call it.
Unpack, you use if you want to make your own thing that takes pack messages and distributes the numbers in some way or another.
Student: I don't think you've showed us unpack yet.
Oh, I haven't shown you unpack. --
Sorry, yeah, better do that! OK, so this is now number four.
The reason I didn't show you unpack is because I forgot to finish number three.
So, let's go back here.
So, this is pack.
I was just showing you this, and then it wasn't obvious why this was a good thing except for putting numbers in a table.
But the other good thing that you could do with pack is controlling volume, controlling volumes in a way that it would operate in dB, which you couldn't do before.
Now, unpack is this one:
Again, you give it arguments.
By convention, I just use zeroes for unpack, and the arguments do nothing but set the number of outlets, and the outlets are going to be the two numbers in the message.
Whoops. So now, it's showing me the numbers that I was previously using print to see.
The reason I used print before was because I hadn't told you about unpack.
But now that you have unpack, you can now make things.
Assuming you know when you're building the patch, how many items are going to be in your message, how many numbers are going to be in your message,
then you can put an unpack there to show yourself what those things are, or to distribute them in some way that does something useful.
So now, having seen that, the next thing to do, I guess is go to window number four again, and using send and receive, bash a whole ... -- You basically know how to do it all now.
Except I want to show you one other good thing, which is that you can use text files to maintain numbers in tables, and that is a good thing, because that's one of the easiest ways of getting Pd and other software programs to talk to each other.
So do that, we'll go forward to ... no, we'll just stay here, actually.
So, the table, here, can be sent a message, which we can do using the send object.
So we're going to send to tab, oh, we've got one of those.
We've got an object called send.
OK, so, since we have that object send tab, bla bla bla, I'll just re-use that object for all the other messages that I'll be sending this thing.
There are plenty of things that you can send to the table.
This was a thing that got values in just by specifying your numbers, so there are also messages that you can send, which are ... I'm introducing too many things here:
First off is fact that you can actually have messages that have commands in them, and second, the fact, what the commands actually are.
You can say, read some file, and it will look at the first twelve numbers that are in that file, and put them in the table.
And of course, what I have now is just an error message:
"file1.txt: can't open"
So, the other thing that we've got is, "write."
Especially for those of you who have Macintoshes, it's getting hard to make text files on Macintoshes, because when you open the text editor up, it wants to do rich text for you, which you don't want, usually, if you're doing stuff with computers.
So, sometimes you have to just make yourself a nice seed text file.
So here's "write file 1.txt".
And now that I've done that, maybe--oh, it doesn't--let's look at all files.
Oh, we don't want to do that. Never mind. Sorry.
I'm using an operating system and now I have to remember how you see files in this thing, which is you go get the little finder hoo-ha.
Tada! "File 1.txt". And now, we have a text editor -- this will work on your Macintosh, too, or your PC -- which has the stuff that was in the table.
And since this is a text file, you can now read it.
You can read it in the MATLAB or Octave, or what else?
Well, you can dump it into HTML, or whatever it is that you want to do with it.
Similarly, now if I want I can put new values in here.
For instance, if I wanted to I could...
Well no, I'll just do it.
It doesn't matter whether they're on different lines or not.
Let's see ... we had 12 numbers in the table, so I'll just give it 12 numbers.
It does the right thing if you have the wrong number of numbers.
And now, we go back to Pd.
Where was Pd?
And say, "Read it."
And there's the nice table I just edited. ,,, ... Yeah??
Student: Is that text file in the same directory as your .pd file?
Oh, thanks. Yes. -- Well, you could give it a path.
So, you could say, "Read ../blah/File 1.txt". And, yeah.
But for right now just make everything be in the same directory.
Also, you can give Pd a search path.
So, there's directory stuff to worry about.
One thing that will come up and bite you is that when you make a new patch, it doesn't know what directory it's in.
And as a result, it might not be able to read a file that is in a directory because the patch itself -- before you save -- isn't in that directory.
It's in no directory at all.
So, you might have to save your patch just to tell Pd what directory you want the thing to believe it's in, so that you can read files in from that same directory.
So, you've seen send.
You've seen pack, you've seen message boxes, and you've seen files.
And this is probably enough Pd lore for a day.
So, I should show you some more stuff of relevance in music for a while.
I know, I haven't been making a whole lot of noise yet.
What I want to do to that end is start out with the assignment for next week, showing you what it is.
It's on the web page.
But the web page doesn't explain it very well.
And so let me explain it better.
So, I'm going to save this.
So, the near-term plan...
(pause for setup/logistics)
Oh, great. I'm running two Pds.
So, I had it miniaturized some how.
I didn't know it.
What's going on?
Oh, and I had this terminal.
Oh, I see, I've miniaturized down to...
Sorry, I'm getting myself confused here.
Now, I'm no longer confused, maybe. [music plays from patch]
This is...
You know how to do this.
Here's a cool thing.
Let's see.
Turn it up.
This is an idea that's attributed to Steve Reich.
Am I pronouncing his name right?
Steve Reich, who invented the idea of having two tape loops with sounds on them, that had slightly different durations, and then playing them both in a loop, so that you would hear them getting phased differently with time.
And then, OK.
So he did that in a series of famous pieces in the 60s, the first of which I think is called "Come Out," which you should probably check out if you haven't checked it out.
And then, he started writing these things like that for instruments, in particular, this one called "Piano Phase," which orders two pianists each to play a 12-note sequence at very slightly different speeds, so that they would phase gradually.
And you would hear them juxtaposed at different phases essentially.
It's the same kind of phase as the phase in an oscillator, except it's being used differently because it's a phase and a melody.
Well, we can do that here: [music plays from patch]
Is it doing it?
Oh, yeah.
I'll let this go for another round or two. [music plays from patch]
There's all sort of fascinating stuff that you can do with this.
Of which I'll show you just a little bit.
One thing is, and this idea I believe is due to David Wessel.
I'm not sure, I heard about it from him:
You can make melodies, and this is the extra credit.
You can make melodies that have two different timbres as well as a repeating pattern ... Actually, this doesn't sound as good on these speakers as it did at home.
By the way if I were doing this for real I would probably work on getting that better.
But I'm doing this only with objects that you've seen so far.
Turned out to be tricky to get it to be perfectly clean, until you have some of your objects in your arsenal.
But what's happening now is there are two different tables of pitches... [music plays from patch]
And what you should hear is the same, what's the word, same series of pitches as you heard here.
Except that every third pitch has a different timbre. [music plays from patch]
So here's the part of the sequence:
All right, so you can also hear [snaps fingers]... If I slow it down, then you just hear the thing as a sequence-- you can't actually hear the other point of view on it.
Which is that you can hear every third pitch as a separate stream.
That only happens at particular speeds.
This is the effect that Wessel I believe discovered.
So now if I speed it up at some point you quit hearing that as a sequence going at this speed, and you start hearing it as two different things.
One of which is the sharp timbre, and the other which is the sinusoid.
All right, the original David Wessel was three pitches.
And [music]
So it's going down.
It's three blind mice now, right?
No it's not, it's going up.
It's "Do-Re-Mi."
Do, re, mi, like that.
Actually, for some reason in this register the sinusoid doesn't sound like it's the same octave as the other ones, but I guarantee you it is.
And then if you speed it up, instead of hearing the thing rising like that, you'll hear it going down.
It's like now you hear two different melodies which are catty-corner, right? And... [music]
So now, if you're good at math, you can figure out that choose any two relatively primary numbers, the number of notes in the melody,
and the interval that you change from timbre A to timbre B, and then you can pick out, basically, permuted versions of melodies that exist within themselves.
And then, yeah?
Student: What does "modulus" mean?
What does "modulus" mean?
Well, OK.
I actually don't know what the word means in fully general, but in mathematics land modulus means the range of a set of numbers that repeats.
So, if you say five is equivalent to two modulo three, in that statement the modulus is three.
I don't know of a better way of explaining it than just by contextifying it like that.
And, of course, you can do this with...
or can you?
I don't know.
I don't know why my patch isn't working today.
You should be able also to hear that phase -- But I seem to have forgotten to connect something in the patch to let you hear that.
So, here is the basic homework thing:
Just do this.
And then if you want to make it hard, do that, except that every third note should be a separate timbre as well.
Then you'll hear really wonderful stuff.
Qustions about that?
... Yeah?
Student: Is there another patch behind there?
Oh, is there another patch behind here?
I didn't tell you this:
If you're working on a patch and you run out of room, you can just say "PD" and either give it a name or not.
Usually I give it a name just so I can tell what's what.
And up will pop another window, and this window is inside this box.
And this is what you do... --
I've been avoiding doing this because I don't think you should be using patches this complicated, that you need this yet. ...
But this is what you do when your patches get too complicated to hold on one screen.
You start encapsulating parts of it into sub-patches.
And then when you close the sub-patch...
oh, let me put something here...
when you close the sub-patch, it's still there in this box.
And you can see it again by clicking on it.
So, if you look at a real piece of music realized using either Max or Pd, it will typically have hundreds of windows in it.
Because all this easy stuff I've shown you so far fits in a window, but by the time you really want to do something specific and you want it just so and you want to have voices and so-on like that, you're going to have windows on top of windows on top of windows.
This is the way of managing them. ... ... Yeah??
Student: Is the a reason that the "pd ----doit----" patch has six different connections is the patch itself is behind the scenes here?
Right. -- And the reason the patch is behind the scenes is because it implements the homework. [laughter]
In fact, there's another reason, too, which is that I implemented the homework in an exceedingly messy way because I made a lot of mistakes and got confused on doing it and kept changing my mind about what you should do.
And so it contains a lot of things besides the homework that I want to go back to later -- but I don't want to show you right now. [laughs] ... Yeah?
Student: In the text file that you did earlier ... Is there a limitation on how long the path can be before it doesn't work?
I think it's limited to 4,000 characters. Should be OK.
But message boxes don't like to be more than 80 characters wide, so that it will automatically wrap the file name in the message box.
There is a thing which I should have told you about.
If there's a space in your file name, Pd will think the space means that you have two different file names.
So, spaces in file names are evil as far as Pd and Max are concerned.
Student: So you can just use underscore, etc? ... Yeah??
Student: Do you have a patch file on here that shows how complicated this can actually be?
Oh, yeah. [laughter]
Here's the patch.
This will take a moment to load, but...
It just did. [laughter]
... Yeah. This is a piece that I'm working on with a composer.
I'll just talk over this while it struggles to load.
Oh, here it is.
So here are a bunch of control panels.
This is an effects processor and it has a frequency shifter with a bunch of parameters.
It has a bank of comb filters.
It has more comb stuff ...
a phaser, noise generator, flanger, harmonizers.
Then meanwhile, there is a sampler bank and there is a thing called Jack.
It's just called "jack" because it's a name.
Then, "eric" -- this is talking to the Synful synthesizer which we have upstairs if you want it.
Then pafs the phase-aligned formant generator which is a synthesis technique that has a bunch of parameters in it and has a bunch of voices in it.
I haven't told you yet, but number of boxes can have sends and receives built into them -- which you need to do if you're going to make something this gnarly.
And how is it implemented?
...Oh, there's markov chains that can drive anything that you want.
But anyway.
This machine will not be able to make sound with this patch, I'm afraid.
It makes great sound, I'll tell you.
So, here's the actual patch.
Here's the sampler.
The sampler has a few voices of samples, and this is a spatializer that sums the first four voices into one place.
Then these get spatialized separately and so on.
The sampler itself looks like this, so there's a bunch of these guys.
Samp-controllers that control things. ...
Here's the unpack and pack for you, I use that a lot.
Here's polyphonic voice allocator.
Go on like that ... "route" ...
Student: You did this all in an hour?
No. I did this in a couple of years.
Inventing all of this stuff as I went along ... hardcore stuff.
Student: Can we hear something from it? [laughter]
Nope. You know, if I drop the sample rate to about a kilohertz I'd be able to do it on this processor.
But this is an Atom processor and the patch needs Core 2 or so to run.
Then there's other stuff. So, we can make arbitrarily complicated patches.
Student: Are the Markov chains something that we're going to cover?
That might happen later this quarter or it might happen next quarter.
Most likely next quarter, but that depends on how things flow.
You can make various kinds of stochastic processes in Pd, and people do use randomness computer music all the time.
Back to "Lore with Tables" and what-not.
Now I want to find the patch I just had.
I must have closed it. [pauses] (opening up "4.table-pitch-again2.pd")
So, now, just to try to tie things together a little bit, I'm going to go back to using tables as waveforms and not as pitches.
Before I do that, let me show you something else.
On the level of glue, there was something important that I didn't tell you.
So, suppose I wanted to put values in the table, but suppose I didn't want to type the values out in cycles per second.
Instead, I want to specify a melody and pitch.
That would be a good thing to be able to do.
So for instance, suppose I want to...
Let's see what's the easy way to do this?
Trying not to introduce too many different objects here. ...
So I had to do it in this way because this is going to be the easy...
well let me show you.
Let me start doing it, and then try to explain what I'm doing as I'm doing it, because I can't figure out how to verbalize it without just showing it.
So, the first thing we're going to do is just say, OK, we're going to put a value on the table, and the value's going to be some number.
And it's going to go into slot zero.
And then I'm going to have a number box that puts the value in.
Ugh. Now I've got this thing going.
So now what you can see is this first value on the table is going up and down, depending on the number in the message box.
But then--what did I figure?
So the message now is "617 0". 0 is "where in the table", 617 is the value.
Now you can sort of see why tabwrite takes the Y-value, that's to say the "value" value here (left inlet),
and the X-value in the other inlet.
It is exactly so that I can do this:
(mousing over the number box into the left inlet)
-- and it changes the value of the table instead of maintaining a single value and splashing it across the whole table, which is likely to be a less important to do.
There is a way to get it to do the other thing if you want, but I don't want to show that to you just yet because it's more glue.
And now of course, if I want to talk to the next value in the table, I just say "1" here, and then I'm changing this next value.
Oh, wait--connect it! OK, so this is all clear, and now, ... Yeah?
Student: Could you connect your number-box to the right inlet of pack, so you could mouse it and change the position in the table?
Except, that in fact it won't do anything.
So here--so I'll say, "Put in 550 please, and put it in location 0." And I'll say, "Put something in location zero."
(mousing over message-box connected to right inlet)
But then I'd have to bang this, or maybe resend "550."
And, yeah, there's a thing I have to tell you, which I've been putting off, but now that you've asked, maybe this is the moment.
You can... OK, here, I'll do it the wrong way first, and then show you why it's wrong and then do it right.
So the wrong thing to do is, (I have to introduce another object to do it right) ... So the wrong way that doesn't require introducing an object is:
550, it's a message; I can throw the number in there.
And then I can say...
Oh, that one.
Oh, yes, thank you.
So I can do nothing. (connects the pack to the tabwrite)
OK: 0, 1,2,3,4 . OK, that's good.
It's not really quite right, because what I haven't done is I haven't actually verified that the 6 goes in here (right inlet of pack)
before the 550 goes in there (left inlet of pack).
If the 550 goes in first, then it writes 550 to whatever this (right inlet, "position") value had been before,
and then writes the thing (right inlet value) in afterward.
And that would be wrong.
I'll make it clearer this way -- a sort of textbook example of how to do something wrong:
Let's take a number and square it by just using a multiplier.
And now what I'll do is just multiply the number by itself.
Now I'll say five, and five squared is five??
-- actually I don't even know how that happened.
But then six, and then I get 30. Why?
Because you don't actually see it from the patch, but just from the way I connected it,
what it's doing is it's sending the 6 to this inlet (left inlet) first.
And multiplying 6 by whatever is in this inlet (right inlet), which is 5.
And then it's hiding the evidence by putting six in there.
And now, no matter how many numbers I put in, it's going to do it wrong until I happen to put a number in twice, at which point it'll do it right.
This is confusing and bad.
To make it good, you need an object which will actually force the order to be a particular order.
Which is to say you want to put this value in first (into the right inlet) before you put that value in (left inlet).
And the object that does that for you -- this is object number six for today, so I'll apologize, I think -- is "trigger,"
which, is named "trigger" just because that's the word that Max Matthews used to use for doing something.
So, you can think of this as a distributor in an automobile, if you're the type of person who fools with automobiles.
And what it does is it takes the value as a floating-point number and outputs it here and then outputs it here as another floating-point number.
And again, I specify float, or bang if I just want to convert it just to a bang message, or other stuff that I don't have to tell you yet.
And now, I've got something that is guaranteed to do the squaring the right way no matter what order I connected it in. -- Trigger.
This is so useful, it's so useful and so long-winded that you can also just say trigger, float, float like that. (t f f) -- And this is what you see more often.
So, here, what I want to do, really, is I want to take this number six and I want to put it in the pack.
And _then_ I want to send 550 in the other inlet.
And now I've got the thing in a way that it will work correctly.
This does the same thing as the network that I had before except that before, I had this number box connected both to the 550 and to the zero.
And you didn't know that they happened in the correct order, which is to put it (the position value) in this inlet (right inlet) first
and then put 550 here. (left inlet)
Student: Could you have additional outlets from the trigger that you don't use?
Here? Yeah, yeah, yeah.
So you can say whatever you want.
Here would be a better style to say give me a bang out this one.
So this is the type of this outlet.
And you don't need the floating number because just the message box will just convert it to the number 550 anyway.
And so here you would just send a bang out instead of a float.
Although I've used float before, the possibility of float before.
So this is the way to get something into an inlet and then make the object do something anyway.
Whereas if you just knew that this value (right inlet) was zero and wanted to control this number (left inlet) with a number box,
it's the much easier situation to deal with.
Which is that you just take the number box in the pack like this.
So this is the easy case, where you're changing this (left inlet) with the number box.
This is the hard case, where your changing this (right inlet) with the number box.
Sorry, this is much too much lore for one day.
But lore is good.
Rather, lore isn't good in it's own right, but knowing how to do this kind of stuff is good.
Now I have to clean this up for you and put it on the website, so you can look at this in fullness of time.
Questions about this?
.... Yeah.
Student: I'm still not quite sure how the trigger sends values from its outlets.
The trigger object always sends messages to its outlets in right to left order.
And it's right to left and not left to right because typically you want the left-most thing to arrive last for the object afterward to work right.
... Yeah, I should have said that.
That was a very good question!
Now, that I've done this, I can go back and remind you of the wonderful midi to frequency (mtof) object.
Now I have a sequencer that I can control using midi numbers.
I'm running out of room here, but I guess I'll do just as much as I can make room for.
We're going to have a seven note sequencer.
Yuck! OK. Got five of them.
Now, the only difference between these is that this one is going to go to cell zero, this is cell 1, this is cell 2, this is cell 3, this is cell 4 -- And let's just have a five-note sequencer because I'm getting tired of this.
Oops, no -- 5. We'll go once per second and listen to it: [music from patch]
OOps. So now, that's a good melody that has five notes in it? [music]
All right. [music] [laughter]
Now we're making western, tempered melodies in a table.
These numbers, now, are the frequencies in Hertz of the pitches which I specified in midi in these number boxes here. ... ... Yeah??
Student: Could you just have midi values in the table and then use mtof to put those into the osc~?
Instead of storing the table in frequency, can you store in midi?
Oh! Yes. Of course. Oh, yes.
You can do that, but notice that I'm reading it (with tabread~):
So I would need to use mtof~ because the output of the table is an audio signal.
That would be another way to do it.
But, of course, then you're doing the conversion every sample, which is more expensive computationally, whereas, this is cheaper.
Everyone's restive ... [laughs] I can see why.
There was a lot of very dry detail today, for which I apologize.
Next time we'll get back to samples and tables, and storing sounds in tables and using oscillators to get them out.