Editing
Clips are pieces of audio on a track. Each one says where it starts on the timeline (start), how far into its audio it begins (offset) and how long it plays (duration), so cuts and trims never touch the audio itself.
Mouse and touch
| Gesture | What it does |
|---|---|
| Drag a clip | Moves it in time and to other tracks, past or over other clips |
| Drag below the last track | Makes a new track for the clip (needs createTrack) |
| Drag a clip edge | Trims it, up to the ends of its audio |
| Drag a corner handle | Fade in or fade out |
| Click / Shift click / Ctrl or ⌘ click | Select, add to the selection, toggle in the selection |
| Drag on an empty track | Selects every clip the box touches; with Shift, adds them to the selection |
| Drag on the ruler | Selects a time range across all tracks, for splitting and looping |
| Drag a range's handles | Moves its start or end, on the ruler or at its edges on the tracks |
| Click the ruler or an empty track | Moves the playhead |
| Alt while dragging | Turns snapping off |
| Ctrl or ⌘ + wheel | Zooms around the pointer |
| Drag a track's bottom edge | Makes the track taller or shorter; double-click to reset |
| + above the track headers | Adds a track at the bottom and lets you name it |
| Right-click a clip | Opens the clip menu: edit notes (note clips), make unique (copies of a pattern), split at the playhead, duplicate, delete |
| Click a track's name, or right-click its header | Opens the track menu: rename, duplicate, add a track below, move up or down, delete |
| Double-click or double-tap a track's name | Renames it; Enter keeps the name, Esc cancels |
On touch screens, drag clips with a finger and swipe empty space to scroll. Range selection works from the ruler. Pinch with two fingers to zoom in and out around the point between them, and hold a finger on a clip for half a second to open its menu.
Tracks
The + above the track headers asks what to add: an empty audio track, audio from a file, or an instrument or drum track. A new empty track puts its name up for editing. Each track's menu, opened from its name or by right-clicking its header, can rename, duplicate (with its clips), add a track below, move it up or down, or delete it with its clips. Every change is one undo step.
Audio from a file shows when you pass importAudio. It opens the device's file picker and hands the picked files to your function. importAudioFiles from @toneflix/studio decodes each one in the page, without uploading it, and puts it on a new track named after the file, at the playhead, as one undo step:
import { importAudioFiles, StudioTimeline } from '@toneflix/studio';
const timeline = new StudioTimeline('#editor', {
importAudio: (files) => importAudioFiles(timeline, engine, files, { onSource: drawWaveform }),
});New tracks come from createTrack when you give it, and are named Track 1, Track 2 and so on otherwise. Pass editTracks: false to hide the button and the menu, and trackLabels to rename their items. In your own renderHeader, fire TRACK_MENU_EVENT from an element to open the menu under it, and give the name element the class tfs-track-name for double-click renaming:
import { TRACK_MENU_EVENT } from '@toneflix/studio';
name.className = 'tfs-track-name';
name.onclick = () => name.dispatchEvent(new CustomEvent(TRACK_MENU_EVENT, { bubbles: true }));From code: addTrack(track?, index?), removeTrack(id), renameTrack(id, name), duplicateTrack(id), moveTrack(id, index), editTrackName(id) and showTrackMenu(id).
Keyboard
While the timeline has focus:
| Key | What it does |
|---|---|
| S | Split the selected clips at the playhead, or cut a selected range at both edges. Does nothing when nothing is selected |
| Delete / Backspace | Delete the selected clips |
| Ctrl+D | Duplicate the selected clips right after themselves |
| Ctrl+A | Select every clip |
| Arrow left / right | Nudge by one snap step (0.1 s with snapping off) |
| Arrow up / down | Move to the track above or below |
| Ctrl+Z, Ctrl+Shift+Z | Undo, redo |
| Esc | Cancel a drag, or clear the selection |
⌘ works in place of Ctrl on macOS. Pass keyboard: false to handle shortcuts yourself.
After a split only the left pieces stay selected, so you can grab a right-hand piece and move it on its own.
Snapping
With the grid on and a snap value other than off, a dragged clip's start lands on the grid. With snapping off, clips are pulled towards other clips' edges, the playhead and zero when they come within 8 pixels (snapToClips: false turns that off).
timeline.setGrid({ bpm: 96, meter: [6, 8], snap: '1/8' });
timeline.setGrid({ show: false });Snap values are 'off', 'bar', 'beat', '1/8', '1/16' and '1/32'. The tempo counts quarter notes, so a beat of 6/8 is an eighth note.
Overlapping clips
Clips can sit on top of each other. Where they overlap, the clip that starts later is on top and is the one heard. audibleRanges gives the heard part of each clip, which is what a player or a mix renderer needs:
import { audibleRanges } from '@toneflix/studio';
const onTrack = timeline.state.clips.filter((clip) => clip.track === 'vox');
for (const { clip, start, end } of audibleRanges(onTrack)) {
// play clip.source from clip.offset + (start - clip.start) for end - start seconds
}Editing from code
Everything the gestures do is also a method:
timeline.setTime(8);
timeline.select(['clip-1']);
timeline.split();
timeline.nudge(0.5, 1);
timeline.duplicateSelected();
timeline.deleteSelected();
timeline.setZoom(120);
timeline.fit();For edits the view has no method for, use the pure edit functions through the model, so they land in the undo history:
import { setGain } from '@toneflix/studio';
timeline.model.apply('Gain', (state) => setGain(state, new Set(timeline.selection), 0.5));