*** MUS171 #08 01 27 |
Miller: @0000 ... Now how will this sound differently from this? Any takers? Student: It shouldn't. It's basically... Miller: It's exactly the same. Student: Yeah. |
es: @0000 |
Miller: @0015 All it does is instead of going up to 88.2 in 2,000 milliseconds it goes to 100,000 in more <<2268 = 2000*100/88.2>> So it just plays off the end of the table -- which does nothing. Student: Complete silence afterward. Miller: Well, playing off the end of the table simply sticks at the last point. |
es: @0015 |
Student @0030 Questioner: Oh, OK. Miller: So again, if this was: [Recording: "This is your brain on drugs."] Miller: Then this is the same thing: [Recording: "This is your brain on drugs."] OK? Student: Wait, why doesn't it play the little noise after two seconds? Because you stopped it at two seconds? |
es: @0030 |
Miller: There is noise there, @0045 |
es: @0045 |
@0060 but if you wanted to hear that I would have to turn the volume way up. So this noise ... Student: ... is being played? Miller: Yeah. Whatever is there. In fact, actually, why don't we do this? How you would hear that, and just that, is we could go to, let's see, this is... Student: Instead of starting at 0 you start at 88.2? |
es: @0060 |
Miller: Yeah. Well, I won't start there, @0075 but I'll start around here, so maybe that's 80,000 or something like that. So let's go... Where am I going to do this -- 80,000 -- and then I'll just add something and I'll say 2,000 ... |
es: @0075 |
@0090 Oh no, wait: 2,268. Sorry. OK, let me explain this now that I've done it. So now what I'm going to do, |
es: @0090 |
@0105 I believe this to be 88,000 right here, because I said the table would be 88,200 samples long. So this <<the point where the voice ends>> x might be about 80,000, maybe plus or minus. |
es: @0105 |
And now what I asked it to do was start there and go to another point which is @0120 100,000 more and to go there in this amount of time <<2268 msec>> which is the amount of time I should take ... Here: |
es: @0120 |
@0135 "Go from a point most of the way through the table 100,000 samples further and do it in the amount of time that's correct for 100,000." So instead of hearing this ... [Recording: "This is your brain on drugs."] Miller: ... you hear this: [silence] |
es: @0135 |
Miller: @0150 And now if you want to know what's in there really, then I'll take the risk of turning the audio up, and you'll here the room's reverberation and things like that, maybe.[noise sound from end of the recording plays] |
es: @0150 |
@0165 Don't know what that is. That might be the room ringing or it might be me clicking on something right after I said it or something else. |
es: @0165 |
Student @0180 Questioner: Why did you choose that amount of time, 2268, as opposed to just like two seconds? |
es: @0180 |
Miller: Yeah, that happened last time. I computed how much time 100,000 samples lasts. @0195 And I did it using a calculator. Student: Oh, right, right, right. So you just got to do that real time? x |
es: @0195 |
Miller: I didn't want to actually re-compute it, so I just used the value I happened to know. But @0210 the value I happened to know was, if I want to have 100,000 samples and I'm running at 44.1 kilohertz, that's the number of seconds |
es: @0210 |
@0225 that amount of that number of samples lasts. Student: So if you don't put that number in, then it won't be the exact same time like you recorded it? Miller: Right. Student Questioner: That's real time, right? |
es: @0225 |
Miller: @0240 Right. Yeah. Or, real time, that is to say, that's for no transposition. And this is a good example. This is ... [Recording: "This is your brain on drugs."] Miller: So if I change this to something else, like ... [Recording: "This is your brain on drugs." at 2X speed] Student: Like what if you didn't put a number? |
es: @0240 |
Miller: If you didn't put a number at all, then it would go to 0, and then it would jump to 100,000 @0255 and stay there ... Student: Oh. Miller: ... So you'd hear nothing. Yeah. Student: So how would you start it right where the recording actually starts, and make it accurate? |
es: @0255 |
Miller: Good question. @0270 How would you find the place at the beginning of the table in order to be able to start right there? There are a bunch of ways you could do that. The way I would do it if it were me is I would do the following: |
es: @0270 |
@0285 (Oh, this will take ... I have to add a concept here, but I'll do it. Because I was wondering when I was going to be able to add this concept. So how about instead of ... |
es: @0285 |
Sorry. @0300 I'm going to really do this -- I'm not going to add any concepts at all. I'm going to do this: I'm going to |
es: @0300 |
@0315 make a little player that plays little tiny segments of the table. (The concept, by the way, that I wanted to add was using message boxes to make variable messages, |
es: @0315 |
@0330 like using dollar signs, but I haven't hit a place where I need that yet.) So what I'm going to do is I'm going to make one of these <<a sample player>> except I'm going to make it be variable. All right? |
es: @0330 |
Let's see, I'm going to need some room. @0345 I can still reuse all that. And this needs to go to here, so that I have room up here. Pull this down, make the window bigger. |
es: @0345 |
@0360 So now what I'm going to do is I'm going to make a number box, and I'm going to arrange for the table to play -- starting at the number box -- a few samples: |
es: @0360 |
All right? So, to do that, what we're going to want @0375 is to generate something like this, number, comma, and then another number in a certain amount of time. Except that the numbers are going to be variable. So, for instance, the numbers might be ... |
es: @0375 |
@0390 let's start at 10,000, and then let's go another 1,000, and let's take a hundred milliseconds. |
es: @0390 |
@0405 So, these two, if I did them in sequence, would go click, and what this is, sounds nice and metallic. |
es: @0405 |
@0420 That's me doing a consonant, probably, and it's at the wrong speed, because I have to be careful about speed here. |
es: @0420 |
Now, how would I do that, except make the 10,000 variable? Well, it's not so hard, all we have to do is we have to use the @0435 wonderful trigger object to generate two messages. One of the messages will go straight through, the other one we're going to add 100 to it, and then pack it in order to make a message to hit 100. So |
es: @0435 |
@0450 that's going to be like this. |
es: @0450 |
So this one, instead of doing this, we're just going to run this straight in. This one is going to be a packed message using the pack object, and what we're going to pack is going to start with zero and 100, @0465 and this, except we're going to replace the value of zero with something. And, the value that we're going to replace is going to be whatever this thing is, plus 1000. |
es: @0465 |
@0480 And now, we have to send a message in here and there, and we should do it in the right order. So, we should use a trigger object. |
es: @0480 |
@0495 Trigger: -- OK, these are all objects you've seen, although you haven't seen them done this way, so I'm doing a sort of review. |
es: @0495 |
So first off, we're going to send the value as a floating-point number @0510 to the line then, and immediately after, we're going to send a value which is 1,000 more. But it's going to be in a packed message, with 100. And now if I say 10,000, I get my sound back. [sound] |
es: @0510 |
@0525 OK -- This isn't moving very much. So, let's do some labor-saving and multiply it by 100. |
es: @0525 |
@0540 Now, this value is too big. |
es: @0540 |
@0555 Now, what we're doing, is we're scratching through the sample. It's such a horrible pitch, you can't even tell what's happening -- or I can't. So I'm going to say, do this in about a fifth of the time that I said before. |
es: @0555 |
@0570 Now I've got a pretty powerful tool. Because I can do this: |
es: @0570 |
@0585 It's got problems, right, which we're going to have to work on. [sound] |
es: @0585 |
But notice now, I can say: here is the very beginning -- this is your question now. Here's the very beginning of it. @0600 If I want to know exactly what the beginning was, maybe I should subtract this 1,000 from here. But it's close enough. And, I don't know of a better way, actually, |
es: @0600 |
@0615 of finding the beginning... I don't know a better, simple way of finding the beginning of the sound than just looking for it audibly like that. Question? Student: Can you go over "trigger" one more time? |
es: @0615 |
Miller: Yeah. Good idea. So, trigger, I've introduced @0630 and I think the last time it was triggered with two bangs, as a way of making two message boxes be in the correct order. And now I'm using a slight twist on the trigger object, which is that it will take whatever message you put in, and output |
es: @0630 |
@0645 that message from right to left, in right to left order. Let's see ... it looks like this to you. And it will put out variously floating-point numbers or bangs, which are messages that don't have any data, or lists, in case your message |
es: @0645 |
@0660 has more than one number in it. |
es: @0660 |
And so in this case, what it's doing is it's interpreting this as a floating-point number each time, which is appropriate. And it's first putting the number 2,700 out here, and then it's putting it out @0675 here, so that it can get 100 added to it and get packed with the value 40. So that, if I want to see what's happening to the line (with a print object, no tilde needed, just the regular old message print). |
es: @0675 |
@0690 I can do this: Now, the print is hooked up exactly the same as the line object, which is down here. Student: What does the number 40 represent in the pack? |
es: @0690 |
Miller: 40 is the amount of time. @0705 So what I'm sending the line is these two messages. 2,700, that came from this 27 when I multiplied it by 100. And then the other message is going to be |
es: @0705 |
@0720 a target value of the time. The target value is computed by adding 1,000 to whatever the start time was, and the time I just gave as 40. And now, of course, 40 milliseconds isn't the right amount |
es: @0720 |
@0735 of time for 1,000 samples to last. But I just remembered that we went to the trouble of finding out that 100,000 samples is 2,268 milliseconds. |
es: @0735 |
@0750 So, really here for 1,000 we should use one hundredth of that which is really 22.6. It's not gonna be exactly right for technical reasons. [sound] Now I've got a little scratcher! [ Recording: "This is your brain..."] |
es: @0750 |
Miller: ... @0765 Yeah? Student: Why exactly do you want to pack this? |
es: @0765 |
Miller: Oh. Why do I want @0780 to pack these? So that the message itself can have two values in it, because line~ wants to get a message (which is target and amount of time) in a single message. Student: So that's why your packing ... Miller: Right. |
es: @0780 |
Student: @0795 So, pack automatically replaces the zero? Miller: Yes. So the zero initializes input but is getting replaced every time I put a new number in. In fact I can replace this <<right inlet>> by setting numbers in here too. |
es: @0795 |
Student: @0810 Could you hypothetically send the trigger also to the right inlet of pack and so whatever you are sending to that zero you're also just sending to the right inlet? ... |
es: @0810 |
@0825 You know how you're getting 40,200 plus a thousand... Miller: You mean make a thing that has this number twice? Student: Yes. |
es: @0825 |
Miller: You can do that but you can also do it wrong, like this: @0840 (This won't sound good but I'll do it just for the sake of the argument.) I do that and I'll put a number in here and I get the correct value and whatever the previous correct value was. So now we have one of these situations where |
es: @0840 |
@0855 if you put a message in here that generates output and then if you put a message in there it updates the inlet. But you want to update the inlet first so that that value will be there when the outlet comes. Student: I forget about that ... Miller: Right, and to do that you need another trigger object. |
es: @0855 |
Student: @0870 If you put another parameter in there as well will that create another inlet, so that you can control that, too? |
es: @0870 |
Miller: Yes, and I think line~ doesn't care about that: I'll give it another value. ... @0885 Oh, let's not do this anymore. <<disconnects from right inlet>> [sound] Right now it's making messages with three values. The thing about that is that there aren't very many objects running on Pd |
es: @0885 |
@0900 that can meaningfully deal with three numbers at a time. They are all designed to be as elemental or as elementary -- as atomic as they can be. In general, when you are just using objects |
es: @0900 |
@0915 and forming messages for them pack with two numbers is all you're going to need. |
es: @0915 |
However, when you make instruments yourselves that might have 100 parameters in them to describe a voice, you might find yourself packing all those 100 parameters into a big mondo message. @0930 Eventually it's going to be interesting to be able to use pack with large numbers or at least medium sized numbers of parameters. Student: If that's the case would you use Pd window, that hidden window to do that and just have those with you? |
es: @0930 |
Miller: Yeah, by that point you would be @0945 keeping everything under the hood. Yeah, in a big way. And we'll get there but maybe not even in the first quarter of this. Other questions? |
es: @0945 |
@0960 If everyone is happy with this... I can't believe you actually all understand what is going on. |
es: @0960 |
Student: ...@0975 wouldn't say "all" ... |
es: @0975 |
OK, well my plans for the rest of the day are to make this @0990 more complicated. Because of course, it would be useful to be able to do things like actually control the transposition. |
es: @0990 |
@1005 When you buy a sampler you sample something and then you hit C and you hear the original thing so you hit G and you want to hear it in transposed to fifth and that sort of thing, So I want to talk about transposition and how to do it. Now the other thing which is |
es: @1005 |
@1020 perhaps, even more fundamentally important, is how to keep it from [sounds] making those clicks. And there are several ways of doing that. I want to show you two of them. |
es: @1020 |
What I think I should do is start with the transposition. @1035 The sounds will still be kind of revolting but at least you'll see how it's possible to transpose stuff. Then after that I'll start in on trying to work on the clicks. Alright. Transposition stuff. |
es: @1035 |
@1050 Transposition: It's not so easy to necessarily hear how much this is being transposed by because you might not know what the original... Does everyone know what transposition is? That's a musical term. |
es: @1050 |
@1065 That means the change in pitch that you get when you read out the sampler, compared to what you put into it. At least that's what it means in sampler land. What I am going to do is get rid of this because we are not going to get here so fast, |
es: @1065 |
@1080 but I''m going to put that in a future window. <<saving "4.notyet2.pd">> |
es: @1080 |
@1095 What this is that we will |
es: @1095 |
@1110 come back to is using a phasor object to drive a sampler. Which, you in fact saw for the first time on Tuesday but I haven't shown you for instance how to do things like affect the transposition |
es: @1110 |
@1125 in this way of doing sampling. |
es: @1125 |
So we've seen two ways of operating samplers in the same way as we have seen two ways of reading sequences back. One of which is this way, which is the signaling way which is generated, as I mentioned, well, which @1140 if you look all the way over to the top of the network here, you'll typically see a phasor~ object. |
es: @1140 |
The other way of doing it is to just use messages. In which case, you can do things in more irregular ways. But there is sometimes more to think about when you're doing @1155 the messages that just doing phasors. |
es: @1155 |
So this, which is maybe even conceptually simpler, I'm going to get rid of and go back to the more complicated thing. Meanwhile, let's see. I'll just set a good example by @1170 putting a high pass filter there and this, we might need this later. OK. |
es: @1170 |
So what we're going to do to start with is just listen to a nice sample: [tone]. It's just me saying "Oh" @1185 because I can't sing. This is about G [plays G on piano], just by accident. OK, so that's what's in this file. And now what I want to do is say "OK, that was a nice G, but I |
es: @1185 |
@1200 want to hear an A." [plays A on piano]. All right. Question: How do you get from G to A? Well, you transpose. How do you transpose? |
es: @1200 |
OK, choice! @1215 So we know basically how to transpose. We know that rather than do this, we should do this <<change the time parameter to line~ >> : [tone] We should do it in approximately 12 percent less than this; it's going to be 1850-ish. |
es: @1215 |
@1230 [tone] . No! Bad, bad, bad, bad, bad. I'm trying to do math in my head and not doing it well. [tone pairs] |
es: @1230 |
@1245 There is maybe a major second for you; it's not really exact. OK. |
es: @1245 |
A major second, OK, you learn this in acoustics, a minor second is six percent. It's actually 1.059 to 1. (That's the twelfth root of 2, @1260 which I use every day.) [laughter] And what I was trying to do here was divide by (the square of the twelfth root of two), which I didn't quite get. I finally just did it by ear. |
es: @1260 |
So here's the original sound [tone] -- That's G. This one, if I did it right, would be an A. [tone] @1275 Sorry about the bad singing. |
es: @1275 |
All right. So what's happening is I could have changed this value of 100,000. I could, say, just go, whatever, 12 percent further than 100,000 in that amount of time. But then when @1290 I started making extreme transformations down I might not get to the end of the table and so I might not like that so much. |
es: @1290 |
So instead, it's easier to, say, go to a place that I know is beyond the end of the table. In fact, when I'm doing this for myself, @1305 I usually take this into millions so that it's beyond any table that I would be likely to use. And then, compute the amount of time that you really should do that in in milliseconds. All right. |
es: @1305 |
@1320 There are a couple of ways you could do that. I could either do this explicitly with logarithms. Or I could do it the less brainy way, which is I could reach for mtof and operate that way. |
es: @1320 |
So I'll do that @1335 because that's easier to think about. Or rather, I don't know, I find this easier to think about. Maybe you will, too. So here is how you do this: |
es: @1335 |
@1350 So mtof "midi to frequency" is a thing which allows you to take a number, which is a frequency ... -- |
es: @1350 |
@1365 This is a number in MIDI and it converts it into a frequency. So for instance, if I feed it 60, I find the number of hertz in middle C. If I feed it 61, I'll be |
es: @1365 |
@1380 six percent faster, and so on like that. |
es: @1380 |
And now I'm realizing -- I'm trying to be as simple as possible. So I'm going to go back on my earlier promise to do this correctly in order @1395 to do it more simply in the following way: So what I'm going to do is say, "OK, we're going to go to 100,000 in 2268 milliseconds, all right. ..." |
es: @1395 |
" ... Except that my value of 100,000 is going to be different." @1410 I want to fix it so that when I say 60, it will be 100,000 all right. But if I say 61, it will be six percent more and so on like that. OK. |
es: @1410 |
How do I do that? Well, it's easy. I just change 261.6... @1425 whatever it is to 100,000. To do that -- it's a rescaling -- a simple-minded way of doing it is just divide by what it was and multiply it by what you want it to be. |
es: @1425 |
This is the other number I use every day, the number of @1440 hertz in middle C. And then you can multiply by 100,000. And then, I'm going to, why don't I set a good example and leave this network here. <<saving "3.sampling.transpose.pd">> |
es: @1440 |
@1455 All right, so I'm going to reach for this trigger. |
es: @1455 |
@1470 This trigger gives me a value, which goes here. And then it gives me the... I'm going to stick this in here. And what I want it to do is I want it to say zero. And then I want it to say this value packed |
es: @1470 |
@1485 with the amount of time which is 2268. |
es: @1485 |
So, lose all this. I think I want the print object still. ...@1500 Let's see, what's a good... And here I just want a bang <<now is "trigger float bang">>. Don't need this anymore. So, in fact, it would be better if I put all this in one place. There. |
es: @1500 |
@1515 Right. So, when I get a bang, I want to go to the value zero -- that's the |
es: @1515 |
@1530 beginning of the table. And then afterward I'm going to pack the amount of time, which will replace zero with the wonderful amount of time, 2268, this is all well and ... |
es: @1530 |
@1545 now, G: [tone; and tones at various successive keys] |
es: @1545 |
@1560 [laughter] Student: I'm lost. I'm lost with the bang. I got how you're setting and transposing, but why the bang? |
es: @1560 |
Miller: @1575 OK, let me answer that first, because that's specific, and then I'll try to answer. "I'm lost," which is more general. So, the specific question is, why would you put a bang on here, and float out here. OK, so this is a message box, |
es: @1575 |
@1590 which will put out 0, no matter what goes in. So, in fact, I could have put in a bang, or a floating point number, or a list of numbers -- or anything -- and out would have come the message "0". |
es: @1590 |
I put bang here as a matter of @1605 style, because I didn't want to put float, because it was just going to be ignored anyway. And so, it was simpler to think of it just as being bang. So, bang is just a message that doesn't have any numerical value associated with it. |
es: @1605 |
@1620 It's the equivalent of the keyword "void" in C. So, what happens is, whenever I say a number here, [tones] sorry... whenever I say a number here, stuff happens. ( |
es: @1620 |
@1635 Which is why I should print this number out. I should display this for you, so you can enjoy it.) 60 again. |
es: @1635 |
Sorry. And the width will be seven, it might be a big number. Tada. Ooh. @1650 Truncation error. You won't hear that. All right. So, stuff happens, and this number comes out -- 100,000 -- which is the number of samples ... which is the number I want to put here. |
es: @1650 |
@1665 Oh, yes. Right, I need my print object again. So, now, this print object is showing us exactly what's happening to the line~. Let's get rid of |
es: @1665 |
@1680 all of this. We've got this in the previous patch; it's not doing anything right now. All right. So, 60 went in here, and it got converted, it got turned into |
es: @1680 |
@1695 100,000 and then trigger says "first, send a bang to here," which outputs the message zero, which causes line~ to jump to zero, which causes tabread~ to read the first element. |
es: @1695 |
Then, @1710 this gets the number 100,000 because I asked for a floating point number, which is just a number. So, this is now the message 100002 (sorry about the two), and then we pack that wigh 2268, |
es: @1710 |
@1725 and so then what we see is the message, which is 100000, 2268 . So this pair of messages got printed out, I think. |
es: @1725 |
@1740 Oh, I see. Maybe I don't... maybe I connected the print afterward. So... It gets two messages: It's "0," and then "100000 2268". |
es: @1740 |
Student: @1755 So basically, this time, we're transposing by... instead of changing the amount of seconds it takes with the line~ object, by changing the amount of samples? |
es: @1755 |
Miller: Right. And the reason I did that, was because @1770 it made the math simpler, not because it made the patch better. Yeah? Student: Is there a samples per second, kind of like, M2F kind of thing? You just kind of bypass the math? Miller: No. |
es: @1770 |
@1785 No, there isn't. Basically, there are no primitives that would make this easier, although I could tell you how to make it a little bit more complicated. |
es: @1785 |
@1800 So, now there are two things to understand, I guess: One is, the bit that, this bit here, the stuff that's actually making the sound, which is to say sequencing two messages for the line~, and making the sampler read. |
es: @1800 |
@1815 The other thing to understand is how on earth I'm computing this value. So this is the value that you have to stick here, in order to get the right transposition. |
es: @1815 |
@1830 And now, to answer your question a little bit better, I want this value to be proportional to this value, and not in proportion to its inverse. I didn't want to have to divide by something. It could, but it would be more work. |
es: @1830 |
@1845 Student: How do you get the 100,002 again? |
es: @1845 |
Miller: OK. Well, it got it for me. What I did was I said I want 60 to go to 100,000. So, this is... So, now what you're asking is what is the design of this @1860 collection of objects. There really are only three objects here that are doing stuff. There's the midi-to-frequency <<mtof>> and then there's a rescaling, which is these two objects: We divide by the number of Hertz in middle C, and we multiply by 100000. So, |
es: @1860 |
@1875 what is happening here is we know that these numbers coming up have the correct proportions, so that we can do musical scales or musical intervals. Why, because mtof, if I, for instance, add 12 to the value here. |
es: @1875 |
@1890 [tones] <<12 steps for octave, doubles frequency>> |
es: @1890 |
Miller: It multiplies its result by two. All right? So mtof is the thing which takes 12 steps and turns it into "multiplied by two" in Hertz. @1905 Or, if you like, it takes the keys of a piano and converts them to Hertz. So that you move up 12 keys on the piano and it doubles the value. |
es: @1905 |
Now that we have the ability to do that... And that's just this object @1920 which does the math for us that does that. It's not so bad, it's -- I can tell you the expression. It's just an exponentiation, except it's scaled correctly. Then, what we say is "OK, I want those proportions. That's to say I want 72 |
es: @1920 |
@1935 to be twice what 60 is. I want 48 to be a half of what 60 is," and so on like that. |
es: @1935 |
But, anyway, I want 60 to give me 100,000. So how do I do that? I just have to multiply by the number, which is 100,000 over 261.62. @1950 Well, that's kind of... Ah, what's the right word? I could do that. I could divide 100,000 by 261.62; but I've found it more pedagogically transparent, hopefully, |
es: @1950 |
@1965 to use two objects so that I divide by 261.62 to get a transposition. And then multiply by this because I want a transposition of 1 to give me a value of 100,000. |
es: @1965 |
@1980 So, in fact, I should have been showing you two numbers. First off, this number is the interval from 60. So if I get 60... [tone] I .. get 1.0 there. If I really did it right. -- |
es: @1980 |
@1995 I think this is 261.626. Those twos are getting my goat. [tone] |
es: @1995 |
Miller: This is as close as I'll get -- Now we're within a part per million or so. A couple parts per million. So we divide by 261.626. @2010 That's just so that 60 gives us 1. And, by the way, now we're in floating point land. You're never going to represent this value exactly. It's irrational anyway. So instead, we just get as close as we can in floating point land to it. |
es: @2010 |
@2025 So now 60 goes to 1. So 72 will go to 2, for instance.[tone] ; 84 would go to 4; 96 would go to 8; |
es: @2025 |
@2040 And so on, like that. 48 goes to a half. Miller: And then harder values. There was 60 again, which goes to 1. |
es: @2040 |
Miller: Go up a fifth and you go to 67, which is MIDI for @2055 G above Middle C, and that turns into roughly 1.5 [tone] Miller: ...because seven semitones is roughly a factor, a multiple of 1.5 to 1 -- but not exactly. [laughter] Miller: Yeah? |
es: @2055 |
Student: @2070 If you go too low, though, it's going to start flipping like this. You don't have enough samples? |
es: @2070 |
Miller: @2085 Well, it'll just stop after two seconds, even if it doesn't get to the end of the sample. So if I say, yeah, do 24. [tone] Miller: Stops after two seconds. Oh! It stops at... Student: While you heard it, it was like tut-tut-tut-tut-tut... |
es: @2085 |
Miller: Right. This is now - what is that? Three octaves below Middle C? So I was droning along at 100 Hertz, and you divide that @2100 by eight and you get about 12, which is an audible rate. [sound playing] |
es: @2100 |
Miller: Maybe that's 12 Hertz-ish. Oh, and so that's one-eighth transposition, @2115 down by a factor of eight. And an eighth of 100,000 is this number, which is the amount we go in the table, which only gets us to about here. Somewhere in there. And it takes that 2.2 seconds to do it, but it originally it would |
es: @2115 |
@2130 have taken 100,000 samples. Student: So it's not playing the whole clip? It's only playing a portion of the clip? Miller: Yeah. Student: So you're not really transposing. Transposing would be playing the whole thing, but in a different key or in a different frequency. |
es: @2130 |
Miller: Yeah. So it's transposing it, @2145 but then it's cutting the transposition off after two seconds. Student: So if you would have to ... |
es: @2145 |
Miller: Yeah. I could have done it the other way, which is I could have said, "Go to the end of the table and compute the amount of time that you do." But then I would have had to divide by this number, which would have been an extra trigger object. @2160 I didn't want to make it any more complicated than it already is. ... Yeah? Student: When you're multiplying by 100,000, what is that number representing an amount of? |
es: @2160 |
Miller: So that's the @2175 number of samples at... OK. If you were at unit transposition -- that's to say, if you were playing the original sound back -- that is the number of samples that you would play in 2,268 milliseconds. |
es: @2175 |
@2190 So the value of 100,000 is, in fact, arbitrary. I chose that in some other context two days ago, and now I'm just sticking with that value because I happen to know that 100,000 |
es: @2190 |
@2205 samples at 44 Kilohertz corresponds to this number of milliseconds. Student: Which is a little more than two seconds. Miller: A bit over, yeah. Somewhat over two seconds. |
es: @2205 |
Student: @2220 Can you review tabread4~? |
es: @2220 |
Miller: Yeah, OK. So tabread4~ is a... Let's see, so it's doing a read into the array whose name is t1.27a, @2235 which is over here. And what goes in are the x-values, that's to say where you want to be in the array. And it is in samples. And what comes out is just what value is in |
es: @2235 |
@2250 the array there, which is the vertical axis in this graph. ... Yeah? Student: Is it possible to do a transposition without the time stretch? |
es: @2250 |
Miller: Well, @2265 yeah. It's more work. But, actually, you all ready sort of heard it because what I showed you in the previous patch, I was able to do little bits of samples in the table, you heard it going backwards and forwards, |
es: @2265 |
@2280 but it was ugly. So, to do that and make it pretty is actually hard. We might get there in a couple weeks or we might not, depending on whether it turns out to be a good use of our time. |
es: @2280 |
@2295 I'm not sure. ... Yeah? Student: Are there cases where you want to use tabread~ rather than tabread4~ ? |
es: @2295 |
Miller: Yes. The best example I know of is back in sequencer land. @2310 I think we go here ... "5.table.pitch" -- this one. |
es: @2310 |
@2325 All right: sampler![tone] . |
es: @2325 |
@2340 Now let's make this use tabread4~ [four tones] <<frequencies smoothed>> . Well, you could want that, but if you want it to sound like a classic synthesizer you really want tabread~. |
es: @2340 |
@2355 [asides] |
es: @2355 |
@2370 [asides] |
es: @2370 |
@2385 So, tabread4~ on the other hand, that's what you want to use if you want a clean audio sound |
es: @2385 |
@2400 of reading a sample out. Student: What is the "hip~ 3" object in the patch? |
es: @2400 |
@2415 "hip~" Yeah. -- "high pass filter." Let me show you, now that I'm in this context, one place where it's really good to have this. One thing that you can do is run off the end of the table, |
es: @2415 |
@2430 so let's go back to playing the original transposition [tone] . Now I have a rather bad thing because, if I disconnect this -- |
es: @2430 |
@2445 you hear that click? Actually, I could make that worse. What's the first sample of the table? There it is. |
es: @2445 |
@2460 It's not that much worse. The reason that you hear that click is because tabread~ is constantly giving me the last value in the table. |
es: @2460 |
@2475 So, the line~, is giving me a 100,000 right now. Let's just verify this. We need a bang for this. |
es: @2475 |
@2490 So, look at that. We have a 100,000 (1 X 10^5) coming out of the line. That's appropriate because I |
es: @2490 |
asked it @2505 to go there in 2268 milliseconds. Then we say tabread4~ and it says "OK. That's fine", and I'm going to give you 0.03... blah, blah, blah -- this amount. |
es: @2505 |
@2520 (That's the value of the table in it's location that corresponds to 99,999, which is the last point on the table.) |
es: @2520 |
And that, when you disconnect it or connect it, sounds like a click because it goes between @2535 that and zero. So, how do we get rid of this? We say "hip~ 3". |
es: @2535 |
@2550 The "3" is just a good number which is well under 20 -- which is the bottom limit of human hearing, luckily. Print tilde here said these numbers, |
es: @2550 |
@2565 and then if I talk to hip~ tilde I get these numbers which are much, much smaller. They're down to truncation error. It might even be turning into a zero? ... No, it won't go below that. |
es: @2565 |
@2580 So, the high pass filter essentially cleaned up the DC value, the constant value of .03 that we had before, as a result of which, I can now disconnect it and connect it without |
es: @2580 |
@2595 hearing it. Although I haven't told you about hip~ I systematically put a 3 Hertz, high pass filter |
es: @2595 |
@2610 in front of the digital to analog converter and before and after the analog to digital converter, every time I make a patch it's going to deal with audio. If my patch is going to drive a DC motor I don't do it, but |
es: @2610 |
@2625 that doesn't happen very often. Almost always I have "hip~ 3" somewhere in the signal path. |
es: @2625 |
Student: @2640 I was going to ask what the "3" coresponded to, but it's 3 Hertz? Miller: It's three Hertz. What that means is it's way below 20 hertz, so far below 20 hertz that by the time 20 hertz happens, we're so far away from the filter's roll off that it's not transmitting a signal. Engineers use values up to about 10 for that. It's a low cut-off. |
es: @2640 |
Student: @2655 But if we can't hear it, then what's the point of it? |
es: @2655 |
Miller: Well, a point of it is if I had a bunch of these voices, and they were all stopped in the same way, but if their outputs all added up @2670 to something more than one -- not only would I not hear anything, but even if I played a sound out in some other part of the patch, I wouldn't hear it because everything would be above the output max of the digital-to-analog converter. |
es: @2670 |
@2685 Here's a thing you might not want to do-- it's good review. Can we get a toggle and then make a metronome? |
es: @2685 |
@2700 Sorry about this: I'm going to make something that will annoy you. Out will come MIDI 60 [tone] , twice a second. |
es: @2700 |
Now that's really annoying -- We're not going to do that. @2715 Oh, and we don't need this print anymore. [beat track sound] OK? So, we know what's coming out of this thing.[laughter] |
es: @2715 |
Miller: Now what I'm going to do is show you how to make it hurt. I'm going to do another one of these. I'm not going to even remember @2730 to connect anything to it, but I'm going to connect it with a bad volume. Now I'm going to start annoying you again. [tones] |
es: @2730 |
Miller: @2745 That is |
es: @2745 |
@2760 the sound of my sample getting shoved up against the very top of the possible output range of my converter hardware. It's always called distortion, |
es: @2760 |
@2775 but sometimes this is called a bias. This is a knob on your expensive guitar amplifier, expensive tube amp. It does that to the guitar sound. Student: How does that relate to the high pass frequency filter? |
es: @2775 |
Miller: @2790 Oh, OK. So, I might have done this by accident, somehow, but if, [tones] on the other hand, I had a high-pass filter there, |
es: @2790 |
@2805 then I can give this as much bias as I want, and it filters it out. |
es: @2805 |
@2820 It's gone, so I can still hear this thing going. |
es: @2820 |
What happened there was this thing is putting out 0.06 V. So, this is now putting out @2835 60 V, too much for my hardware. But this <<hip~ 3>> is taking the DC out of it, which is therefore returning it to zero, because everything that's happening here is DC. It's flat-lined; it's not changing with time. |
es: @2835 |
Student: @2850 When you're increasing the bias, is the speaker cone also going out towards its maximum travel? |
es: @2850 |
Miller: It should be, except that I have faith in the cheapness of the mixing hardware @2865 that we have here, and it's almost certainly AC coupled, so that, in fact, there is an implied hip~ somewhere in the hardware. Student: OK. |
es: @2865 |
Miller: Otherwise I could actually literally push the speaker out its cone. Well, probably the amplifier wouldn't allow me @2880 to do that anyway, but it would be bad because DC speakers' resistance goes down, and so you can actually burn your speaker out if it would actually send that voltage to the speakers. |
es: @2880 |
I have long experience with this brand of mixer because @2895 I'm cheap too. I know that it won't actually do that to me, neither will your home stereo. It's more expensive to build DC-coupled stuff. ... Yeah? |
es: @2895 |
Student: Is it possible to write your own objects, like the mtof? ... @2910 Someone was saying before about the samples-to-frequency, because that's just a simple conversion? |
es: @2910 |
Miller: Sure. Yeah, it's just an arithmetic expression. You could just make an object that does it. That is the subject, or a subject among others, @2925 of Tom Erbe's seminar that he gives in the Fall on Programming for Musical Applications. Although, you can just sort of learn how to do it. Just go find a pd object that someone's written, see how it's done by example, and just go from there. |
es: @2925 |
@2940 There are some thousands of them on the web. ... Any questions? |
es: @2940 |
OK. @2955 So, what happened was two things that were kind of jumbled together. One is this high-pass filtering notion, which is a good way of dealing with DC offset problems in signals -- |
es: @2955 |
@2970 Which will come in. (This is one good way of making yourself a DC offset without wanting to-- having a sampler and just have it stuck in a location in the sample; but there are many others.) |
es: @2970 |
In particular, if I, for instance, just say "Give me an oscillator," @2985 it now has a phase of zero because it starts at the top of the cycle. It's putting out "1" constantly. If I put that out my dac~, |
es: @2985 |
@3000 that will mess up the sound of the rest of the patch. |
es: @3000 |
Frequency modulation and wave shaping-- I've shown you frequency modulation, although I need to show it to you again more controllably-- they have a tendency to have @3015 DC as part of their spectrum. It's not the only thing they put out, but they will put out some DC as well as everything else. As a result, if you are playing them, you probably want to put one of these things <<hip~ 3>>x in the chain somewhere. |
es: @3015 |
@3030 So that's this object and then the other thing was this way of talking about transposition of samples. Done in a way that hopefully is as simple as possible which is to say |
es: @3030 |
@3045 that you first get yourself from pitch to frequency and then correct. So that its in the range that you want which is 100,000 corresponds to no transposition. And the reason I've decided that 60 should correspond to no transposition is just because that's a habit: |
es: @3045 |
@3060 Middle C by default is no transposition on a sample. And 60 is the MIDI value for Middle C. Questions about this? ... Yeah? |
es: @3060 |
Student: @3075 Is there a way to change the slope of the filter. |
es: @3075 |
Miller: @3090 Slope? OK. In this particular filter is the most simple minded well second most simple minded filter in the world and the only thing you can change is the cut-off point. It always has a 3 dB per octave roll off. |
es: @3090 |
@3105 So it's the cheapest, simplest possible low cut filter you can get. You can get better ones but then you land in a region where there are actually thousands of designs of filters. There are at least dozens of them available in Pd. |
es: @3105 |
@3120 And you would have to spend some time figuring out what characteristics you wanted. I wouldn't be able to just give you a quick answer. |
es: @3120 |
Other questions about that? OK. So what I want to do now is @3135 first off mention that of course this was playing the entire sample but you can play bits of samples as well. |
es: @3135 |
And what I should do is start another window showing you an example of playing a bit @3150 of a sample. That will be interesting because it will make it much much more important to be able to control the clicks that naturally happen at the beginnings and ends of samples. So that should be kind of the next thing to worry about. |
es: @3150 |
OK. So what I'm going to do is "save as," @3165 going to hang on to this thing. And I thought it was before that but, four. <<saving "4.sampling.envelope.pd">> |
es: @3165 |
@3180 I won't get too far but I'll start it anyway to do enveloping the sampl. The first thing I want to do is say, OK rather than making 100,000 I want to make ... |
es: @3180 |
@3195 no, lets do 10,000 points. And lets do it in this amount of time. See how this sounds. [tones] Pretty good. |
es: @3195 |
@3210 I should say here that this is not a good practice. I'm taking a very short amount of time here and time is quantized. |
es: @3210 |
@3225 Rather I should say line~ has a quantization in its actions which is 64 samples. So this is not a terribly accurate way to make a sampler because this will be quantized to about 1 1/2 which would be noticeably out of tune if we're actually being careful about it. |
es: @3225 |
@3240 So this is just going to be a bad example right now because I just want to show you an envelope. |
es: @3240 |
That is that: The problem is that it clicks every time you use it. @3255 And we would like it not to do that. So how do we deal with that? In the usual obvious way, you multiply it by a line~. And the thing that you multiply by is the output of a tabread4~. |
es: @3255 |
Student: @3270 I thought you were high pass filtering that? |
es: @3270 |
Oh I am high pass filtering that @3285 but I'm changing the value I put into to the high filter which gets us to the step function which we still hear -- although then it takes it out. Anyway, let's get rid of this and let's multiply it by a line~. And now there will be two line~'s running around. And so there |
es: @3285 |
@3300 will be plenty of opportunity to get confused. The first one, let's see ... |
es: @3300 |
... @3315 This one now what were going to do is were going to say you are at 0 please and lets go up to a value of 1 and do it in a certain amount of time. Which will be 50 milliseconds. |
es: @3315 |
@3330 And then after a certain delay we can turn it back off. |
es: @3330 |
@3345 And now I get something which allows me to put values in here: |
es: @3345 |
@3360 Whoa?! What did I just do... I didn't want it to do that -- Send this to zero: [tones] Ah, no clicks! |
es: @3360 |
So before it was this [tones] @3375 and after is this [tones]. All right. OK. Now who can tell me why this will stop working, |
es: @3375 |
@3390 the next thing I do? I'm going to do scroll on this thing and it's going to make my clicks after all. Anyway. And why does that happen? |
es: @3390 |
Student: @3405 You're going faster than the delay? |
es: @3405 |
Miller: Yeah. I'm not waiting for this, I'm not waiting for the end of a note before I start another one. So let me back up, and carefully explain what's happening. What's happening is, we're starting the tabread~ and we're giving it two messages which tell it to jump to a point and then to slide to another point. @3420 At the same time we're doing that, we're muting this line: We're making it jump to 0; and then we're ramping it up to 1 in 50 milliseconds. And then, a 100 milliseconds later, we ramp it back down to zero. So that it's safely back down, before the end of this segment. |
es: @3420 |
@3435 So the thing goes up. It sits there at it's apex for 50 milliseconds because we started it but then a 100 milliseconds later, we started sending it back down. But meanwhile, if I don't wait that whole |
es: @3435 |
@3450 150 milliseconds before I send another message. [modulating sounds] It will bash the value zero discontinuously, and that will sound like a click. So, actually, it's a little harder than this. |
es: @3450 |
@3465 What you really should do is ... What you really should do -- |
es: @3465 |
@3480 I'm thinking of a simple way to explain this. |
es: @3480 |
First off, what we have to do is remember the value we want. Because @3495 we are not going to be able to use it immediately. So we're going to take the value and stick it in a nice F-box. Like this. That's step one. At the same |
es: @3495 |
@3510 time as that, we will mute the value of the line~. What that means is that we will send it down to zero, and do it very quickly. And now I will go ahead and do bad style and |
es: @3510 |
@3525 just send the floating point number straight into the message box. OK. Then we will start a delay of five milliseconds. |
es: @3525 |
@3540 After which, we do the rest of it using the floating point value. Like that. Now I have to clean this up. |
es: @3540 |
@3555 I don't think we need that zero anymore, because we already did that. OK. So now, what's happening? You know what? Let me make it a little bit better style |
es: @3555 |
@3570 and put it back in. So that you can see it all in order. So, first thing, first step is to mute the thing. So whatever is happening |
es: @3570 |
@3585 when I ask it to play a new voice it doesn't do anything except mute the old one. Because it might be playing something and the new one is going to start at zero. And if we don't then ramp it to zero, we're going to hear a click because it will jump to zero. |
es: @3585 |
So, we spend five milliseconds @3600 covering up for ourselves by muting whatever was happening previously. And then; and by the way, the next thing to do is take the floating point number and store it because five milliseconds later, we're going to need it. |
es: @3600 |
@3615 And five milliseconds later -- "del" is short for delay -- five milliseconds later we will get the value out of the float and then we will do the previous thing, which is bang this to turn the line on and do all this choreography for this line. |
es: @3615 |
@3630 Now if we do that we have: [sound notes changing without clicks] Not perfect, but it's at least decreased. All right? |
es: @3630 |
@3645 Now let me move this down so you can actually see where the lines are going. |
es: @3645 |
@3660 So, this is now an almost complete and almost acceptable sampler. In the sense that I can throw pitches at it and it will play samples back. [sound of sample] And this is...Yeah? |
es: @3660 |
Student: @3675 In your "trigger bang float bang" is the float doing anything, or...? |
es: @3675 |
Miller: Yeah this float corresponds to this outlet, and it is being remembered. ... @3690 So the "float" object - I think this showed up last Tuesday. This is an object which remembers values and then when you give a bang which, the delay will put out, it restores the value. Student: OK. |
es: @3690 |
Miller: @3705 There are other ways to cause a number to get delayed. But in general, when you want to do something after a certain amount of time and have the thing that you had before, you have to store it. |
es: @3705 |
@3720 So this is may be conceptually the simplest way of doing it. Now the next thing that you might want to do is: gee we got a sampler, let's make it a |
es: @3720 |
@3735 100-voice polyphonic. So lets just copy and paste this thing a hundred times? .... No, you want to do something different. |
es: @3735 |
So that's coming. But actually I think what's going to have to happen next time is more careful @3750 talk about envelopes, and pitches, and transpositions, and stuff like that. Because I'm sure there are a whole lot of misconceptions to clear up. |
es: @3750 |
So this is using line~ and messages, as opposed to using a phasor to loop through a sampler. @3765 I didn't even show you how to de-clicks sampler that are operating from phasors. There's a totally different strategy for doing that. |
es: @3765 |