Building a Dynamic Sampler Plugin in Plugdata - Part1
Tutorial | Sep 08, 2023
In this video, I demonstrate how to use Pure Data as a plugin inside Bitwig. I explain the process of recording and sampling audio into an array, manipulating the playback speed, and adding fade-in and fade-out effects. By understanding these techniques, viewers can explore creating their own plugins or prototype their own audio projects.
You can watch the Video on Youtube - support me on Patreon
More Videos in this Series #
Questions & Answers #
Maybe you dont watch the video, here are some important takeaways:
What is the video about? #
The video is about using Pure Data as a plugin inside of Bitwig Studio, instead of using the Grid or Bitwig's built-in features. It introduces Pure Data and demonstrates how to create a basic patch for sampling and processing audio.
What are the benefits of learning Pure Data? #
Learning Pure Data can be beneficial for those interested in creating their own plugins or prototyping audio effects. It provides a fun and exploratory way of working with audio and can be applied to various modular environments and coding practices.
How does the patch work? #
The patch utilizes modules such as ADC and DAC to bring audio signals into and out of Pure Data. It uses an array to store and playback the sampled audio, and modules like the phaser and vline for processing and controlling playback. The patch also incorporates elements like fade-ins, fade-outs, and dry/wet mixing for further customization.
What are some potential applications of this knowledge? #
The knowledge gained from this video can be applied to creating custom audio effects, manipulating audio recordings, or experimenting with granular delays. The concepts and techniques demonstrated in the patch can serve as a foundation for further exploration and creation in Pure Data and other audio software.
Transcription #
This is what im talking about in this video. The text is transcribed by AI, so it might not be perfect. If you find any mistakes, please let me know.
You can also click on the timestamps to jump to the right part of the video, which should be helpful.
[00:00:00] Hey folks in today's video. It's a bit bit special. I don't want to use the grid
[00:00:05] I don't want to use bitwig. I want to use pure data as
[00:00:09] In the form of black data. It's a plug-in inside of the door. It's completely free open source
[00:00:16] But stay with me. I try to keep it simple and fun
[00:00:18] And it's also beneficial to have this knowledge
[00:00:21] Maybe later on if you plan to create your own plug-ins or maybe for prototyping your rec stuff and so on
[00:00:29] But it's a fun way of doing things sometimes to explore this and
[00:00:33] Yeah, why not? So let's start here with
[00:00:37] With bitwig. I'm using basically here as an input some kind of piano
[00:00:43] Just basic stuff something we can sample in the plug data, maybe it's too quiet, huh?
[00:00:56] Okay, so after this plug in we use here plug data
[00:01:00] FX it's basically an FX VSC plug in and as I said, this is completely free and open source
[00:01:07] This is the nightly built here. Maybe not completely stable
[00:01:11] But I want to show you here the new additions to the interface we have here now on the left side some
[00:01:17] Some high-level modules bit crush our chorus delay drive flanger phaser
[00:01:24] Stuff like you want to use in a euro rec environment or maybe
[00:01:28] Reactor blocks or maybe the grid itself. So more like higher level stuff
[00:01:34] Need to have
[00:01:37] But this time we want to go deep and dirty and create a new patch here. This is how it looks like
[00:01:42] In here in this completely empty canvas
[00:01:46] We create a new module and this new module is created by double clicking on the empty space
[00:01:53] We get this input here. We type in a DC and it wants to complete to ADC tilde, which we accept with tap
[00:02:00] And it's return we can zoom in here by using control and mouse wheel just to zoom in a bit
[00:02:07] and this ADC is basically a
[00:02:11] digital audio converter bringing in
[00:02:14] Audio signals from the door and there's also another module double click here and use the AC and
[00:02:22] tilde and basically the still the means that this module operates at audio rate. That's important to know
[00:02:29] also this
[00:02:31] orange here these orange input jacks or output jacks mean basically we have here signals at audio rate and
[00:02:39] Blue is basically data just pure data
[00:02:42] Yeah pure data
[00:02:44] So the simplest connection we can do is basically here connecting the input left channel right channel with the output and
[00:02:51] Just pass through the audio
[00:02:53] But that's pretty boring so we want to process the audio so we just cut this here by selecting the wires and hit delete and
[00:03:02] We want to write this audio data inside of an recorder or sampler inside of pure data
[00:03:10] We have nothing like that. We have to use an array you can find this on top here
[00:03:14] Basically also you have the object browser is pretty new. We have some categories here
[00:03:19] Which is pretty neat, but most of the times you just need the top ones here the top
[00:03:23] Modules so use an array here by just clicking and dragging this out or we can use hotkey
[00:03:30] control shift and a
[00:03:32] But just drag this out. I
[00:03:34] Select here basically the array one and we can go to the inspector here and rename this to let's say sampler
[00:03:41] And then we have a size and the size is basically not the size of the visual
[00:03:48] Presentation here. It's more like the size of the arrays. We have 100 data points and you want to sample
[00:03:55] Two seconds of data. So when we go here to the settings of bitwig audio sample rate is
[00:04:01] 48,000 Hertz which means this is one second right we need 48,000
[00:04:08] Data points for just one second if we want to sample two seconds of data
[00:04:15] We have to go up to twice as much so 96, right? So I'm typing in here
[00:04:21] 96,000 data points. That's what we want to save. So exactly two seconds
[00:04:29] So we can see there are no input jacks here on the sampler now on the array
[00:04:35] So we have to use another module we double click here and use tap right
[00:04:41] There's a tilt also there which means we operate at audio rates. We hit tap and
[00:04:47] Now we need to insert a space and in my case here in bitwig captures for some reason the input
[00:04:54] So every time I press space here, I just you know hit play on the transport in bitwig
[00:04:59] So I need to use control and space to insert actually a space
[00:05:03] And now we want to insert here the name as it also says here symbol sets table name with the sample
[00:05:11] So we type in the array name which is sampler
[00:05:14] So sampler so we want to tap right data into the sampler easy
[00:05:20] And we take here the input
[00:05:23] left channel right channel
[00:05:26] Summit and put it into the sampler and you're right. This is mono
[00:05:30] If you want to have this in stereo you have to use two tap rights and two
[00:05:35] Arrays for the left and the right channel, but I want to keep it simple
[00:05:39] I just use one for the sake of this tutorial. That's just so you know just for info
[00:05:45] So if you right click on this here and use reference you can see we have your inlets one. There's only one inlet. It's one
[00:05:54] input jack basically
[00:05:57] But this one accepts two signals
[00:05:59] The first one is here a signal which is basically what we already have to input signal signal to write to an array
[00:06:06] That's the data. We want to write to the array
[00:06:09] the second one is a bang
[00:06:11] starts recording into the array and in pure data a bang is basically a trigger, but they call it bang for no reason
[00:06:19] So we can drag in here basically a bang button to bang it
[00:06:24] It's the terminology
[00:06:27] Sorry, so we connect you the output of this
[00:06:31] Also, you have the input so because we have here a bank signal and the audio signal the module can
[00:06:39] Distinguish between these two pretty easily so you can just use one input jack for some reason that that's how it works basically
[00:06:45] So with the bit the push of this button we can start the recording process
[00:06:51] But you can't push it at the moment
[00:06:53] Because we are in edit mode here at the top, right?
[00:06:57] So we have to go to run mode in run mode. You can't change these modules. You can't change
[00:07:02] Values, but you can interact with here
[00:07:06] With interface elements. So now we have to place something on the piano and we have to push record
[00:07:12] You can see it records until it reaches here the end of the array
[00:07:18] But you can't hear nothing because we need now to read
[00:07:24] Something out of the array and we can do this by using another module which is called of course tap read
[00:07:31] tilt and
[00:07:34] We also insert your space and the name of the array
[00:07:36] sampler
[00:07:38] And here to playback actually something from the array. It's not that easy as just attaching a bang to hit play and stop and so on
[00:07:47] This one wants to have some kind of positioning signal some kind of face signal
[00:07:53] So here it says signal sets table index and
[00:07:58] Output its value. It's weirdly word, but what it means basically you need to send in some kind of
[00:08:04] number and the number is then the
[00:08:07] Yet the position or the index and we have here as you remember
[00:08:11] 96,000 indexes basically
[00:08:15] So to do this over and over basically one index after the other so it is some kind of playback happening
[00:08:23] We can do this for instance like with a phaser
[00:08:27] And the phaser works exactly here also in the tilt version face ramp generator. So we hit the tab
[00:08:34] The phaser is basically something that generates a ramp and you can input here a frequency number and it
[00:08:40] outputs then basically this ramp at this frequency and I show you how this looks like here in a scope
[00:08:47] So we use the scope here. You can resize this a bit
[00:08:52] Output of the phaser goes in here and now we need the number
[00:08:56] or float
[00:08:58] float does it also and
[00:09:01] When we change now here the frequency or the input number the frequency changes of the phaser the ramp signal basically
[00:09:08] Gets longer or wider. You can see this in a moment, but I don't want to use here the
[00:09:13] The run mode for this
[00:09:15] I want to show you also that you can hold down control here if you hold down control you can see here some of these
[00:09:22] Elements become gray and when you hold down control you can interact with these knobs here
[00:09:28] Even you are still in edit mode
[00:09:31] So you don't need to switch to run mode all the time you can just quickly
[00:09:34] Dynamically switch to these run mode by holding down control. So now you can see we have your nine
[00:09:41] It's a frequency and the phaser generates here some kind of ramp signal all the time it outputs a ramp signal from zero to one
[00:09:50] Oh, one oh, it's basically some kind of LFO that operates between zero and one
[00:09:54] The problem now is
[00:09:57] That we don't need a signal between zero and one we need a signal between zero and
[00:10:03] 96,000 because we want to use this ramp signal to
[00:10:08] Scrap through the array
[00:10:11] That's that's what we want to do. Maybe I use here a different draw mode. Maybe I use here
[00:10:19] Polygon or something, yeah
[00:10:21] So I feel like this okay, so we want to scrub through the array buffer here with the phaser so
[00:10:29] We have to multiply basically the signal so we insert here a new module double-click use a
[00:10:37] Star which means multiply if you want to use this multiply also with the tilt version at audio rate. So we hit here
[00:10:47] Insert and now it gives us here basically a second input jack which is
[00:10:52] Kind of what we want to use to multiply the signal with so we want to use this signal and then we want to multiply it here with a different signal
[00:11:01] But the the second signal is basically not dynamic. I don't want to change it
[00:11:06] I want to keep it static so I can also input this here as a default value and the default value is
[00:11:12] 96,000
[00:11:17] The wrong
[00:11:19] Thing
[00:11:20] So we take basically this input signal
[00:11:23] Multiply it here with this number and then we get basically a signal between zero and this number
[00:11:30] Does it make sense because the output of the phasers between zero and one?
[00:11:33] Times this number and then you one instead of one we get basically this number
[00:11:39] So it's a ramp signal between zero and 96,000 so we can use this to go from here to here
[00:11:46] So we use this as an input for the tab read
[00:11:48] You can delete this here now. Oh
[00:11:51] We need this actually so
[00:11:53] And yeah, we scrub basically with this
[00:11:57] Through the sampler and this gives us already I think some output here. It's a bit too fast so we can slow it down
[00:12:10] So you can change the playback speed here with this frequency of the phaser
[00:12:14] Which then gets multiplied and then we use this as a positioning signal for the ray and then the ray outputs this here
[00:12:21] Like a sampler we can change the frequency and change the pitch
[00:12:25] And if you go negative
[00:12:28] It's actually backwards
[00:12:30] Right so we already have
[00:12:35] Some nice features to actually sample something and to we have some influence over
[00:12:40] The output of this plug in so so far. I think it's pretty simple, right? It's not that hard
[00:12:47] Audio in tap right. We trigger the writing here
[00:12:51] gets written into the array the race exactly two seconds long
[00:12:56] Then we have here a phaser the phasers multiplied by the length of the array
[00:13:02] And then we use this as a positioning signal to read the array and then the ray gets the values out into
[00:13:08] The door again and we basically have yeah a playback
[00:13:12] Pretty simple. I think so far
[00:13:15] So this is already a nice lesson you can try out with plug data and have some fun, but I want to I
[00:13:22] Don't want to show you more things, right? That's that's not all so we can also
[00:13:29] Delete this here because the phaser is is neat to play back audio at different rates
[00:13:35] It can be fun, but we want to actually also play this audio back in exactly the same
[00:13:41] Speed as we sampled it, right and you can this
[00:13:45] Make you can do this more easily by using a v-line for instance here
[00:13:53] V line basically generates also a ramp. It's in the reference here. It's also said it's a signal generator
[00:14:00] it accepts basically
[00:14:03] Target value and start ramp set next ramp time sets delay time. Okay, so we can input here basically a message
[00:14:13] Let me see
[00:14:18] Yeah, it inputs it need it needs some some some some float as input and we can do this here with a message
[00:14:25] We drag this in and into the message we write basically the start
[00:14:30] Position which is zero which is the start of the
[00:14:34] ramp and
[00:14:37] We hit here comma and then we insert basically the end point which is
[00:14:42] 96,000 and then we insert the space and then we want to insert here the
[00:14:48] Time the time frame of this so we want to have a ramp between zero and ninety six thousand in the time frame of
[00:14:56] 2000 milliseconds, which is one second or two seconds
[00:15:00] so we hit return
[00:15:02] Feed this here into the v-line and the v-line goes in the tap reader and the tap reader goes into the output and then we can hit control and
[00:15:09] play it back
[00:15:12] so control and
[00:15:14] Push and we play it back, but you can see we have here still some output right at the end of block data
[00:15:20] So something is wrong and the problem here is basically that we are stuck at the end of this array
[00:15:26] And we're using the last index the last value of this index as an output all the time nothing changes, right?
[00:15:33] And we can prevent this in multiple ways and I want to introduce here some kind of second v-line
[00:15:40] To have a fade in and a fade out at the end, okay?
[00:15:44] so we keep this here as it is and
[00:15:47] We use a second a
[00:15:50] Second v-line for the volume instead of the face and we use also here a second
[00:15:57] Message and this time we want to fade in so we go from zero which is zero volume
[00:16:05] Up to one which is the maximum volume over the time frame of 100 milliseconds and we go here into the v-line
[00:16:14] Okay, and then we want to introduce here a multiplication also the tilt version because it's all your rate and
[00:16:22] We want to use here this in between
[00:16:26] the output so we use your shift to
[00:16:29] sneak this in between and
[00:16:33] Discourse also here and the right channel
[00:16:35] So then the v-line goes in here. So this changes basically the volume some multiplication here
[00:16:42] With zero is basically zero volume. It's completely quiet and one is the maximum value
[00:16:49] So the v-line also goes from let's trigger this here as a slow ramp basically
[00:16:54] You can see this here. It's goes slowly up from zero up to one
[00:16:59] So that's something we want to trigger every time we hit play and we can do this
[00:17:04] by just
[00:17:07] Using doing like this. So when I push this, this is also a trick out or we can do something like
[00:17:13] Use a bang here and we can call this for instance with the comment. We can call this
[00:17:20] Playback
[00:17:24] right
[00:17:26] And this one triggers here this message and it also triggers this message and we trigger basically two v-lines at the same time
[00:17:34] one is for the face signal and one is for the volume fade or for the fade in
[00:17:39] So now we have a fade in but we also need to fade out at the end. So how do we do this?
[00:17:45] We actually duplicate here this message and we go also here
[00:17:51] with this node or with this
[00:17:55] wire here in the first input jack and
[00:17:59] This one here is then a fade out. So the fade out is going for maximum volume
[00:18:05] Which is one down to zero volume, which is zero over the time frame of 100 milliseconds. It's perfect
[00:18:12] So so so we need to trigger this here at a certain point in time and the exact time frame is basically
[00:18:20] This is 2000 milliseconds
[00:18:23] And you want to trigger basically 100 milliseconds earlier like here. So it's enough time to fade out
[00:18:30] so we insert here a delay and
[00:18:34] the delay is
[00:18:37] 1900 so it's basically
[00:18:41] 2000 minus 100 so we have like this and we trigger this here also with the play button. So maybe
[00:18:49] Let's move this down here
[00:18:53] So when we trigger this here, we start the playback we start to fade in and then after
[00:18:59] 1900 or 1900 that's how it's called in UK. I think 1900
[00:19:04] milliseconds
[00:19:07] You trigger the fade out and then after 100 milliseconds basically we are stuck at the end here
[00:19:13] So this should work in my opinion
[00:19:15] Right, so we have a fade in then we play back everything and
[00:19:22] Exactly 100 milliseconds before the end we fade out and then we have a nice
[00:19:27] ramp in ramp out no clicking no popping and
[00:19:32] You also are not stuck at the end here with the last sample value. So pretty easy
[00:19:38] I hope this is clear so far what I did here
[00:19:41] Actually, it's nothing changed as before instead of the face of using here the v-line and the v-line
[00:19:48] Except here basically this nice little message format where you start at the value end up on a value and then you type in the milliseconds
[00:19:57] For the time frame for the v-line and then the v-line
[00:20:01] Processes this and actually produces some kind of ramp signal
[00:20:05] So pretty neat actually
[00:20:08] So what we can do now is we can first instead of going from zero to the maximum value
[00:20:15] We go from the maximum value down to zero which gives us
[00:20:20] Kind of reverse playback. So let's try this
[00:20:25] Okay
[00:20:30] This works nice and then I don't want to push this button all the time
[00:20:34] I want to have this trigger for for me, right automatically. So
[00:20:39] Let's move this down here a bit
[00:20:43] And let's use another module called
[00:20:46] Metro or metronome sense a message periodically. It's exactly what we need
[00:20:52] so we use this here
[00:20:55] Connect here this with our with the output input to the bang and
[00:20:59] We also use here another bang or maybe we just remove remove this here
[00:21:07] Push this here in and then use a use a bang here
[00:21:12] Connect this call this playback
[00:21:19] And
[00:21:22] Then we can use here a second input and the second input takes
[00:21:26] basically a
[00:21:28] number and the number is also milliseconds for
[00:21:31] Yeah, let's say
[00:21:35] The distance between the banks
[00:21:37] So we connect this here
[00:21:42] And we type in
[00:21:44] 2000 okay
[00:21:47] So the distance between two banks is exactly the time we need to play back this whole array buffer
[00:21:53] I hope this makes sense and
[00:21:56] If you look up here the reference for the metro
[00:21:59] Or for the metro norm it also accepts here a method a message stop stop the metro norm
[00:22:05] That's also what we need to implement. So we use a message here
[00:22:10] type in stop and
[00:22:12] We put this also in here
[00:22:15] Okay, so we can push this to start push this to stop and between the banks we have exactly
[00:22:26] 2000 milliseconds
[00:22:28] Which we use then to play back this thing every two seconds. Okay, so let's try this out
[00:22:36] To us it doesn't work fantastic and that's because we also need to trigger the fade in here and the fade out
[00:22:43] So we have a start button we have an stop button we have
[00:22:54] Fade in we have a fade out we can record here
[00:22:59] So what we want to do now is probably also to record all the time
[00:23:05] So it's more like a
[00:23:07] granular delay or something like this. I don't know how to call it
[00:23:11] So we can just use the output of the metronome and feed it back into the sampler bank here to sample every time we play back
[00:23:19] Maybe it doesn't work. Let's see
[00:23:22] and push
[00:23:25] Push record here and play something
[00:23:27] So it looks like it works
[00:23:40] The problem now is we only hear basically the process signal that's coming from the array
[00:23:46] Maybe it's also interesting to also hear the dry
[00:23:50] input
[00:23:53] And mix it blended with a wet signal kind of
[00:23:56] So we can do this by using a second
[00:23:59] Output here deck can also use just this one here but for the sake of the
[00:24:07] For the visual clutter. I just use a second one and then we can
[00:24:13] Maybe also use here a second input
[00:24:21] And let's use here for that a multiply. Yeah, let's go with the multiply also the tilt one
[00:24:30] And to use this for the left channel
[00:24:34] Duplicates, I don't know why it's
[00:24:38] Doing this here. Let's do it this way
[00:24:42] Put this in
[00:24:48] And now we can use maybe a knob or a slider depends on what you want to use I use here a knob
[00:24:55] And the knob is a range between zero and 127. That's not what we need. We need
[00:25:02] Maximum value of one so one is like like here the volume zero is no volume or no gain at all and one is the maximum gain
[00:25:13] It's the same here. So we have a value between zero and one we can use this directly as an input here for the multiplies
[00:25:20] It can basically change how loud the dry signal is
[00:25:25] Um, you can also input here a comment
[00:25:31] Another object
[00:25:34] I want to insert a comment this one
[00:25:39] Let's go try signal or level actually it's a try level
[00:25:44] And yeah, let's use this
[00:25:49] Um
[00:25:51] Nice
[00:26:13] so instead of
[00:26:15] Using a try level or additionally we can also just duplicate this here and do the same thing basically for
[00:26:22] Um for the left and right channel here down here
[00:26:28] Like this
[00:26:32] And say this is the wet level
[00:26:39] So
[00:26:41] And then can put this maybe on different positions here up here
[00:26:50] Something like this presentation mode. Hmm
[00:27:07] That's a good but it kind of works
[00:27:10] So
[00:27:12] So
[00:27:41] There's still some clicks and pops in there maybe I have to increase here the delay times
[00:27:47] Maybe 200 here
[00:27:51] Make it more soft. I have no idea
[00:27:54] Maybe I do something wrong. Um, so here I go for 800
[00:28:02] So
[00:28:04] It's at least
[00:28:19] In parts smooth
[00:28:21] So, yeah, I want to give you basically an idea how you do something in plug data with the array
[00:28:27] I'll give you some ideas. Um, there's a lot of stuff you can implement and you probably already have some ideas to try out
[00:28:34] At least with the pitch pitch up and pitch down, you know, put stuff in octave higher octave lower halftime double time
[00:28:42] Reverse playback and so on and you can imagine if you combine this here with multiple arrays
[00:28:48] Sampling at different positions in time and playback in different
[00:28:54] Timeframes and so on you can create interesting
[00:28:57] um audio effects
[00:29:00] Just with this basic
[00:29:02] Basic setup
[00:29:05] So, yeah, I want to show you plug data how it looks like now the grand state of it
[00:29:10] Like I said, this the nightly built maybe not that stable, but you can also build this in the stable version
[00:29:16] The link is in the description below. I also put this
[00:29:19] Patch here I'm made in the description below so you can download it and try it out for yourself
[00:29:24] And have some fun
[00:29:26] So like I said, it's beneficial to know all that stuff the signal for stuff
[00:29:31] It helps you also in the grid and you react on all kinds of modular environments
[00:29:36] It's kind of all the same language everything kind of works the same also when you um
[00:29:43] Code at some point in the future, maybe some plug-ins the signal flow is the same thing
[00:29:50] You probably um implement this more like in code instead of in a visual language
[00:29:55] But the steps and the things you have to do
[00:29:58] Are kind of the same, okay?
[00:30:01] So that's what I want to say with this. So learning this is
[00:30:05] Even though it's pretty old. It's a pretty old language pure data is around since I don't know 20 years
[00:30:11] 25 years
[00:30:14] Even longer
[00:30:16] But it's still used in the industry for prototyping stuff and there are still a lot of knowledge around and
[00:30:24] Learning this is nova is never
[00:30:26] Wasted time in my opinion. So try it out links are in the description below leave a thumbs up if you like the video
[00:30:33] Uh, subscribe to the channel
[00:30:36] Super important and thanks for watching. See you in the next video. Bye
[00:30:39] [BLANK_AUDIO]