Skip to content

Commit

Permalink
Merge pull request #73 from crucialfelix/feature/dryads-static-methods
Browse files Browse the repository at this point in the history
feat: dryads static methods
  • Loading branch information
crucialfelix authored Dec 6, 2019
2 parents f96f51f + 78481d7 commit 79f759e
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 25 deletions.
26 changes: 10 additions & 16 deletions examples/sine-wave.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,17 @@
const d = require("supercolliderjs").dryads;
const { SCLang, SCServer, Synth, dryadic } = require("supercolliderjs").dryads;

/**
* This is the full tree required just to play a Sin wave.
* Dryadic 2 will
* Minimal Sin wave example.
*
* To compile the SuperCollider language synth def it requires a
* SCLang. To play the Synth it requires a SCServer.
*/
const out = new d.SCLang({}, [
new d.SCServer({ numInputBusChannels: 0 }, [
new d.Synth({
def: new d.SCSynthDef({
source: `
{ arg freq;
Out.ar(0, SinOsc.ar(freq))
}`,
}),
args: {
freq: 440,
},
const out = new SCLang({}, [
new SCServer({}, [
Synth.fromSource(`|freq| SinOsc.ar(freq)`, {
freq: 440,
}),
]),
]);

d.dryadic(out).play();
dryadic(out).play();
21 changes: 18 additions & 3 deletions packages/dryads/src/SCSynthDef.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ const StateKeys = {
* `synthDef` is returned from compilation by sclang and
* is set in the context for children Dryads to access.
*/
interface CompiledSynthDef {
export interface CompiledSynthDef {
name: string;
bytes: Buffer;
// object with descriptive meta data
synthDesc: SynthDesc;
}
interface LoadedSynthDef {
export interface LoadedSynthDef {
name: string;
}
export type SynthDef = CompiledSynthDef | LoadedSynthDef;
Expand Down Expand Up @@ -56,6 +56,19 @@ interface Context {
* Note that the synthDefName is not known until after the source code is compiled.
*/
export default class SCSynthDef extends Dryad<Properties> {
static fromSource(source: string): SCSynthDef {
return new SCSynthDef({
source,
watch: false,
});
}
static fromFile(path: string): SCSynthDef {
return new SCSynthDef({
compileFrom: path,
watch: true,
});
}

defaultProperties(): Properties {
return { watch: false };
}
Expand Down Expand Up @@ -144,8 +157,10 @@ export default class SCSynthDef extends Dryad<Properties> {
* Returns a Promise for a SynthDef result object: name, bytes, synthDesc
*/
async compileSource(context: Context, sourceCode: string, pathName?: string): Promise<CompiledSynthDef> {
// add surrounding { } to any expressions that start with arg or |
const autoBraced = /^ *arg|\|/.test(sourceCode) ? `{ ${sourceCode} }` : sourceCode;
const wrappedCode = `{
var def = { ${sourceCode} }.value.asSynthDef;
var def = { ${autoBraced} }.value.asSynthDef;
(
name: def.name,
synthDesc: def.asSynthDesc.asJSON(),
Expand Down
28 changes: 24 additions & 4 deletions packages/dryads/src/Synth.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Dryad, Command } from "dryadic";
import Server, { msg, OscType, updateNodeState, whenNodeEnd, whenNodeGo } from "@supercollider/server";
import { Command, Dryad } from "dryadic";
import _ from "lodash";

import Server, { OscType, updateNodeState, whenNodeEnd, whenNodeGo, msg } from "@supercollider/server";
import { SynthDef } from "./SCSynthDef";
import SynthDef, { CompiledSynthDef, LoadedSynthDef } from "./SCSynthDef";

const { AddActions, nodeFree, synthNew } = msg;

Expand All @@ -12,7 +12,7 @@ interface SynthParams {

interface Properties {
args: SynthParams;
def: SynthDef | string;
def: SynthDef | CompiledSynthDef | LoadedSynthDef | string;
}
interface Context {
id: string;
Expand All @@ -30,6 +30,26 @@ interface Context {
* - args
*/
export default class Synth extends Dryad<Properties> {
/**
* Make a Synth that will play the SynthDef compiled from sclang source code.
*
* source may be fully defined:
* `SynthDef("defName", { |out=0, freq=440| Out.ar(SinOsc.ar(freq)) });`
* or more simply:
* `{|freq| SinOsc.ar(freq)}`
* or even just:
* `|freq| SinOsc.ar(freq)`
*/
static fromSource(source: string, args: SynthParams = {}): Synth {
return new Synth({ def: SynthDef.fromSource(source), args });
}
/**
* Make a Synth that will play the SynthDef compiled from an *.scd source code file
*/
static fromFile(path: string, args: SynthParams = {}): Synth {
return new Synth({ def: SynthDef.fromFile(path), args });
}

/**
* If there is no SCServer in the parent context,
* then this will wrap itself in an SCServer
Expand Down
5 changes: 3 additions & 2 deletions packages/server/src/osc/msg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,9 @@ function flattenPairs(pairs: PairsType): OscType[] {
if (_.isArray(pairs)) {
return _.flatten(pairs);
}
// unreachable
throw new Error(`Unmatched type: ${pairs}`);
throw new TypeError(
`Received ${typeof pairs} ${JSON.stringify(pairs)}. Expected \{key: value, ...\} or [[key, value],...]`,
);
}

/**
Expand Down

0 comments on commit 79f759e

Please sign in to comment.