Overview
Larsio Paint Music is a love letter to Mario Paint -- the mouse-driven art creation cartridge for Super Nintendo. It included a wonderfully fun music composition mode where you could draw notes on a music staff using different samples and synth voices and then play them. I decided to recreate this classic on a modern microcontroller in CircuitPython as Larsio Paint Music (LPM).
LPM runs on a Metro RP2350 or the Fruit Jam. With USB mouse-input, HDMI video output, and stereo I2S DAC audio output for synthesized and sampled sounds, you can try your hand at making music the semi old-fashioned way -- with a music staff and pixelated sprites for notes!
Parts
The project can be built using the Adafruit Metro RP2350 with PSRAM and some additional parts (DAC and DVI breakout) or the Adafruit Fruit Jam.
Other project parts (used with either microcontroller dev board):
HDMI/DVI Display
An HDMI/DVI display that can be set to 640x480 mode.
This one is great because it can be set to 4:3 mode so your image won't be stretched, and it has a 3.5mm TRS audio input for the internal speakers.
Page last edited September 03, 2025
Text editor powered by tinymce.
For Fruit Jam
Page last edited September 03, 2025
Text editor powered by tinymce.
Install CircuitPython
CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.
CircuitPython Quickstart
Follow this step-by-step to quickly get CircuitPython running on your board.
Click the link above to download the latest CircuitPython UF2 file.
Save it wherever is convenient for you.
To enter the bootloader, hold down the BOOT/BOOTSEL button (highlighted in red above), and while continuing to hold it (don't let go!), press and release the reset button (highlighted in red or blue above). Continue to hold the BOOT/BOOTSEL button until the RP2350 drive appears!
If the drive does not appear, release all the buttons, and then repeat the process above.
You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.
A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.
You will see a new disk drive appear called RP2350.
Drag the adafruit-circuitpython-boardname-language-version.uf2 file to RP2350.
The RP2350 drive will disappear and a new disk drive called CIRCUITPY will appear.
That's it, you're done! :)
Safe Mode
You want to edit your code.py or modify the files on your CIRCUITPY drive, but find that you can't. Perhaps your board has gotten into a state where CIRCUITPY is read-only. You may have turned off the CIRCUITPY drive altogether. Whatever the reason, safe mode can help.
Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode bypasses any code in boot.py (where you can set CIRCUITPY read-only or turn it off completely). Second, it does not run the code in code.py. And finally, it does not automatically soft-reload when data is written to the CIRCUITPY drive.
Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the CIRCUITPY drive.
To enter safe mode when using CircuitPython, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)
In Safe Mode
If you successfully enter safe mode on CircuitPython, the LED will intermittently blink yellow three times.
If you connect to the serial console, you'll find the following message.
Auto-reload is off. Running in safe mode! Not running saved code. CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode. Press any key to enter the REPL. Use CTRL-D to reload.
You can now edit the contents of the CIRCUITPY drive. Remember, your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode.
Flash Resetting UF2
If your board ever gets into a really weird state and CIRCUITPY doesn't show up as a disk drive after installing CircuitPython, try loading this 'nuke' UF2 to RP2350. which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.
Page last edited September 03, 2025
Text editor powered by tinymce.
Code Larsio Paint Music
Download the Project Bundle
Your project will use a specific set of CircuitPython libraries, sprite assets, sound assets, and .py files. To get everything you need, click on the Download Project Bundle link below, and uncompress the .zip file.
Drag the contents of the uncompressed bundle directory onto your board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.
# SPDX-FileCopyrightText: 2025 John Park and Claude AI for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Larsio Paint Music
Fruit Jam w mouse, HDMI, audio out
or Metro RP2350 with EYESPI DVI breakout and TLV320DAC3100 breakout on STEMMA_I2C,
pin D7 reset, 9/10/11 = BCLC/WSEL/DIN
"""
# pylint: disable=invalid-name,too-few-public-methods,broad-except,redefined-outer-name
# Main application file for Larsio Paint Music
import time
import gc
from sound_manager import SoundManager
from note_manager import NoteManager
from ui_manager import UIManager
# Configuration
AUDIO_OUTPUT = "i2s" # Options: "pwm" or "i2s"
class MusicStaffApp:
"""Main application class that ties everything together"""
def __init__(self, audio_output="pwm"):
# Initialize the sound manager with selected audio output
# Calculate tempo parameters
BPM = 120 # Beats per minute
SECONDS_PER_BEAT = 60 / BPM
SECONDS_PER_EIGHTH = SECONDS_PER_BEAT / 2
# Initialize components in a specific order
# First, force garbage collection to free memory
gc.collect()
# Initialize the sound manager
print("Initializing sound manager...")
self.sound_manager = SoundManager(
audio_output=audio_output,
seconds_per_eighth=SECONDS_PER_EIGHTH
)
# Give hardware time to stabilize
time.sleep(0.5)
gc.collect()
# Initialize the note manager
print("Initializing note manager...")
self.note_manager = NoteManager(
start_margin=25, # START_MARGIN
staff_y_start=int(240 * 0.1), # STAFF_Y_START
line_spacing=int((240 - int(240 * 0.1) - int(240 * 0.2)) * 0.95) // 8 # LINE_SPACING
)
gc.collect()
# Initialize the UI manager
print("Initializing UI manager...")
self.ui_manager = UIManager(self.sound_manager, self.note_manager)
def run(self):
"""Set up and run the application"""
# Setup the display and UI
print("Setting up display...")
self.ui_manager.setup_display()
# Give hardware time to stabilize
time.sleep(0.5)
gc.collect()
# Try to find the mouse
if self.ui_manager.find_mouse():
print("Mouse found successfully!")
else:
print("WARNING: Mouse not found.")
print("The application will run, but mouse control may be limited.")
# Enter the main loop
self.ui_manager.main_loop()
# Create and run the application
if __name__ == "__main__":
# Start with garbage collection
gc.collect()
print("Starting Music Staff Application...")
try:
app = MusicStaffApp(audio_output=AUDIO_OUTPUT)
app.run()
except Exception as e: # pylint: disable=broad-except
print(f"Error with I2S audio: {e}")
# Force garbage collection
gc.collect()
time.sleep(1)
# Fallback to PWM
try:
app = MusicStaffApp(audio_output="pwm")
app.run()
except Exception as e2: # pylint: disable=broad-except
print(f"Fatal error: {e2}")
To keep things manageable, Larsio Paint Music uses a modular design with each component handling a specific set of related tasks:
| Module | Use |
|---|---|
code.py |
Main application entry point |
sound_manager.py |
Audio handling (WAV samples, and synthio) |
note_manager.py |
Manages note positions and properties |
ui_manager.py |
Coordinates UI elements and user interaction |
display_manager.py |
Configures and initializes the display |
staff_view.py |
Creates and manages the music staff visuals |
control_panel.py |
Handles buttons and controls |
input_handler.py |
Processes mouse input |
sprite_manager.py |
Loads and manages graphics assets |
cursor_manager.py |
Manages the mouse cursor |
playback_controller.py |
Controls playback and timing |
Here's how these modules work.
Main Application (code.py)
This file runs when the board starts up and then it coordinates the other modules.
Sound Manager
The SoundManager handles all audio playback, including WAV samples, MIDI output, and synthesized sounds. It's one of the more complex parts of the application.
It also auto-detects which board is being used (Metro RP2350 or Fruit Jam) and configures the I2S pins appropriately.
Audio Mixer
The app uses an audio mixer with multiple voices, enabling simultaneous sounds.
Multi-Channel Sound
The program supports multiple instrument channels:
- Channel 1 (Lars): Custom WAV samples of everyone's favorite sloth
- Channel 2 (Heart): Bass
- Channel 3 (Drums): Percussion sounds
- Channels 4-6: Synthesizer voices with different waveforms
Note Manager
The NoteManager handles the positions of notes on the staff and their pitch values. It maintains a mapping of staff positions to MIDI note numbers.
When a note is added, the manager:
- Finds the closest valid position
- Creates a visual note at that position
- Adds ledger lines if needed
- Stores the note's data for playback
UI Manager and Display Manger
These coordinate all user interface elements and interactions, as well as displaying them to the screen.
- Setting up the display
- Creating the staff view
- Handling the control panel
- Processing user input
- Managing the playback
Staff View
The StaffView class creates the musical staff display with proper music notation spacing. It draws the staff lines, measure bars, and quarter note dividers so you can more easily see the bar subdivisions.
Control Panel
The ControlPanel class handles all the UI controls for the application, including transport buttons and channel selectors.
Input Handling
The InputHandler processes mouse input for interacting with the application, including mouse position and interactions:
- Left-click to add notes
- Right-click to delete notes
- Click on channel icons to switch instruments
- Control playback with transport buttons
- Adjust tempo
Sprite Manager
The SpriteManager loads and manages all graphical assets using BMP files:
Each instrument channel has its own unique sprite:
- Channel 1: Lars
- Channel 2: Heart (bass)
- Channel 3: Drum
- Channel 4: Meatball sprite for sine wave notes
- Channel 5: star sprite for triangle wave notes
- Channel 6: Adabot Head sprite for sawtooth wave notes
The sprite manager also handles preview notes shown during mouse hover, and handles button sprites for the transport controls.
Cursor Manager
The CursorManager handles the mouse cursor visuals, switching between different cursor styles based on context:
- Crosshair Cursor: Used when over the staff for precise note placement
- Triangle Cursor: Used when over buttons or controls
The offsets for each cursor ensure that the "hot spot" or active point of the cursor is properly aligned with the actual mouse position, making interaction more intuitive.
Playback Controller
The PlaybackController manages the playback of notes:
- Moves a playhead across the staff
- Triggers all notes at the current position
- Handles looping when enabled
- Stops playback when finished
Main Loop
The application's main loop continuously:
- Updates the playback (if active)
- Processes mouse input
- Updates the cursor position
- Handles button clicks
Page last edited September 03, 2025
Text editor powered by tinymce.
Prep Fruit Jam
Connections
- Plug an HDMI cable into HSTX DVI-D Video Output on the Fruit Jam, then plug other end of cable into your HDMI TV or monitor
- Plug a set of headphones or 3.5mm TRS stereo cable into the DAC output port (labeled Stereo Headphone). You can use headphones or plug the cable into the input of an amplifier or powered speakers, just watch the levels
- Plug a USB mouse into the USB 1 port on the Fruit Jam
- Power the Fruit Jam by plugging a USB C cable into the USB C Power & Data port
Turn on the monitor, speaker amplifier, and the Fruit Jam and you're ready to go.
Page last edited September 03, 2025
Text editor powered by tinymce.
For Metro RP2350
Page last edited September 03, 2025
Text editor powered by tinymce.
Install CircuitPython
CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.
CircuitPython Quickstart
Follow this step-by-step to quickly get CircuitPython running on your board.
Click the link above to download the latest CircuitPython UF2 file.
Save it wherever is convenient for you.
To enter the bootloader, hold down the BOOT/BOOTSEL button (highlighted in red above), and while continuing to hold it (don't let go!), press and release the reset button (highlighted in red or blue above). Continue to hold the BOOT/BOOTSEL button until the RP2350 drive appears!
If the drive does not appear, release all the buttons, and then repeat the process above.
You can also start with your board unplugged from USB, press and hold the BOOTSEL button (highlighted in red above), continue to hold it while plugging it into USB, and wait for the drive to appear before releasing the button.
A lot of people end up using charge-only USB cables and it is very frustrating! Make sure you have a USB cable you know is good for data sync.
You will see a new disk drive appear called RP2350.
Drag the adafruit-circuitpython-boardname-language-version.uf2 file to RP2350.
The RP2350 drive will disappear and a new disk drive called CIRCUITPY will appear.
That's it, you're done! :)
Safe Mode
You want to edit your code.py or modify the files on your CIRCUITPY drive, but find that you can't. Perhaps your board has gotten into a state where CIRCUITPY is read-only. You may have turned off the CIRCUITPY drive altogether. Whatever the reason, safe mode can help.
Safe mode in CircuitPython does not run any user code on startup, and disables auto-reload. This means a few things. First, safe mode bypasses any code in boot.py (where you can set CIRCUITPY read-only or turn it off completely). Second, it does not run the code in code.py. And finally, it does not automatically soft-reload when data is written to the CIRCUITPY drive.
Therefore, whatever you may have done to put your board in a non-interactive state, safe mode gives you the opportunity to correct it without losing all of the data on the CIRCUITPY drive.
To enter safe mode when using CircuitPython, plug in your board or hit reset (highlighted in red above). Immediately after the board starts up or resets, it waits 1000ms. On some boards, the onboard status LED (highlighted in green above) will blink yellow during that time. If you press reset during that 1000ms, the board will start up in safe mode. It can be difficult to react to the yellow LED, so you may want to think of it simply as a slow double click of the reset button. (Remember, a fast double click of reset enters the bootloader.)
In Safe Mode
If you successfully enter safe mode on CircuitPython, the LED will intermittently blink yellow three times.
If you connect to the serial console, you'll find the following message.
Auto-reload is off. Running in safe mode! Not running saved code. CircuitPython is in safe mode because you pressed the reset button during boot. Press again to exit safe mode. Press any key to enter the REPL. Use CTRL-D to reload.
You can now edit the contents of the CIRCUITPY drive. Remember, your code will not run until you press the reset button, or unplug and plug in your board, to get out of safe mode.
Flash Resetting UF2
If your board ever gets into a really weird state and CIRCUITPY doesn't show up as a disk drive after installing CircuitPython, try loading this 'nuke' UF2 to RP2350. which will do a 'deep clean' on your Flash Memory. You will lose all the files on the board, but at least you'll be able to revive it! After loading this UF2, follow the steps above to re-install CircuitPython.
Page last edited September 03, 2025
Text editor powered by tinymce.
Preparing the Metro RP2350
The USB Host port is the only part of this project that required soldering.
The USB Host pin connections are highlighted on the Metro image to the left. You will need a small piece of standard 0.1 inch male header, with 4 pins, to fit the holes.
You can cut header with diagonal cutters or break them with pliers or even your fingers. Just be sure to wear eye protection as they can fly when cut.
Put the short end of the header into the holes in the Metro marked USB Host and secure them with putty, blutack, tape, etc. Turn the Metro over and you should see the header barely poking out of the bottom of the board. If the pins stick through a great deal you may have the header pins upside down, double check the short end is sticking into the board.
Solder the 4 pin "nubbins" to the board.
Turn the board over and remove the material securing the pins. Now there is a new 4-pin header.
Get the USB Host cable and wire as follows:
GRD to Black
D+ to Green
D- to White
5V to Red
Get the HSTX cable. Any length Adafruit sells is fine. CAREFULLY lift the dark grey bar up on the Metro, insert the cable silver side down, blue side up, then put the bar CAREFULLY down, ensuring it locks. If it feels like it doesn't want to go, do not force it.
Do the same with the other end and the DVI breakout. Note that the DVI breakout will be inverted/upside down when compared to the Metro - this is normal for these boards and the Adafruit cables.
Page last edited September 03, 2025
Text editor powered by tinymce.
Metro RP2350 DAC Circuit
DAC Wiring
The TVL320DAC3100 is wired up with I2S for digital audio, I2C for settings, power, ground, and a reset line. Make the following connections between the Metro and the DAC either on a breadboard or Perma Proto board:
- Metro 3V to DAC VIN
- Metro GND to DAC GND
- Metro SDA to DAC SDA
- Metro SCL to DAC SCL
- Metro D9 to DAC BCLK
- Metro D10 to DAC WSEL
- Metro D11 to DAC DIN
- Metro D7 to DAC RST
Page last edited September 03, 2025
Text editor powered by tinymce.
Code Larsio Paint Music
Download the Project Bundle
Your project will use a specific set of CircuitPython libraries, sprite assets, sound assets, and .py files. To get everything you need, click on the Download Project Bundle link below, and uncompress the .zip file.
Drag the contents of the uncompressed bundle directory onto your board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.
# SPDX-FileCopyrightText: 2025 John Park and Claude AI for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Larsio Paint Music
Fruit Jam w mouse, HDMI, audio out
or Metro RP2350 with EYESPI DVI breakout and TLV320DAC3100 breakout on STEMMA_I2C,
pin D7 reset, 9/10/11 = BCLC/WSEL/DIN
"""
# pylint: disable=invalid-name,too-few-public-methods,broad-except,redefined-outer-name
# Main application file for Larsio Paint Music
import time
import gc
from sound_manager import SoundManager
from note_manager import NoteManager
from ui_manager import UIManager
# Configuration
AUDIO_OUTPUT = "i2s" # Options: "pwm" or "i2s"
class MusicStaffApp:
"""Main application class that ties everything together"""
def __init__(self, audio_output="pwm"):
# Initialize the sound manager with selected audio output
# Calculate tempo parameters
BPM = 120 # Beats per minute
SECONDS_PER_BEAT = 60 / BPM
SECONDS_PER_EIGHTH = SECONDS_PER_BEAT / 2
# Initialize components in a specific order
# First, force garbage collection to free memory
gc.collect()
# Initialize the sound manager
print("Initializing sound manager...")
self.sound_manager = SoundManager(
audio_output=audio_output,
seconds_per_eighth=SECONDS_PER_EIGHTH
)
# Give hardware time to stabilize
time.sleep(0.5)
gc.collect()
# Initialize the note manager
print("Initializing note manager...")
self.note_manager = NoteManager(
start_margin=25, # START_MARGIN
staff_y_start=int(240 * 0.1), # STAFF_Y_START
line_spacing=int((240 - int(240 * 0.1) - int(240 * 0.2)) * 0.95) // 8 # LINE_SPACING
)
gc.collect()
# Initialize the UI manager
print("Initializing UI manager...")
self.ui_manager = UIManager(self.sound_manager, self.note_manager)
def run(self):
"""Set up and run the application"""
# Setup the display and UI
print("Setting up display...")
self.ui_manager.setup_display()
# Give hardware time to stabilize
time.sleep(0.5)
gc.collect()
# Try to find the mouse
if self.ui_manager.find_mouse():
print("Mouse found successfully!")
else:
print("WARNING: Mouse not found.")
print("The application will run, but mouse control may be limited.")
# Enter the main loop
self.ui_manager.main_loop()
# Create and run the application
if __name__ == "__main__":
# Start with garbage collection
gc.collect()
print("Starting Music Staff Application...")
try:
app = MusicStaffApp(audio_output=AUDIO_OUTPUT)
app.run()
except Exception as e: # pylint: disable=broad-except
print(f"Error with I2S audio: {e}")
# Force garbage collection
gc.collect()
time.sleep(1)
# Fallback to PWM
try:
app = MusicStaffApp(audio_output="pwm")
app.run()
except Exception as e2: # pylint: disable=broad-except
print(f"Fatal error: {e2}")
To keep things manageable, Larsio Paint Music uses a modular design with each component handling a specific set of related tasks:
| Module | Use |
|---|---|
code.py |
Main application entry point |
sound_manager.py |
Audio handling (WAV samples, and synthio) |
note_manager.py |
Manages note positions and properties |
ui_manager.py |
Coordinates UI elements and user interaction |
display_manager.py |
Configures and initializes the display |
staff_view.py |
Creates and manages the music staff visuals |
control_panel.py |
Handles buttons and controls |
input_handler.py |
Processes mouse input |
sprite_manager.py |
Loads and manages graphics assets |
cursor_manager.py |
Manages the mouse cursor |
playback_controller.py |
Controls playback and timing |
Here's how these modules work.
Main Application (code.py)
This file runs when the board starts up and then it coordinates the other modules.
Sound Manager
The SoundManager handles all audio playback, including WAV samples, MIDI output, and synthesized sounds. It's one of the more complex parts of the application.
It also auto-detects which board is being used (Metro RP2350 or Fruit Jam) and configures the I2S pins appropriately.
Audio Mixer
The app uses an audio mixer with multiple voices, enabling simultaneous sounds.
Multi-Channel Sound
The program supports multiple instrument channels:
- Channel 1 (Lars): Custom WAV samples of everyone's favorite sloth
- Channel 2 (Heart): Bass
- Channel 3 (Drums): Percussion sounds
- Channels 4-6: Synthesizer voices with different waveforms
Note Manager
The NoteManager handles the positions of notes on the staff and their pitch values. It maintains a mapping of staff positions to MIDI note numbers.
When a note is added, the manager:
- Finds the closest valid position
- Creates a visual note at that position
- Adds ledger lines if needed
- Stores the note's data for playback
UI Manager and Display Manger
These coordinate all user interface elements and interactions, as well as displaying them to the screen.
- Setting up the display
- Creating the staff view
- Handling the control panel
- Processing user input
- Managing the playback
Staff View
The StaffView class creates the musical staff display with proper music notation spacing. It draws the staff lines, measure bars, and quarter note dividers so you can more easily see the bar subdivisions.
Control Panel
The ControlPanel class handles all the UI controls for the application, including transport buttons and channel selectors.
Input Handling
The InputHandler processes mouse input for interacting with the application, including mouse position and interactions:
- Left-click to add notes
- Right-click to delete notes
- Click on channel icons to switch instruments
- Control playback with transport buttons
- Adjust tempo
Sprite Manager
The SpriteManager loads and manages all graphical assets using BMP files:
Each instrument channel has its own unique sprite:
- Channel 1: Lars
- Channel 2: Heart (bass)
- Channel 3: Drum
- Channel 4: Meatball sprite for sine wave notes
- Channel 5: star sprite for triangle wave notes
- Channel 6: Adabot Head sprite for sawtooth wave notes
The sprite manager also handles preview notes shown during mouse hover, and handles button sprites for the transport controls.
Cursor Manager
The CursorManager handles the mouse cursor visuals, switching between different cursor styles based on context:
- Crosshair Cursor: Used when over the staff for precise note placement
- Triangle Cursor: Used when over buttons or controls
The offsets for each cursor ensure that the "hot spot" or active point of the cursor is properly aligned with the actual mouse position, making interaction more intuitive.
Playback Controller
The PlaybackController manages the playback of notes:
- Moves a playhead across the staff
- Triggers all notes at the current position
- Handles looping when enabled
- Stops playback when finished
Main Loop
The application's main loop continuously:
- Updates the playback (if active)
- Processes mouse input
- Updates the cursor position
- Handles button clicks
Page last edited September 03, 2025
Text editor powered by tinymce.
Plug in Metro
Video Output
Plug the HDMI cable out of the DVI video output on the Metro RP2350 and into your HDMI monitor.
Note: some monitors aren't capable of displaying 640x480, in which case you'll see a blank screen.
The monitor linked in the Parts section of this guide is a good bet if you need a small 640x480 4:3 ratio display. You'll also often find that older LCD televisions are 640x480 capable.
Audio Output
Plug a 3.5mm TRS audio cable into the DAC output and either your TV's audio input if available or a set of powered speakers or headphones.
Mouse Input
Just like with Mario Paint, the only input device you'll need for Larsio Paint Music is a mouse. Plug a USB mouse into the USB A connector.
Page last edited September 03, 2025
Text editor powered by tinymce.
Use Larsio Paint Music
Usage
Making music with Larsio Paint Music is fun and simple -- just add notes where you like and hit play! You can add notes while it's playing for fast composition. Watch the above video for a demonstration.
Voice Select
There are six types of sounds (called "voices") you can play with. Click the icons in the upper left corner to choose among them. The first three are wav samples, the other three are synthio synthesizer voices.
- Lars - pitched sample of eveyone's favorite creepy sloth, Lars
- Heart - bass multi-sample
- Drums - multiple drum samples: kick, snare, closed hihat, open hihat, crash cymbal
- Meatball - synthesizer sine wave notes
- Star - synthesizer triangle wave notes
- Robot - synthesizer sawtooth wave notes
Add Notes
Hover the cursor over the music staff -- you'll see that you're dragging a Lars note around. Click anywhere on the staff with the left mouse button (LMB) to place a note and hear a preview.
Delete Notes
If you don't like where you placed the note, delete it by hovering over it and right mouse button (RMB) clicking it.
Play
Hover over the transport control section on the bottom and click the triangle Play button to play the four bars.
Stop
Click the square Stop button to stop playback. The playhead will return to the beginning of the first bar.
Loop
Click the Loop button and the song will play over and over and over again until you press stop or the power goes out!
Clear
If you want to clear all the notes at once, click the bomb-shaped Clear button.
Page last edited September 03, 2025
Text editor powered by tinymce.