@blibliki/engine
Advanced tools
Comparing version 0.1.16 to 0.1.17
@@ -28,13 +28,8 @@ import MidiDeviceManager from "./MidiDeviceManager"; | ||
static getInstance(): Engine; | ||
initialize(props: InitializeInterface): { | ||
master: { | ||
id: string; | ||
name: string; | ||
type: string; | ||
props: any; | ||
inputs: import(".").IOProps[]; | ||
outputs: import(".").IOProps[]; | ||
}; | ||
}; | ||
registerModule(name: string, type: string, props?: any): { | ||
initialize(props: InitializeInterface): Promise<unknown>; | ||
addModule(params: { | ||
name: string; | ||
type: string; | ||
props?: any; | ||
}): { | ||
id: string; | ||
@@ -47,3 +42,3 @@ name: string; | ||
}; | ||
unregisterModule(id: string): string[]; | ||
removeModule(id: string): string[]; | ||
updateNameModule(id: string, name: string): { | ||
@@ -50,0 +45,0 @@ id: string; |
@@ -29,11 +29,16 @@ import { Context, now, setContext } from "tone"; | ||
initialize(props) { | ||
this.context = new Context(props.context); | ||
setContext(this.context); | ||
this.context.transport.start(); | ||
this.midiDeviceManager = new MidiDeviceManager(); | ||
return { | ||
master: this.master, | ||
}; | ||
return new Promise((resolve) => { | ||
if (this.context) | ||
return resolve({ master: this.master }); | ||
this.context = new Context(props.context); | ||
setContext(this.context); | ||
this.context.transport.start(); | ||
this.midiDeviceManager = new MidiDeviceManager(); | ||
setTimeout(() => { | ||
resolve({ master: this.master }); | ||
}, 0); | ||
}); | ||
} | ||
registerModule(name, type, props = {}) { | ||
addModule(params) { | ||
const { name, type, props = {} } = params; | ||
const audioModule = createModule(name, type, {}); | ||
@@ -45,3 +50,3 @@ audioModule.props = props; | ||
} | ||
unregisterModule(id) { | ||
removeModule(id) { | ||
this.modules[id].dispose(); | ||
@@ -87,3 +92,3 @@ const moduleRouteIds = this.moduleRouteIds(id); | ||
return this._master.serialize(); | ||
const masterProps = this.registerModule("Master", "Master"); | ||
const masterProps = this.addModule({ name: "Master", type: "Master" }); | ||
this._master = this.modules[masterProps.id]; | ||
@@ -102,3 +107,3 @@ return masterProps; | ||
}); | ||
this.modules = { [this._master.id]: this._master }; | ||
this.modules = this._master ? { [this._master.id]: this._master } : {}; | ||
this.routes = {}; | ||
@@ -113,3 +118,5 @@ } | ||
get isStarted() { | ||
return this.context.transport.state === "started" && this._isStarted; | ||
return (this.context !== undefined && | ||
this.context.transport.state === "started" && | ||
this._isStarted); | ||
} | ||
@@ -116,0 +123,0 @@ start() { |
@@ -18,7 +18,5 @@ import { InputNode } from "tone"; | ||
} | ||
export interface ModuleInterface { | ||
export interface ModuleInterface<PropsInterface> { | ||
name: string; | ||
props?: { | ||
[key: string]: any; | ||
}; | ||
props: PropsInterface; | ||
voiceNo?: number; | ||
@@ -31,3 +29,3 @@ } | ||
} | ||
declare class Module<InternalModule extends Connectable, PropsInterface> implements ModuleInterface { | ||
declare class Module<InternalModule extends Connectable, PropsInterface> implements ModuleInterface<PropsInterface> { | ||
static readonly moduleName: string; | ||
@@ -42,3 +40,3 @@ readonly id: string; | ||
_props: PropsInterface; | ||
constructor(internalModule: InternalModule, props: Partial<ModuleInterface>); | ||
constructor(internalModule: InternalModule, props: Partial<ModuleInterface<PropsInterface>>); | ||
set props(value: PropsInterface); | ||
@@ -45,0 +43,0 @@ get props(): PropsInterface; |
@@ -15,2 +15,3 @@ import Module, { DummnyInternalModule } from "./Base"; | ||
private prevNumberOfVoices; | ||
private loop; | ||
constructor(name: string, props: Partial<IDataSequence>); | ||
@@ -17,0 +18,0 @@ get sequences(): IDataSequence[]; |
@@ -1,5 +0,5 @@ | ||
import { now } from "tone"; | ||
import { Loop, now } from "tone"; | ||
import Module, { DummnyInternalModule } from "./Base"; | ||
import MidiEvent from "../MidiEvent"; | ||
import { uniq } from "lodash"; | ||
import { sortBy, uniq } from "lodash"; | ||
import Engine from "../Engine"; | ||
@@ -13,2 +13,3 @@ const InitialProps = () => ({ | ||
prevNumberOfVoices; | ||
loop; | ||
constructor(name, props) { | ||
@@ -26,3 +27,3 @@ super(new DummnyInternalModule(), { | ||
set sequences(value) { | ||
const sequences = value; | ||
const sequences = sortBy(value, (seq) => -seq.time); | ||
this._props = { ...this.props, sequences }; | ||
@@ -35,7 +36,25 @@ this.updateNumberOfVoices(); | ||
return; | ||
this.sequences.forEach((sequence) => { | ||
this.onPartEvent(time + sequence.time, sequence); | ||
}); | ||
Engine.updateRoutes(); | ||
const loopLength = 0.1; | ||
const tempSequences = [...this.sequences]; | ||
const iterate = (maxTime) => { | ||
const sequence = tempSequences.pop(); | ||
if (!sequence) | ||
return; | ||
const seqTime = time + sequence.time; | ||
this.onPartEvent(seqTime, sequence); | ||
if (seqTime > maxTime) | ||
return; | ||
iterate(maxTime); | ||
}; | ||
this.loop = new Loop((t) => { | ||
iterate(time + t + loopLength); | ||
}, loopLength).start(time); | ||
} | ||
stop() { } | ||
stop() { | ||
if (!this.loop) | ||
return; | ||
this.loop.stop(); | ||
this.loop.dispose(); | ||
} | ||
onPartEvent = (time, sequence) => { | ||
@@ -42,0 +61,0 @@ const { voiceNo } = sequence; |
{ | ||
"name": "@blibliki/engine", | ||
"version": "0.1.16", | ||
"version": "0.1.17", | ||
"main": "build/index.js", | ||
@@ -5,0 +5,0 @@ "types": "build/index.d.ts", |
110
README.md
@@ -15,4 +15,114 @@ # Blibliki Engine | ||
## Installing | ||
```bash | ||
npm install @blibliki/engine | ||
``` | ||
## Usage | ||
```JavaScript | ||
import Engine from "@blibliki/engine"; | ||
``` | ||
#### Initialize | ||
`Engine.initialize` returns a promise that resolves when the engine is initialized and ready for use. | ||
```JavaScript | ||
Engine.initialize({ context: { lookAhead: 0.03 } }); | ||
``` | ||
#### Start / Stop | ||
This methods are triggering all audio modules to start or stop | ||
```JavaScript | ||
Engine.start(); | ||
Engine.stop(); | ||
``` | ||
#### Modules | ||
##### AudioModule structure | ||
All audio modules share the shame structure. | ||
The props structure vary per audioModule. | ||
```JavaScript | ||
{ | ||
id: string, | ||
name: string, | ||
props: Object | ||
} | ||
``` | ||
##### Create audio module | ||
```JavaScript | ||
const master = Engine.master; | ||
const osc = Engine.addModule({ name: "Osc", type: "Oscillator" }); | ||
const volume = Engine.addModule({ | ||
name: "Vol", | ||
type: "Volume", | ||
props: { volume: -10 }, | ||
}); | ||
``` | ||
##### Update props | ||
```JavaScript | ||
// Update props | ||
Engine.updatePropsModule(volume.id, { volume: -20 }); | ||
Engine.updatePropsModule(osc.id, { wave: "square", fine: -10 }); | ||
``` | ||
##### Remove audio module | ||
```JavaScript | ||
Engine.removeModule(osc.id); | ||
``` | ||
#### Routes | ||
##### Route structure | ||
```JavaScript | ||
{ | ||
id: string, | ||
sourceId: string, | ||
outputName: string, | ||
destinationId: string, | ||
inputName: string, | ||
} | ||
``` | ||
##### Add Route | ||
```JavaScript | ||
// Connect oscillator out to volume input | ||
const oscVolRoute = Engine.addRoute({ | ||
sourceId: osc.id, | ||
outputName: "output", | ||
destinationId: volume.id, | ||
inputName: "input", | ||
}); | ||
// Connect oscillator out to volume input | ||
const volToMaster = Engine.addRoute({ | ||
sourceId: volume.id, | ||
outputName: "output", | ||
destinationId: master.id, | ||
inputName: "input", | ||
}); | ||
``` | ||
##### Remove route | ||
```JavaScript | ||
Engine.removeRoute(oscVolRoute.id); | ||
``` | ||
## Contributing | ||
As a work-in-progress project, Blibliki Engine actively welcomes contributions and feedback from the community. Whether it's reporting issues, suggesting new features, or submitting code changes, contributors are encouraged to get involved and help shape the future of Blibliki Engine. |
@@ -53,14 +53,20 @@ import { Context, now, setContext } from "tone"; | ||
initialize(props: InitializeInterface) { | ||
this.context = new Context(props.context); | ||
setContext(this.context); | ||
this.context.transport.start(); | ||
return new Promise((resolve) => { | ||
if (this.context) return resolve({ master: this.master }); | ||
this.midiDeviceManager = new MidiDeviceManager(); | ||
this.context = new Context(props.context); | ||
setContext(this.context); | ||
this.context.transport.start(); | ||
return { | ||
master: this.master, | ||
}; | ||
this.midiDeviceManager = new MidiDeviceManager(); | ||
setTimeout(() => { | ||
resolve({ master: this.master }); | ||
}, 0); | ||
}); | ||
} | ||
registerModule(name: string, type: string, props: any = {}) { | ||
addModule(params: { name: string; type: string; props?: any }) { | ||
const { name, type, props = {} } = params; | ||
const audioModule = createModule(name, type, {}); | ||
@@ -75,3 +81,3 @@ audioModule.props = props; | ||
unregisterModule(id: string) { | ||
removeModule(id: string) { | ||
this.modules[id].dispose(); | ||
@@ -130,3 +136,3 @@ const moduleRouteIds = this.moduleRouteIds(id); | ||
const masterProps = this.registerModule("Master", "Master"); | ||
const masterProps = this.addModule({ name: "Master", type: "Master" }); | ||
this._master = this.modules[masterProps.id] as Master; | ||
@@ -150,3 +156,3 @@ | ||
this.modules = { [this._master.id]: this._master }; | ||
this.modules = this._master ? { [this._master.id]: this._master } : {}; | ||
this.routes = {}; | ||
@@ -164,3 +170,7 @@ } | ||
get isStarted() { | ||
return this.context.transport.state === "started" && this._isStarted; | ||
return ( | ||
this.context !== undefined && | ||
this.context.transport.state === "started" && | ||
this._isStarted | ||
); | ||
} | ||
@@ -167,0 +177,0 @@ |
@@ -24,5 +24,5 @@ import { v4 as uuidv4 } from "uuid"; | ||
export interface ModuleInterface { | ||
export interface ModuleInterface<PropsInterface> { | ||
name: string; | ||
props?: { [key: string]: any }; | ||
props: PropsInterface; | ||
voiceNo?: number; | ||
@@ -42,3 +42,3 @@ } | ||
class Module<InternalModule extends Connectable, PropsInterface> | ||
implements ModuleInterface | ||
implements ModuleInterface<PropsInterface> | ||
{ | ||
@@ -56,3 +56,6 @@ static readonly moduleName: string; | ||
constructor(internalModule: InternalModule, props: Partial<ModuleInterface>) { | ||
constructor( | ||
internalModule: InternalModule, | ||
props: Partial<ModuleInterface<PropsInterface>> | ||
) { | ||
this.internalModule = internalModule; | ||
@@ -59,0 +62,0 @@ this.id = uuidv4(); |
@@ -1,2 +0,2 @@ | ||
import { now } from "tone"; | ||
import { Loop, now } from "tone"; | ||
@@ -6,3 +6,3 @@ import Module, { DummnyInternalModule } from "./Base"; | ||
import MidiEvent from "../MidiEvent"; | ||
import { uniq } from "lodash"; | ||
import { sortBy, uniq } from "lodash"; | ||
import Engine from "../Engine"; | ||
@@ -32,2 +32,3 @@ | ||
private prevNumberOfVoices: number; | ||
private loop: Loop; | ||
@@ -49,3 +50,3 @@ constructor(name: string, props: Partial<IDataSequence>) { | ||
set sequences(value: IDataSequence[]) { | ||
const sequences = value; | ||
const sequences = sortBy(value, (seq) => -seq.time); | ||
this._props = { ...this.props, sequences }; | ||
@@ -58,10 +59,29 @@ this.updateNumberOfVoices(); | ||
if (!Engine.isStarted) return; | ||
Engine.updateRoutes(); | ||
this.sequences.forEach((sequence) => { | ||
this.onPartEvent(time + sequence.time, sequence); | ||
}); | ||
const loopLength = 0.1; | ||
const tempSequences = [...this.sequences]; | ||
const iterate = (maxTime: number) => { | ||
const sequence = tempSequences.pop(); | ||
if (!sequence) return; | ||
const seqTime = time + sequence.time; | ||
this.onPartEvent(seqTime, sequence); | ||
if (seqTime > maxTime) return; | ||
iterate(maxTime); | ||
}; | ||
this.loop = new Loop((t) => { | ||
iterate(time + t + loopLength); | ||
}, loopLength).start(time); | ||
} | ||
stop() {} | ||
stop() { | ||
if (!this.loop) return; | ||
this.loop.stop(); | ||
this.loop.dispose(); | ||
} | ||
private onPartEvent = (time: number, sequence: IDataSequence) => { | ||
@@ -68,0 +88,0 @@ const { voiceNo } = sequence; |
@@ -27,3 +27,3 @@ import { Signal } from "tone"; | ||
name, | ||
props: { ...InitialProps, ...props }, | ||
props: { ...InitialProps, ...props } as ModuleInterface, | ||
}); | ||
@@ -30,0 +30,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
222512
5160
128