Trying to do better but it's hard
This commit is contained in:
1
csound-live-code
Submodule
1
csound-live-code
Submodule
Submodule csound-live-code added at 71b9973520
@ -31,6 +31,7 @@
|
||||
FileStack,
|
||||
PanelLeftOpen,
|
||||
PanelRightOpen,
|
||||
CircleStop,
|
||||
} from "lucide-svelte";
|
||||
|
||||
const appContext = createAppContext();
|
||||
@ -44,7 +45,7 @@
|
||||
uiState,
|
||||
executionContext,
|
||||
} = appContext;
|
||||
const csoundDerived = createCsoundDerivedStores(csound);
|
||||
const { logs: csoundLogs, initialized, compiled, running } = createCsoundDerivedStores(csound);
|
||||
|
||||
let analyserNode = $state<AnalyserNode | null>(null);
|
||||
let interpreterLogs = $state<LogEntry[]>([]);
|
||||
@ -91,9 +92,27 @@
|
||||
projectEditor.loadProject(projectToLoad);
|
||||
}
|
||||
|
||||
logsUnsubscribe = csoundDerived.logs.subscribe((logs) => {
|
||||
logsUnsubscribe = csoundLogs.subscribe((logs) => {
|
||||
interpreterLogs = logs;
|
||||
});
|
||||
|
||||
const handleKeyDown = (e: KeyboardEvent) => {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === '.') {
|
||||
e.preventDefault();
|
||||
handleStop();
|
||||
}
|
||||
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
|
||||
e.preventDefault();
|
||||
handleSave();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
});
|
||||
|
||||
onDestroy(async () => {
|
||||
@ -220,6 +239,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
async function handleStop() {
|
||||
try {
|
||||
await csound.stop();
|
||||
} catch (error) {
|
||||
console.error("Failed to stop:", error);
|
||||
}
|
||||
}
|
||||
|
||||
$effect(() => {
|
||||
if (uiState.scopePopupVisible || uiState.spectrogramPopupVisible) {
|
||||
analyserNode = csound.getAnalyserNode();
|
||||
@ -281,6 +308,14 @@
|
||||
<div class="app-container">
|
||||
<TopBar title="OldBoy">
|
||||
{#snippet leftActions()}
|
||||
<button
|
||||
onclick={handleStop}
|
||||
class="icon-button stop-button"
|
||||
disabled={!$running}
|
||||
title="Stop audio (Ctrl+.)"
|
||||
>
|
||||
<CircleStop size={18} />
|
||||
</button>
|
||||
<button
|
||||
class="icon-button"
|
||||
onclick={handleNewFromTemplate}
|
||||
@ -292,8 +327,8 @@
|
||||
class="icon-button"
|
||||
onclick={handleSave}
|
||||
disabled={!projectEditor.hasUnsavedChanges}
|
||||
title="Save {projectEditor.hasUnsavedChanges
|
||||
? '(unsaved changes)'
|
||||
title="Save (Ctrl+S){projectEditor.hasUnsavedChanges
|
||||
? ' - unsaved changes'
|
||||
: ''}"
|
||||
class:has-changes={projectEditor.hasUnsavedChanges}
|
||||
>
|
||||
@ -537,6 +572,15 @@
|
||||
color: #646cff;
|
||||
}
|
||||
|
||||
.icon-button.stop-button:not(:disabled) {
|
||||
color: #ff6b6b;
|
||||
}
|
||||
|
||||
.icon-button.stop-button:hover:not(:disabled) {
|
||||
color: #ff5252;
|
||||
border-color: #ff5252;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin-top: 0;
|
||||
color: rgba(255, 255, 255, 0.87);
|
||||
|
||||
@ -42,6 +42,7 @@
|
||||
const lineNumbersCompartment = new Compartment();
|
||||
const lineWrappingCompartment = new Compartment();
|
||||
const vimCompartment = new Compartment();
|
||||
const languageCompartment = new Compartment();
|
||||
|
||||
function handleExecute() {
|
||||
if (!editorView) return;
|
||||
@ -111,11 +112,13 @@
|
||||
|
||||
const initSettings = $editorSettings;
|
||||
|
||||
const fileType = mode === 'livecoding' ? 'orc' : 'csd';
|
||||
|
||||
editorView = new EditorView({
|
||||
doc: value,
|
||||
extensions: [
|
||||
...baseExtensions,
|
||||
csoundMode({ fileType: 'csd' }),
|
||||
languageCompartment.of(csoundMode({ fileType })),
|
||||
oneDark,
|
||||
evaluateKeymap,
|
||||
flashField(),
|
||||
@ -154,6 +157,15 @@
|
||||
editorView.dom.style.fontFamily = settings.fontFamily;
|
||||
});
|
||||
|
||||
$effect(() => {
|
||||
if (!editorView) return;
|
||||
|
||||
const fileType = mode === 'livecoding' ? 'orc' : 'csd';
|
||||
editorView.dispatch({
|
||||
effects: languageCompartment.reconfigure(csoundMode({ fileType }))
|
||||
});
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (editorView) {
|
||||
editorView.destroy();
|
||||
|
||||
@ -1,13 +1,10 @@
|
||||
import { Csound } from '@csound/browser';
|
||||
|
||||
export type InstanceMode = 'persistent' | 'ephemeral';
|
||||
|
||||
export interface CsoundEngineOptions {
|
||||
onMessage?: (message: string) => void;
|
||||
onError?: (error: string) => void;
|
||||
onPerformanceEnd?: () => void;
|
||||
onAnalyserNodeCreated?: (node: AnalyserNode) => void;
|
||||
instanceMode?: InstanceMode;
|
||||
}
|
||||
|
||||
export interface PerformanceMetrics {
|
||||
@ -30,16 +27,15 @@ export class CsoundEngine {
|
||||
private scopeNode: AnalyserNode | null = null;
|
||||
private audioNode: AudioNode | null = null;
|
||||
private audioContext: AudioContext | null = null;
|
||||
private instanceMode: InstanceMode;
|
||||
|
||||
constructor(options: CsoundEngineOptions = {}) {
|
||||
this.options = options;
|
||||
this.instanceMode = options.instanceMode ?? 'ephemeral';
|
||||
}
|
||||
|
||||
async init(): Promise<void> {
|
||||
if (this.initialized) return;
|
||||
|
||||
await this.ensureCsoundInstance();
|
||||
this.initialized = true;
|
||||
this.log('Csound ready');
|
||||
}
|
||||
@ -49,10 +45,51 @@ export class CsoundEngine {
|
||||
this.log('Creating Csound instance...');
|
||||
this.csound = await Csound();
|
||||
this.setupCallbacks();
|
||||
await this.csound.setOption('-odac');
|
||||
}
|
||||
}
|
||||
|
||||
async restart(): Promise<void> {
|
||||
this.log('Restarting Csound...');
|
||||
|
||||
if (this.running) {
|
||||
await this.stop();
|
||||
}
|
||||
|
||||
if (this.csound) {
|
||||
try {
|
||||
await this.csound.reset();
|
||||
} catch (error) {
|
||||
this.log('Reset failed, creating new instance...');
|
||||
await this.cleanupInstance();
|
||||
await this.ensureCsoundInstance();
|
||||
}
|
||||
} else {
|
||||
await this.ensureCsoundInstance();
|
||||
}
|
||||
|
||||
await this.csound!.setOption('-m0');
|
||||
await this.csound!.setOption('-odac');
|
||||
await this.csound!.setOption('-+msg_color=false');
|
||||
await this.csound!.setOption('--daemon');
|
||||
|
||||
const ac = await this.csound!.getAudioContext();
|
||||
const sampleRate = ac?.sampleRate || 48000;
|
||||
|
||||
const header = `sr = ${sampleRate}\nksmps = 32\n0dbfs = 1\nnchnls = 2\nnchnls_i = 1`;
|
||||
|
||||
const compileResult = await this.csound!.compileOrc(header);
|
||||
if (compileResult !== 0) {
|
||||
throw new Error('Failed to compile base header');
|
||||
}
|
||||
|
||||
await this.csound!.start();
|
||||
|
||||
this.compiled = true;
|
||||
this.running = true;
|
||||
this.setupAnalyser();
|
||||
this.log('Csound restarted and ready');
|
||||
}
|
||||
|
||||
private setupCallbacks(): void {
|
||||
if (!this.csound) return;
|
||||
|
||||
@ -78,11 +115,13 @@ export class CsoundEngine {
|
||||
throw new Error('Csound not initialized. Call init() first.');
|
||||
}
|
||||
|
||||
try {
|
||||
await this.ensureCsoundInstance();
|
||||
if (!this.csound) {
|
||||
throw new Error('No Csound instance available');
|
||||
}
|
||||
|
||||
try {
|
||||
this.log('Compiling orchestra...');
|
||||
const result = await this.csound!.compileOrc(orchestra);
|
||||
const result = await this.csound.compileOrc(orchestra);
|
||||
|
||||
if (result !== 0) {
|
||||
const errorMsg = 'Orchestra compilation failed';
|
||||
@ -135,7 +174,7 @@ export class CsoundEngine {
|
||||
await this.csound!.readScore(event);
|
||||
}
|
||||
|
||||
async evaluateCode(code: string, forceNewInstance = false): Promise<void> {
|
||||
async evaluateCode(code: string): Promise<void> {
|
||||
if (!this.initialized) {
|
||||
throw new Error('Csound not initialized. Call init() first.');
|
||||
}
|
||||
@ -145,22 +184,10 @@ export class CsoundEngine {
|
||||
await this.stop();
|
||||
}
|
||||
|
||||
const needsNewInstance = forceNewInstance ||
|
||||
this.instanceMode === 'ephemeral' ||
|
||||
!this.csound;
|
||||
|
||||
if (needsNewInstance && this.csound) {
|
||||
this.log('Destroying existing instance...');
|
||||
await this.cleanupInstance();
|
||||
} else if (this.csound && this.compiled) {
|
||||
this.log('Resetting Csound for new performance...');
|
||||
await this.resetForNewPerformance();
|
||||
}
|
||||
await this.restart();
|
||||
|
||||
this.scopeNode = null;
|
||||
|
||||
await this.ensureCsoundInstance();
|
||||
|
||||
const orcMatch = code.match(/<CsInstruments>([\s\S]*?)<\/CsInstruments>/);
|
||||
const scoMatch = code.match(/<CsScore>([\s\S]*?)<\/CsScore>/);
|
||||
|
||||
@ -171,13 +198,12 @@ export class CsoundEngine {
|
||||
const orc = orcMatch[1].trim();
|
||||
const sco = scoMatch[1].trim();
|
||||
|
||||
const compileResult = await this.compileOrchestra(orc);
|
||||
if (!compileResult.success) {
|
||||
throw new Error(compileResult.errorMessage || 'Compilation failed');
|
||||
}
|
||||
await this.csound!.compileOrc(orc);
|
||||
this.compiled = true;
|
||||
|
||||
if (sco) {
|
||||
await this.readScore(sco);
|
||||
await this.startPerformance();
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
this.running = false;
|
||||
@ -298,31 +324,6 @@ export class CsoundEngine {
|
||||
}
|
||||
}
|
||||
|
||||
async reset(): Promise<void> {
|
||||
this.log('Resetting Csound...');
|
||||
await this.stop();
|
||||
await this.cleanupInstance();
|
||||
this.compiled = false;
|
||||
await this.ensureCsoundInstance();
|
||||
this.log('Reset complete');
|
||||
}
|
||||
|
||||
private async resetForNewPerformance(): Promise<void> {
|
||||
if (!this.csound) return;
|
||||
|
||||
try {
|
||||
await this.csound.reset();
|
||||
await this.csound.setOption('-odac');
|
||||
this.compiled = false;
|
||||
this.running = false;
|
||||
this.audioNode = null;
|
||||
this.audioContext = null;
|
||||
this.scopeNode = null;
|
||||
} catch (error) {
|
||||
this.log('Reset failed, creating new instance...');
|
||||
await this.cleanupInstance();
|
||||
}
|
||||
}
|
||||
|
||||
private async cleanupInstance(): Promise<void> {
|
||||
if (!this.csound) return;
|
||||
|
||||
@ -78,6 +78,10 @@ export class ExecutionContext {
|
||||
await this.endSession();
|
||||
this.currentMode = newMode;
|
||||
this.strategy = this.createStrategyForMode(newMode);
|
||||
|
||||
if (newMode === 'composition') {
|
||||
await this.csound.stop();
|
||||
}
|
||||
}
|
||||
|
||||
private createStrategyForMode(mode: ProjectMode): ExecutionStrategy {
|
||||
|
||||
@ -25,7 +25,6 @@ export class CompositionStrategy implements ExecutionStrategy {
|
||||
|
||||
export class LiveCodingStrategy implements ExecutionStrategy {
|
||||
private isInitialized = false;
|
||||
private headerCompiled = false;
|
||||
|
||||
async execute(
|
||||
csound: CsoundStore,
|
||||
@ -34,95 +33,40 @@ export class LiveCodingStrategy implements ExecutionStrategy {
|
||||
source: EvalSource
|
||||
): Promise<void> {
|
||||
if (!this.isInitialized) {
|
||||
await this.initializeFromDocument(csound, fullContent);
|
||||
await csound.restart();
|
||||
this.isInitialized = true;
|
||||
return;
|
||||
}
|
||||
|
||||
await this.evaluateBlock(csound, code);
|
||||
}
|
||||
|
||||
private async initializeFromDocument(
|
||||
csound: CsoundStore,
|
||||
fullContent: string
|
||||
): Promise<void> {
|
||||
const { header, instruments, score } = this.parseCSD(fullContent);
|
||||
|
||||
const fullOrchestra = header + '\n' + instruments;
|
||||
const compileResult = await csound.compileOrchestra(fullOrchestra);
|
||||
|
||||
if (!compileResult.success) {
|
||||
throw new Error(compileResult.errorMessage || 'Compilation failed');
|
||||
}
|
||||
|
||||
this.headerCompiled = true;
|
||||
|
||||
await csound.startPerformance();
|
||||
|
||||
if (score.trim()) {
|
||||
await csound.readScore(score);
|
||||
}
|
||||
}
|
||||
|
||||
private async evaluateBlock(csound: CsoundStore, code: string): Promise<void> {
|
||||
const trimmedCode = code.trim();
|
||||
const filteredCode = this.stripCommentLines(code);
|
||||
|
||||
if (!trimmedCode) return;
|
||||
if (!filteredCode.trim()) return;
|
||||
|
||||
if (this.isScoreEvent(trimmedCode)) {
|
||||
await csound.sendScoreEvent(trimmedCode);
|
||||
if (this.isScoreEvent(filteredCode)) {
|
||||
await csound.sendScoreEvent(filteredCode);
|
||||
}
|
||||
else if (this.isInstrumentDefinition(trimmedCode)) {
|
||||
await csound.compileOrchestra(trimmedCode);
|
||||
}
|
||||
else if (this.isChannelSet(trimmedCode)) {
|
||||
await this.handleChannelSet(csound, trimmedCode);
|
||||
else if (this.isChannelSet(filteredCode)) {
|
||||
await this.handleChannelSet(csound, filteredCode);
|
||||
}
|
||||
else {
|
||||
await csound.compileOrchestra(trimmedCode);
|
||||
await csound.compileOrchestra(filteredCode);
|
||||
}
|
||||
}
|
||||
|
||||
private parseCSD(content: string): {
|
||||
header: string;
|
||||
instruments: string;
|
||||
score: string
|
||||
} {
|
||||
const orcMatch = content.match(/<CsInstruments>([\s\S]*?)<\/CsInstruments>/);
|
||||
if (!orcMatch) {
|
||||
return { header: '', instruments: '', score: '' };
|
||||
}
|
||||
|
||||
const orchestra = orcMatch[1].trim();
|
||||
|
||||
const scoMatch = content.match(/<CsScore>([\s\S]*?)<\/CsScore>/);
|
||||
const score = scoMatch ? scoMatch[1].trim() : '';
|
||||
|
||||
const instrMatch = orchestra.match(/([\s\S]*?)(instr\s+\d+[\s\S]*)/);
|
||||
|
||||
if (instrMatch) {
|
||||
return {
|
||||
header: instrMatch[1].trim(),
|
||||
instruments: instrMatch[2].trim(),
|
||||
score
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
header: orchestra,
|
||||
instruments: '',
|
||||
score
|
||||
};
|
||||
private stripCommentLines(code: string): string {
|
||||
return code
|
||||
.split('\n')
|
||||
.filter(line => !line.trim().startsWith(';'))
|
||||
.join('\n');
|
||||
}
|
||||
|
||||
private isScoreEvent(code: string): boolean {
|
||||
return /^[ifea]\s+[\d\-]/.test(code);
|
||||
}
|
||||
|
||||
private isInstrumentDefinition(code: string): boolean {
|
||||
return /^\s*instr\s+/.test(code);
|
||||
}
|
||||
|
||||
private isChannelSet(code: string): boolean {
|
||||
return /^\w+\s*=\s*[\d\.\-]+/.test(code);
|
||||
}
|
||||
@ -139,7 +83,6 @@ export class LiveCodingStrategy implements ExecutionStrategy {
|
||||
|
||||
reset(): void {
|
||||
this.isInitialized = false;
|
||||
this.headerCompiled = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
import { writable, derived, get } from 'svelte/store';
|
||||
import { CsoundEngine, type InstanceMode, type PerformanceMetrics, type CompilationResult } from './engine';
|
||||
import { writable, derived } from 'svelte/store';
|
||||
import { CsoundEngine, type PerformanceMetrics, type CompilationResult } from './engine';
|
||||
|
||||
export interface LogEntry {
|
||||
timestamp: Date;
|
||||
@ -21,9 +21,9 @@ export interface CsoundStore {
|
||||
startPerformance: () => Promise<void>;
|
||||
readScore: (score: string) => Promise<void>;
|
||||
sendScoreEvent: (event: string) => Promise<void>;
|
||||
evaluate: (code: string, forceNewInstance?: boolean) => Promise<void>;
|
||||
evaluate: (code: string) => Promise<void>;
|
||||
stop: () => Promise<void>;
|
||||
reset: () => Promise<void>;
|
||||
restart: () => Promise<void>;
|
||||
setControlChannel: (name: string, value: number) => Promise<void>;
|
||||
getControlChannel: (name: string) => Promise<number>;
|
||||
setStringChannel: (name: string, value: string) => Promise<void>;
|
||||
@ -41,7 +41,7 @@ export interface CsoundStore {
|
||||
destroy: () => Promise<void>;
|
||||
}
|
||||
|
||||
export function createCsoundStore(instanceMode?: InstanceMode): CsoundStore {
|
||||
export function createCsoundStore(): CsoundStore {
|
||||
const initialState: CsoundState = {
|
||||
initialized: false,
|
||||
compiled: false,
|
||||
@ -76,8 +76,7 @@ export function createCsoundStore(instanceMode?: InstanceMode): CsoundStore {
|
||||
},
|
||||
onAnalyserNodeCreated: (node) => {
|
||||
analyserNodeListeners.forEach(listener => listener(node));
|
||||
},
|
||||
instanceMode
|
||||
}
|
||||
});
|
||||
|
||||
await engine.init();
|
||||
@ -140,13 +139,13 @@ export function createCsoundStore(instanceMode?: InstanceMode): CsoundStore {
|
||||
await engine.sendScoreEvent(event);
|
||||
},
|
||||
|
||||
async evaluate(code: string, forceNewInstance = false) {
|
||||
async evaluate(code: string) {
|
||||
if (!engine) {
|
||||
throw new Error('Csound engine not initialized');
|
||||
}
|
||||
|
||||
try {
|
||||
await engine.evaluateCode(code, forceNewInstance);
|
||||
await engine.evaluateCode(code);
|
||||
update(state => ({
|
||||
...state,
|
||||
compiled: engine!.isCompiled(),
|
||||
@ -172,14 +171,14 @@ export function createCsoundStore(instanceMode?: InstanceMode): CsoundStore {
|
||||
}
|
||||
},
|
||||
|
||||
async reset() {
|
||||
async restart() {
|
||||
if (!engine) return;
|
||||
|
||||
try {
|
||||
await engine.reset();
|
||||
update(state => ({ ...state, compiled: false, running: false }));
|
||||
await engine.restart();
|
||||
update(state => ({ ...state, compiled: true, running: true }));
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Reset failed';
|
||||
const errorMsg = error instanceof Error ? error.message : 'Restart failed';
|
||||
addLog(errorMsg, 'error');
|
||||
}
|
||||
},
|
||||
|
||||
@ -80,14 +80,57 @@ export function getLine(state: EditorState): EvalBlock {
|
||||
return { text, from, to };
|
||||
}
|
||||
|
||||
type BlockType = 'instr' | 'endin' | 'opcode' | 'endop' | null;
|
||||
|
||||
function startsWithBlockMarker(text: string): BlockType {
|
||||
const trimmed = text.trim();
|
||||
if (/^\s*instr\b/.test(text)) return 'instr';
|
||||
if (/^\s*endin\b/.test(text)) return 'endin';
|
||||
if (/^\s*opcode\b/.test(text)) return 'opcode';
|
||||
if (/^\s*endop\b/.test(text)) return 'endop';
|
||||
return null;
|
||||
}
|
||||
|
||||
function findBlockMarker(
|
||||
doc: any,
|
||||
startLine: number,
|
||||
direction: number,
|
||||
limit: number
|
||||
): [number, BlockType] | null {
|
||||
for (let i = startLine; direction > 0 ? i <= limit : i >= limit; i += direction) {
|
||||
if (i < 1 || i > doc.lines) break;
|
||||
const lineText = doc.line(i).text;
|
||||
const marker = startsWithBlockMarker(lineText);
|
||||
if (marker) {
|
||||
return [i, marker];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function getBlock(state: EditorState): EvalBlock {
|
||||
let { doc, selection } = state;
|
||||
let { text, number } = state.doc.lineAt(selection.main.from);
|
||||
|
||||
if (text.trim().length === 0) return { text: '', from: null, to: null };
|
||||
|
||||
let fromL, toL;
|
||||
fromL = toL = number;
|
||||
const prevBlockMark = findBlockMarker(doc, number, -1, 1);
|
||||
const nextBlockMark = findBlockMarker(doc, number, 1, doc.lines);
|
||||
|
||||
if (
|
||||
prevBlockMark &&
|
||||
nextBlockMark &&
|
||||
((prevBlockMark[1] === 'instr' && nextBlockMark[1] === 'endin') ||
|
||||
(prevBlockMark[1] === 'opcode' && nextBlockMark[1] === 'endop'))
|
||||
) {
|
||||
const { from } = doc.line(prevBlockMark[0]);
|
||||
const { to } = doc.line(nextBlockMark[0]);
|
||||
text = state.doc.sliceString(from, to);
|
||||
return { text, from, to };
|
||||
}
|
||||
|
||||
let fromL = number;
|
||||
let toL = number;
|
||||
|
||||
while (fromL > 1 && doc.line(fromL - 1).text.trim().length > 0) {
|
||||
fromL -= 1;
|
||||
|
||||
@ -71,19 +71,11 @@ const LIVECODING_TEMPLATE: CsoundTemplate = {
|
||||
id: 'livecoding',
|
||||
name: 'Live Coding',
|
||||
mode: 'livecoding',
|
||||
content: `<CsoundSynthesizer>
|
||||
<CsOptions>
|
||||
-odac
|
||||
</CsOptions>
|
||||
<CsInstruments>
|
||||
|
||||
sr = 48000
|
||||
ksmps = 32
|
||||
nchnls = 2
|
||||
0dbfs = 1
|
||||
|
||||
; Press Cmd/Ctrl+E on the full document first to initialize
|
||||
; Then evaluate individual blocks to trigger sounds
|
||||
content: `; LIVE CODING MODE
|
||||
; Engine auto-initializes on first evaluation (Ctrl+E)
|
||||
; Evaluate instruments/opcodes with Ctrl+E to define them
|
||||
; Evaluate score events (i-statements) to trigger sounds
|
||||
; Press Ctrl+. to stop all audio
|
||||
|
||||
gaReverb init 0
|
||||
|
||||
@ -119,14 +111,12 @@ instr 99
|
||||
gaReverb = 0
|
||||
endin
|
||||
|
||||
</CsInstruments>
|
||||
<CsScore>
|
||||
; Start reverb (always on)
|
||||
i 99 0 -1
|
||||
</CsScore>
|
||||
</CsoundSynthesizer>
|
||||
|
||||
|
||||
; LIVE CODING EXAMPLES
|
||||
; === LIVE CODING EXAMPLES ===
|
||||
; Select a block and press Ctrl+E to evaluate
|
||||
|
||||
; Basic note
|
||||
i 1 0 2 440 0.3
|
||||
@ -146,7 +136,7 @@ i 2 1.5 0.5 130.81 0.4
|
||||
; Long note for channel control
|
||||
i 1 0 30 440 0.3
|
||||
|
||||
; Change frequency while playing
|
||||
; Change frequency while playing (select and evaluate)
|
||||
freq = 440
|
||||
|
||||
freq = 554.37
|
||||
|
||||
Reference in New Issue
Block a user