Request for a Littlefoot tutorial or simple piece of working code


#1

Hi there,
I think there could be a huge improvement for the littlefoot leaning curve.
I see it as a working piece of well commented code with just minimum functions to make a Block create music. This minimum may include:

  • a static grid initialization (for example, 5x5 with no ability to change)
  • a single scale to link with that grid
  • a touch handling event sending note and highlighting relative cell
  • a slide handling event sending pitch

I think this would be enough for a dummy coder like me to gain initial knowledge along with huge enthusiasm for more learning. Tnx.


#2

Agreed, that’s a pretty good list. I recently started working with Littlefoot, and I came up with this to draw a static 4x4 grid:

void repaint()
{
    clearDisplay();
    for (int i = 0; i < 7; ++i) {
        for (int j = 0; j < 7; ++j) {
            fillRect (makeARGB (int (0), i*30+10, 0, j*30+10), i*4, j*4, 3, 3);
        }
    }
}

Granted, that only draws it and does nothing more! I think that adding pressure points and sending note events would be the next steps.

Edit: code formatting and misquoted grid size


#3

Actually, looking that the API, it would probably be better to call that in initialise instead of repaint. That way you aren’t drawing the same static thing over and over. :grinning:


#4

I put together a simple 5x5 note grid example. It sends note messages and displays the note number sent. I commented it heavily and wrote the code to be explicit so that it might help others who are just starting out.

/*
<metadata description="5x5 note grid with midi note display">
</metadata>
*/	


//==============================================================================
// Clear anything left on the display and draw a grid
//==============================================================================
void initialise() {
    clearDisplay();
    drawPads();
}


//==============================================================================
// Draw a 5x5 grid in a checkerboard pattern
//==============================================================================
void drawPads() {
    for (int i = 0; i < 5; ++i) {
        for (int j = 0; j < 5; ++j) {
            if ((i+j)%2 == 0)
                fillRect (makeARGB (int (0), 0, 5, 10), i*3, j*3, 3, 3);
            else
                fillRect (makeARGB (int (0), 0, 10, 5), i*3, j*3, 3, 3);
        }
    }
}


//==============================================================================
/* 
  touchStart is called when a touch event starts.
  
  We do a few things here:
    - Redraw the pads (to clear the debugging overlay)
    - Determine which pad was pressed using getPadNumber (defined below).
      The pads are numbered 0-24 starting at the bottom left.
    - Send a key-down message in the range 60-84 with velocity 127 on channel 0
    - Store padNumber on the heap at location touchIndex. This allows us to 
      retrieve the padNumber later in touchEnd.
    - Draw the key number sent (debugging overlay)
*/
//==============================================================================
void touchStart (int touchIndex, float x, float y, float z, float vz) {
    drawPads();
    int padNumber = getPadNumber(x, y);
    sendNoteOn(0, padNumber+60, 127);
    setHeapByte(touchIndex, padNumber);
    drawNumber (padNumber+60, 0xbbdd9900, 3, 5);
}


//==============================================================================
/*
  touchEnd is called when a touch event ends.
  
  The main goal here is to send a key-up message:
    - Retrieve the padNumber for the touch that has ended from the heap
    - Send a key-up message to end the note
    - Redraw the pads (to clear the debugging overlay)
*/
//==============================================================================
void touchEnd (int touchIndex, float x, float y, float z, float vz) {
    int padNumber = getHeapByte(touchIndex);
    sendNoteOff(0, padNumber+60, 127);
    drawPads();
}


//==============================================================================
/*
  getPadNumber and its helper getColumn determine which pad received a touch.
  On a Lightpad Block, each side ranges from 0.0 to 2.0. We can logically
  divide the Block into 0.4x0.4 cells and return a padNumber based on the
  coordinates of the touch.
*/
//==============================================================================
int getPadNumber (float x, float y) {
    if (y < 0.4) return getColumn(x) + 20;
    else if (y > 0.4 && y < 0.8) return 15 + getColumn(x);
    else if (y > 0.8 && y < 1.2) return 10 + getColumn(x);
    else if (y > 1.2 && y < 1.6) return 5 + getColumn(x);
    else return getColumn(x);
}

int getColumn (float x) {
    if (x < 0.4) return 0;
    else if (x > 0.4 && x < 0.8) return 1;
    else if (x > 0.8 && x < 1.2) return 2;
    else if (x > 1.2 && x < 1.6) return 3;
    else return 4;
}

#5

For when we are making a layout that does not use a mathematically generated “pad” layout system, how do we define the range of specific “buttons” that we would like to apply functions to?


#6

I just remembered that is what logical operations are for. doi’ :blush:

Defining the “pads” based on the x, y ranges.


#7

Would you be willing to go over working with the heap in littlefoot?

Mostly, I am confused as to how much memory to allocate to specific things.