Let's fucking go
This commit is contained in:
@ -3,6 +3,7 @@ import { Csound } from '@csound/browser';
|
||||
export interface CsoundEngineOptions {
|
||||
onMessage?: (message: string) => void;
|
||||
onError?: (error: string) => void;
|
||||
onPerformanceEnd?: () => void;
|
||||
}
|
||||
|
||||
export class CsoundEngine {
|
||||
@ -10,6 +11,9 @@ export class CsoundEngine {
|
||||
private initialized = false;
|
||||
private running = false;
|
||||
private options: CsoundEngineOptions;
|
||||
private scopeNode: AnalyserNode | null = null;
|
||||
private audioNode: AudioNode | null = null;
|
||||
private audioContext: AudioContext | null = null;
|
||||
|
||||
constructor(options: CsoundEngineOptions = {}) {
|
||||
this.options = options;
|
||||
@ -18,26 +22,12 @@ export class CsoundEngine {
|
||||
async init(): Promise<void> {
|
||||
if (this.initialized) return;
|
||||
|
||||
try {
|
||||
this.csound = await Csound();
|
||||
|
||||
this.csound.on('message', (message: string) => {
|
||||
this.options.onMessage?.(message);
|
||||
});
|
||||
|
||||
await this.csound.setOption('-odac');
|
||||
|
||||
this.initialized = true;
|
||||
this.log('Csound initialized successfully');
|
||||
} catch (error) {
|
||||
const errorMsg = error instanceof Error ? error.message : 'Failed to initialize Csound';
|
||||
this.error(errorMsg);
|
||||
throw error;
|
||||
}
|
||||
this.initialized = true;
|
||||
this.log('Csound ready');
|
||||
}
|
||||
|
||||
async evaluateCode(code: string): Promise<void> {
|
||||
if (!this.initialized || !this.csound) {
|
||||
if (!this.initialized) {
|
||||
throw new Error('Csound not initialized. Call init() first.');
|
||||
}
|
||||
|
||||
@ -46,8 +36,29 @@ export class CsoundEngine {
|
||||
await this.stop();
|
||||
}
|
||||
|
||||
this.log('Resetting Csound...');
|
||||
await this.csound.reset();
|
||||
this.scopeNode = null;
|
||||
|
||||
this.log('Creating new Csound instance...');
|
||||
this.csound = await Csound();
|
||||
|
||||
this.csound.on('message', (message: string) => {
|
||||
this.options.onMessage?.(message);
|
||||
});
|
||||
|
||||
this.csound.on('onAudioNodeCreated', (node: AudioNode) => {
|
||||
this.audioNode = node;
|
||||
this.audioContext = node.context as AudioContext;
|
||||
this.log('Audio node created and captured');
|
||||
});
|
||||
|
||||
this.csound.on('realtimePerformanceEnded', async () => {
|
||||
try {
|
||||
await this.csound?.cleanup();
|
||||
} catch {}
|
||||
this.running = false;
|
||||
this.log('Performance complete');
|
||||
this.options.onPerformanceEnd?.();
|
||||
});
|
||||
|
||||
this.log('Setting audio output...');
|
||||
await this.csound.setOption('-odac');
|
||||
@ -63,22 +74,28 @@ export class CsoundEngine {
|
||||
const sco = scoMatch[1].trim();
|
||||
|
||||
this.log('Compiling orchestra...');
|
||||
await this.csound.compileOrc(orc);
|
||||
const compileResult = await this.csound.compileOrc(orc);
|
||||
|
||||
if (compileResult !== 0) {
|
||||
throw new Error('Failed to compile orchestra');
|
||||
}
|
||||
|
||||
this.log('Reading score...');
|
||||
await this.csound.readScore(sco);
|
||||
|
||||
this.log('Starting...');
|
||||
this.log('Starting performance...');
|
||||
this.running = true;
|
||||
await this.csound.start();
|
||||
|
||||
this.log('Performing...');
|
||||
this.running = true;
|
||||
await this.csound.perform();
|
||||
this.setupAnalyser();
|
||||
|
||||
this.log('Performance complete');
|
||||
this.running = false;
|
||||
} catch (error) {
|
||||
this.running = false;
|
||||
if (this.csound) {
|
||||
try {
|
||||
await this.csound.cleanup();
|
||||
} catch {}
|
||||
}
|
||||
const errorMsg = error instanceof Error ? error.message : 'Evaluation failed';
|
||||
this.error(errorMsg);
|
||||
throw error;
|
||||
@ -89,8 +106,9 @@ export class CsoundEngine {
|
||||
if (!this.csound || !this.running) return;
|
||||
|
||||
try {
|
||||
this.log('Stopping...');
|
||||
await this.csound.stop();
|
||||
await this.csound.reset();
|
||||
await this.csound.cleanup();
|
||||
this.running = false;
|
||||
this.log('Stopped');
|
||||
} catch (error) {
|
||||
@ -107,6 +125,36 @@ export class CsoundEngine {
|
||||
return this.initialized;
|
||||
}
|
||||
|
||||
getAudioContext(): AudioContext | null {
|
||||
return this.audioContext;
|
||||
}
|
||||
|
||||
private setupAnalyser(): void {
|
||||
if (!this.audioNode || !this.audioContext) {
|
||||
this.log('Warning: Audio node not available yet');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
this.scopeNode = this.audioContext.createAnalyser();
|
||||
this.scopeNode.fftSize = 2048;
|
||||
this.scopeNode.smoothingTimeConstant = 0.3;
|
||||
|
||||
this.audioNode.disconnect();
|
||||
this.audioNode.connect(this.scopeNode);
|
||||
this.scopeNode.connect(this.audioContext.destination);
|
||||
|
||||
this.log('Analyser node created and connected');
|
||||
} catch (error) {
|
||||
console.error('Failed to setup analyser:', error);
|
||||
this.log('Error setting up analyser: ' + error);
|
||||
}
|
||||
}
|
||||
|
||||
getAnalyserNode(): AnalyserNode | null {
|
||||
return this.scopeNode;
|
||||
}
|
||||
|
||||
private log(message: string): void {
|
||||
this.options.onMessage?.(message);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user