Skip to main content
Csound’s JavaScript bindings allow you to run Csound in web browsers and Node.js environments using WebAssembly. This enables interactive audio applications, web-based DAWs, and real-time synthesis directly in the browser.

Installation

For browser

Install via npm:
npm install @csound/browser
Or use a CDN:
<script src="https://unpkg.com/@csound/browser"></script>

For Node.js

npm install @csound/node

Browser usage

Basic setup

import { Csound } from '@csound/browser';

async function initCsound() {
    // Create Csound instance
    const csound = await Csound();
    
    console.log('Csound initialized');
    
    // Get version
    const version = await csound.getVersion();
    console.log(`Csound version: ${version}`);
    
    return csound;
}

initCsound();

Configuration options

const csound = await Csound({
    // Use existing AudioContext
    audioContext: myAudioContext,
    
    // Audio I/O configuration
    inputChannelCount: 2,
    outputChannelCount: 2,
    
    // Auto-connect to audio destination
    autoConnect: true,
    
    // Use Web Worker for better performance
    useWorker: true,
    
    // Use SharedArrayBuffer if available
    useSAB: true,
    
    // Load plugins
    withPlugins: ['libfluidsynth.wasm']
});

Compiling and performing

const csound = await Csound();

// Define orchestra
const orc = `
sr = 44100
ksmps = 64
nchnls = 2
0dbfs = 1

instr 1
    kfreq = p4
    asig oscils 0.5, kfreq, 0
    outs asig, asig
endin
`;

// Compile orchestra
await csound.compileOrc(orc);

// Start audio processing
await csound.start();

// Send score event
await csound.inputMessage('i 1 0 2 440');

// Start performance (non-blocking)
await csound.perform();

console.log('Playing...');

Loading CSD files

const csound = await Csound();

// Write CSD to virtual filesystem
const csdContent = `
<CsoundSynthesizer>
<CsOptions>
-odac
</CsOptions>
<CsInstruments>
sr = 44100
ksmps = 64
nchnls = 2
0dbfs = 1

instr 1
    asig oscils 0.5, 440, 0
    outs asig, asig
endin
</CsInstruments>
<CsScore>
i 1 0 2
</CsScore>
</CsoundSynthesizer>
`;

await csound.fs.writeFile('myfile.csd', csdContent);

// Compile and perform
await csound.compileCSD('myfile.csd');
await csound.start();
await csound.perform();

Channels

Control channels

const csound = await Csound();

const orc = `
instr 1
    kfreq chnget "frequency"
    kvol chnget "volume"
    asig oscils kvol, kfreq, 0
    outs asig, asig
    
    kout = kfreq * 2
    chnset kout, "output"
endin
`;

await csound.compileOrc(orc);
await csound.start();
await csound.inputMessage('i 1 0 3600');
await csound.perform();

// Set control channels
await csound.setControlChannel('frequency', 440);
await csound.setControlChannel('volume', 0.8);

// Read control channel
const output = await csound.getControlChannel('output');
console.log(`Output: ${output}`);

// Update in real-time
setInterval(async () => {
    const freq = 440 + Math.random() * 100;
    await csound.setControlChannel('frequency', freq);
}, 100);

String channels

await csound.setStringChannel('message', 'Hello from JavaScript!');
const msg = await csound.getStringChannel('message');
console.log(msg);

File system operations

Virtual file system

Csound WebAssembly uses an in-memory virtual file system:
const csound = await Csound();

// Write file
await csound.fs.writeFile('myfile.txt', 'Hello, Csound!');

// Read file
const content = await csound.fs.readFile('myfile.txt', { encoding: 'utf8' });
console.log(content);

// Check if file exists
const exists = await csound.fs.exists('myfile.txt');
console.log(`File exists: ${exists}`);

// List directory
const files = await csound.fs.readdir('/');
console.log('Files:', files);

// Create directory
await csound.fs.mkdir('/samples');

// Remove file
await csound.fs.unlink('myfile.txt');

Loading audio files

// Fetch audio file
const response = await fetch('sample.wav');
const arrayBuffer = await response.arrayBuffer();
const audioData = new Uint8Array(arrayBuffer);

// Write to virtual filesystem
await csound.fs.writeFile('sample.wav', audioData);

// Use in Csound
const orc = `
instr 1
    asig diskin2 "sample.wav", 1
    outs asig, asig
endin
`;

await csound.compileOrc(orc);
await csound.start();
await csound.inputMessage('i 1 0 5');
await csound.perform();

Audio input

Microphone input

const csound = await Csound({
    inputChannelCount: 2,
    outputChannelCount: 2
});

// Request microphone access
const stream = await navigator.mediaDevices.getUserMedia({ 
    audio: {
        echoCancellation: false,
        noiseSuppression: false,
        autoGainControl: false
    } 
});

// Enable audio input
await csound.enableAudioInput(stream);

// Process microphone input
const orc = `
sr = 44100
ksmps = 64
nchnls = 2
nchnls_i = 2
0dbfs = 1

instr 1
    ain1, ain2 ins
    ; Add reverb
    aL, aR reverbsc ain1, ain2, 0.85, 8000
    outs aL, aR
endin
`;

await csound.compileOrc(orc);
await csound.start();
await csound.inputMessage('i 1 0 3600');
await csound.perform();

MIDI support

MIDI input

const csound = await Csound();

const orc = `
sr = 44100
ksmps = 64
nchnls = 2
0dbfs = 1
massign 0, 1

instr 1
    ifreq cpsmidi
    iamp ampmidi 1
    asig oscils iamp * 0.5, ifreq, 0
    asig *= linsegr:a(0, 0.01, 1, 0.1, 0)
    outs asig, asig
endin
`;

await csound.compileOrc(orc);
await csound.start();
await csound.perform();

// Request MIDI access
const midiAccess = await navigator.requestMIDIAccess();

// Handle MIDI messages
midiAccess.inputs.forEach(input => {
    input.onmidimessage = async (event) => {
        const [status, data1, data2] = event.data;
        
        // Send to Csound
        await csound.midiMessage(status, data1, data2);
    };
});

Tables

Creating and reading tables

const csound = await Csound();

// Create table
const orc = 'giSine ftgen 1, 0, 1024, 10, 1';
await csound.compileOrc(orc);
await csound.start();

// Get table length
const length = await csound.tableLength(1);
console.log(`Table length: ${length}`);

// Get table data
const tableData = await csound.getTable(1);
console.log('First 10 values:', tableData.slice(0, 10));

// Visualize table
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;

ctx.clearRect(0, 0, width, height);
ctx.beginPath();
ctx.moveTo(0, height / 2);

for (let i = 0; i < tableData.length; i++) {
    const x = (i / tableData.length) * width;
    const y = height / 2 - (tableData[i] * height / 2);
    ctx.lineTo(x, y);
}

ctx.strokeStyle = '#4CAF50';
ctx.lineWidth = 2;
ctx.stroke();

Writing tables

// Create empty table
await csound.compileOrc('giTable ftgen 1, 0, 1024, 7, 0, 1024, 0');
await csound.start();

// Generate data
const size = 1024;
const data = new Float64Array(size);
for (let i = 0; i < size; i++) {
    data[i] = Math.sin(2 * Math.PI * i / size);
}

// Write to table
await csound.setTable(1, data);

Event handling

Message callback

const csound = await Csound();

// Set message callback
await csound.setMessageCallback((message) => {
    console.log('Csound:', message);
});

await csound.compileOrc(`
print "Hello from Csound!"
print 123
`);

Performance events

const csound = await Csound();

// Listen for performance events
csound.on('realtimePerformanceStarted', () => {
    console.log('Performance started');
});

csound.on('realtimePerformanceEnded', () => {
    console.log('Performance ended');
});

csound.on('realtimePerformancePaused', () => {
    console.log('Performance paused');
});

csound.on('realtimePerformanceResumed', () => {
    console.log('Performance resumed');
});

Complete example

<!DOCTYPE html>
<html>
<head>
    <title>Csound WebAssembly Demo</title>
</head>
<body>
    <h1>Interactive Synthesizer</h1>
    
    <button id="initBtn">Initialize Csound</button>
    <button id="playBtn" disabled>Play Note</button>
    
    <div>
        <label>Frequency: <span id="freqValue">440</span> Hz</label>
        <input type="range" id="freqSlider" min="200" max="800" value="440" disabled>
    </div>
    
    <div>
        <label>Filter: <span id="filterValue">2000</span> Hz</label>
        <input type="range" id="filterSlider" min="200" max="5000" value="2000" disabled>
    </div>
    
    <div id="output"></div>
    
    <script type="module">
        import { Csound } from 'https://unpkg.com/@csound/browser';
        
        let csound;
        
        const output = document.getElementById('output');
        const initBtn = document.getElementById('initBtn');
        const playBtn = document.getElementById('playBtn');
        const freqSlider = document.getElementById('freqSlider');
        const freqValue = document.getElementById('freqValue');
        const filterSlider = document.getElementById('filterSlider');
        const filterValue = document.getElementById('filterValue');
        
        function log(msg) {
            output.innerHTML += msg + '<br>';
            output.scrollTop = output.scrollHeight;
        }
        
        initBtn.addEventListener('click', async () => {
            log('Initializing Csound...');
            
            try {
                csound = await Csound({
                    autoConnect: true,
                    useWorker: true
                });
                
                const version = await csound.getVersion();
                log(`Csound version: ${version}`);
                
                // Define orchestra
                const orc = `
                sr = 44100
                ksmps = 64
                nchnls = 2
                0dbfs = 1
                
                instr 1
                    kfreq chnget "freq"
                    kfilt chnget "filter"
                    
                    asig vco2 0.5, kfreq
                    asig moogladder asig, kfilt, 0.7
                    asig *= linsegr:a(0, 0.01, 1, 0.1, 0)
                    
                    outs asig, asig
                endin
                `;
                
                await csound.compileOrc(orc);
                await csound.start();
                await csound.perform();
                
                // Set initial values
                await csound.setControlChannel('freq', 440);
                await csound.setControlChannel('filter', 2000);
                
                log('Csound ready!');
                
                // Enable controls
                initBtn.disabled = true;
                playBtn.disabled = false;
                freqSlider.disabled = false;
                filterSlider.disabled = false;
                
            } catch (error) {
                log(`Error: ${error.message}`);
            }
        });
        
        playBtn.addEventListener('click', async () => {
            await csound.inputMessage('i 1 0 1');
            log('Playing note...');
        });
        
        freqSlider.addEventListener('input', async (e) => {
            const freq = parseFloat(e.target.value);
            freqValue.textContent = freq;
            if (csound) {
                await csound.setControlChannel('freq', freq);
            }
        });
        
        filterSlider.addEventListener('input', async (e) => {
            const filter = parseFloat(e.target.value);
            filterValue.textContent = filter;
            if (csound) {
                await csound.setControlChannel('filter', filter);
            }
        });
    </script>
</body>
</html>

Node.js usage

import { Csound } from '@csound/node';

async function main() {
    const csound = await Csound();
    
    const orc = `
    sr = 44100
    ksmps = 64
    nchnls = 2
    0dbfs = 1
    
    instr 1
        asig oscils 0.5, 440, 0
        outs asig, asig
    endin
    `;
    
    await csound.setOption('-odac');
    await csound.compileOrc(orc);
    await csound.start();
    await csound.inputMessage('i 1 0 2');
    await csound.perform();
    
    console.log('Done');
}

main();

Performance considerations

Web Worker

For best performance, use Web Workers:
const csound = await Csound({
    useWorker: true,  // Run in separate thread
    useSAB: true      // Use SharedArrayBuffer if available
});

Buffer sizes

Adjust buffer sizes for your use case:
const orc = `
sr = 44100
ksmps = 128    ; Larger for lower CPU, higher latency
nchnls = 2
0dbfs = 1
`;

AudioContext

Reuse existing AudioContext:
const audioContext = new AudioContext({ latencyHint: 'interactive' });

const csound = await Csound({
    audioContext: audioContext
});

Browser compatibility

  • Chrome/Edge: Full support including SharedArrayBuffer
  • Firefox: Full support
  • Safari: Limited support (no SharedArrayBuffer in some versions)
  • Mobile browsers: Supported with limitations
Always test across target browsers.

Next steps

Examples

Browse JavaScript examples

Web IDE

Try Csound in your browser

C API reference

Understand the underlying API

npm package

@csound/browser on npm