Cookbook
Complete scripts. All of them ship with the studio under File > Open, so you can run and modify them there.
A pluck with a reverb send and a looping arpeggio
CODE
const project = openDAW.newProject("Hello openDAW")
project.bpm = 110
const synth = project.addInstrumentUnit("Vaporisateur", {label: "Pluck", volume: -9}, {
cutoff: 2400, resonance: 0.4, filterEnvelope: 0.6, decay: 0.25, sustain: 0.1, release: 0.4
})
const reverb = project.addAuxUnit({label: "Reverb"})
reverb.addAudioEffect("Reverb", {decay: 0.7, wet: -6})
synth.addSend(reverb, {amount: -12})
const region = synth.noteTracks[0].addRegion({duration: PPQN.Bar * 2, loopDuration: PPQN.Bar})
const pitches = [60, 64, 67, 71, 72, 71, 67, 64]
region.addEvents(pitches.map((pitch, index) => ({
position: index * PPQN.SemiQuaver * 2,
duration: PPQN.SemiQuaver,
pitch,
velocity: 0.6 + (index % 2) * 0.3
})))
project.openInStudio()Drums from the sample library
CODE
const project = openDAW.newProject("Beat")
const samples = await openDAW.listSamples()
const pick = (needle: string) => samples.find(sample => sample.name.toLowerCase().includes(needle))
const kick = pick("kick")
const snare = pick("snare")
const hat = pick("hat")
if (!kick || !snare || !hat) {
await openDAW.showInfo("Beat", "Could not find kick, snare and hat samples.")
return
}
const drums = project.addInstrumentUnit("Playfield", {label: "Drums"})
drums.instrument.addSample(kick, {note: 36})
drums.instrument.addSample(snare, {note: 38})
drums.instrument.addSample(hat, {note: 42, exclude: true, release: 0.05})
const region = drums.noteTracks[0].addRegion({duration: PPQN.Bar * 4, loopDuration: PPQN.Bar})
const step = PPQN.SemiQuaver
for (let index = 0; index < 16; index++) {
if (index % 4 === 0) {region.addEvent({position: index * step, duration: step, pitch: 36})}
if (index % 8 === 4) {region.addEvent({position: index * step, duration: step, pitch: 38})}
region.addEvent({position: index * step, duration: step, pitch: 42, velocity: index % 2 === 0 ? 0.8 : 0.4})
}
project.openInStudio()Generate a sample and place it on an audio track
CODE
const numberOfFrames = sampleRate * 3
const audioData = AudioData.create(sampleRate, numberOfFrames, 1)
const frames = audioData.frames[0]
for (let index = 0, phase = 0.0; index < numberOfFrames; index++) {
frames[index] = Math.sin(phase * Math.PI * 2.0) * dbToGain(-6.0)
const t = index / numberOfFrames
const freq = 200.0 * Math.pow(20.0, 1.0 - Math.abs(2.0 * t - 1.0))
phase += freq / sampleRate
}
const sample = await openDAW.addSample(audioData, "Chirp")
const project = openDAW.newProject("Chirp")
const tape = project.addInstrumentUnit("Tape")
tape.audioTracks[0].addRegion(sample, {playback: "no-sync"})
tape.addAudioEffect("Reverb", {wet: -9})
project.openInStudio()Automate a filter sweep and wobble it with an LFO
CODE
const project = openDAW.newProject("Sweep")
const synth = project.addInstrumentUnit("Vaporisateur", {label: "Bass"}, {cutoff: 400, resonance: 2})
synth.noteTracks[0].addRegion({duration: PPQN.Bar * 8}).addEvent({position: 0, duration: PPQN.Bar * 8, pitch: 36})
const lane = synth.addValueTrack(synth.instrument, "cutoff")
lane.addRegion({duration: PPQN.Bar * 8}).addEvents([
{position: 0, value: 0.1},
{position: PPQN.Bar * 8, value: 0.8, interpolation: Interpolation.Linear}
])
const lfo = project.addModulator("LFO", {label: "Wobble", rateSync: 8})
lfo.assign(synth.instrument, "cutoff", 0.3)
project.openInStudio()Transpose every note of the open project
CODE
const project = await openDAW.getProject()
project.audioUnits.forEach(unit => unit.noteTracks.forEach(track => {
track.regions.forEach(region => region.events.forEach(event => event.pitch += 2))
track.clips.forEach(clip => clip.events.forEach(event => event.pitch += 2))
}))
project.openInStudio()Cleanup
Removes empty tracks, muted regions and clips, regions beyond the end and unused aux units, then reports.
CODE
if (!await openDAW.hasProject()) {
await openDAW.showInfo("Cleanup", "No project is open.")
return
}
const project = await openDAW.getProject()
const report: string[] = []
const note = (amount: number, what: string) => {if (amount > 0) {report.push(`${amount} × ${what}`)}}
let muted = 0
project.audioUnits.forEach(unit => unit.tracks.forEach(track => {
track.regions.filter(region => region.mute || region.position >= project.duration).forEach(region => {
region.remove()
muted++
})
track.clips.filter(clip => clip.mute).forEach(clip => {
clip.remove()
muted++
})
}))
note(muted, "muted or stray regions and clips")
let emptyTracks = 0
project.audioUnits.forEach(unit => {
const empty = unit.tracks.filter(track => track.regions.length === 0 && track.clips.length === 0)
const removable = empty.length === unit.tracks.length ? empty.slice(1) : empty
removable.forEach(track => {
track.remove()
emptyTracks++
})
})
note(emptyTracks, "empty tracks")
const targets = new Set<string>()
project.audioUnits.forEach(unit => {
if (unit.kind !== "output") {unit.sends.forEach(send => targets.add(send.target.uuid))}
})
const unused = project.auxUnits.filter(aux => !targets.has(aux.uuid))
unused.forEach(aux => aux.remove())
note(unused.length, "unused auxiliary units")
if (report.length === 0) {
await openDAW.showInfo("Cleanup", "Nothing to remove.")
} else {
await openDAW.showInfo("Cleanup", report.join("\n"))
project.openInStudio()
}Inventory of the open project
CODE
const project = await openDAW.getProject()
const count = new Map<string, number>()
const add = (name: string, amount: number = 1) => count.set(name, (count.get(name) ?? 0) + amount)
project.audioUnits.forEach(unit => {
add(`${unit.kind} units`)
if (unit.kind === "instrument") {add(`instrument ${unit.instrument.key}`)}
unit.audioEffects.forEach(effect => add(`effect ${effect.key}`))
unit.tracks.forEach(track => {
add(`${track.type} tracks`)
add("regions", track.regions.length)
add("clips", track.clips.length)
})
})
add("modulators", project.modulators.length)
const lines = [...count.entries()].map(([name, amount]) => `${amount} × ${name}`)
await openDAW.showInfo("Inventory", lines.join("\n"))