Project 5: Drag and Drop Sampler

This project allows you drag audio files into the designated regions. The samples are then loaded into into the Sampler oscillator.

Each of these sampler oscillators are within their own separate keygroups. Each keygroup is assigned to a specific MIDI note.

Variables

The first group of variables refer to the FOM locations for keygroups and oscillators.

-- Variables for the FOM
local keygroup1 = Program.layers[1].keygroups[1] --Sampler1
local sample1Osc = keygroup1.oscillators[1] --Oscillator for Sampler1

local keygroup2 = Program.layers[1].keygroups[2] --Sampler2
local sample2Osc = keygroup2.oscillators[1] --Oscillator for Sampler2

local keygroup3 = Program.layers[1].keygroups[3] --Sampler3
local sample3Osc = keygroup3.oscillators[1] --Oscillator for Sampler3

local keygroup4 = Program.layers[1].keygroups[4] --Sampler4
local sample4Osc = keygroup4.oscillators[1] --Oscillator for Sampler4

local keygroup5 = Program.layers[1].keygroups[5] --Sampler4
local sample5Osc = keygroup5.oscillators[1] --Oscillator for Sampler5

Additional UI Variables

These variables handle user interface details. The first one, mainBg, will be the background image. We use the Image class and the parameter will be the file location.

local mainBg = Image("assets/wvfrm_lua_p5_bg.png")

The following variables don't use the image class. This is because they are variables that have a string value of a file location. They are used later in the code.

local defaultBg = "assets/drag-drop-ui.png"
local triggerBG = "assets/drag-drop-trigger-ui.png"

User Interface

The next section utilizes the Drag and Drop Widget. First we position the background image.

mainBg.x = 0
mainBg.y = 0

Drag and Drop

The process of using widgets should look familiar now. We create a variable called dnd1 from the DnDArea widget.

dnd1 = DnDArea("DnD1")

After the creation of this variable, we then position and define details about this UI widget. The last line defines the image and you can see the variable is used for the default image. The reason we did this is because we repeat this widget multiple times. So we use a single variable for this file location

dnd1 = DnDArea("DnD1")
dnd1.backgroundColour = ("#DADADA")
dnd1.size = {60,60}
dnd1.x = 30
dnd1.y = 195
dnd1.image = defaultBg

File Format

acceptedFileFormat allows you to define the type of file. We're specifying audio as our format.

dnd1.acceptedFileFormat = FileFormat.Audio

fileDropped

This function uses the fileDropped method. It is assigned a value of a function. This means that when the fileDropped function is triggered, it will trigger the function we assign. fileDropped is triggered when we drop a file into the region.

Self

The keyword self is used inside the function. Placing it there allows the dnd1 object to refer to itself. Observe how self.filepath is assigned to sampleOsc.SamplePath. We are assigning the brand new filepath to the SamplePath of the sample1Osc.

loadSample

This function takes three parameters. The first is the oscillator (where we place our sample). The second is the path where the sample is placed. You just need to know that the path will be the oscillator location followed by SamplePath. The third is the callback function. This will be a function that is called after the rest is completed.

dnd1.fileDropped = function(self)
    sample1Osc.SamplePath = self.filepath
    loadSample(sample1Osc, sample1Osc.SamplePath,
    function(task)
        print("done") 
        print(task.success) 
    end
    )
    print("samplepath1: ", sample1Osc.SamplePath)
end

This is then repeated 5 times!

Important:⚠️

  • Be careful to observe how each dnd variable has a specific suffix number.

  • Each FOM variable has a specific number

Labels

After the repetition of those widgets, we then create the labels. The same principles apply here. We create a variable from the label widget. We then specify the text and visual details for the label. This is repeated 5 times.

l1 = Label("C2_label")
l1.text = "C2"
l1.align = "center"
l1.textColour = "black"
l1.x = 50
l1.y = 230

Callback Functions

onNote

We use the function onNote() in this project and it contains many conditionals. Before the conditionals, we have the playNote(e). This ensures that any note that is pressed, is sent to the engine and oscillators.

The if statement uses the variable e, which stands for the incoming event. We then check what specific note this event has. In the example below, we are checking if the note is 48, which is C2 on the keyboard. If it is, we switch the image of the dnd widget. This creates a visual feedback for the user.

This is repeated 5 times in the code for different notes.

-- Partial Excerpt of code
function onNote(e)
    playNote(e)

    if e.note == 48 then
        print(e.type)
        dnd1.image = triggerBG
    end

    -- Additional conditionals would appear here
end

onRelease

This is identical to onNote except we are not detecting when a note released. I set this up in order to switch the image of the dnd widget again back to the default state.

function onRelease(e)
    if e.note == 48 then
        dnd1.image = defaultBg
    end
    -- Additional conditionals would appear here
end

Final

At the end we specify the size of the UI and also we use the makePerformanceView() function. This activates the script within the info tab of Falcon.

makePerformanceView()
setSize(720, 480)