Skip to content

Commit

Permalink
feat: Get an oscillator wave as an array
Browse files Browse the repository at this point in the history
  • Loading branch information
tambien committed Oct 8, 2019
1 parent 2935f65 commit 9ad519e
Show file tree
Hide file tree
Showing 9 changed files with 79 additions and 10 deletions.
7 changes: 6 additions & 1 deletion Tone/source/oscillator/AMOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ import { Signal } from "../../signal/Signal";
import { Source } from "../Source";
import { Oscillator } from "./Oscillator";
import { AMConstructorOptions, AMOscillatorOptions,
NonCustomOscillatorType, ToneOscillatorInterface,
generateWaveform, NonCustomOscillatorType,
ToneOscillatorInterface,
ToneOscillatorType } from "./OscillatorInterface";

export { AMOscillatorOptions } from "./OscillatorInterface";
Expand Down Expand Up @@ -230,6 +231,10 @@ export class AMOscillator extends Source<AMOscillatorOptions> implements ToneOsc
this._carrier.partials = partials;
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

/**
* Clean up.
*/
Expand Down
6 changes: 5 additions & 1 deletion Tone/source/oscillator/FMOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Signal } from "../../signal/Signal";
import { Source } from "../Source";
import { Oscillator } from "./Oscillator";
import { FMConstructorOptions, FMOscillatorOptions,
NonCustomOscillatorType, ToneOscillatorInterface, ToneOscillatorType } from "./OscillatorInterface";
generateWaveform, NonCustomOscillatorType, ToneOscillatorInterface, ToneOscillatorType } from "./OscillatorInterface";

export { FMOscillatorOptions } from "./OscillatorInterface";
/**
Expand Down Expand Up @@ -245,6 +245,10 @@ export class FMOscillator extends Source<FMOscillatorOptions> implements ToneOsc
this._carrier.partials = partials;
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

/**
* Clean up.
*/
Expand Down
6 changes: 5 additions & 1 deletion Tone/source/oscillator/FatOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Signal } from "../../signal/Signal";
import { Source } from "../Source";
import { Oscillator } from "./Oscillator";
import { FatConstructorOptions, FatOscillatorOptions,
ToneOscillatorInterface, ToneOscillatorType } from "./OscillatorInterface";
generateWaveform, ToneOscillatorInterface, ToneOscillatorType } from "./OscillatorInterface";

export { FatOscillatorOptions } from "./OscillatorInterface";

Expand Down Expand Up @@ -273,6 +273,10 @@ export class FatOscillator extends Source<FatOscillatorOptions> implements ToneO
this._type = this._oscillators[0].type;
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

/**
* Clean up.
*/
Expand Down
10 changes: 7 additions & 3 deletions Tone/source/oscillator/OmniOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import { AMOscillator } from "./AMOscillator";
import { FatOscillator } from "./FatOscillator";
import { FMOscillator } from "./FMOscillator";
import { Oscillator } from "./Oscillator";
import { OmniOscillatorConstructorOptions,
OmniOscillatorOptions, OmniOscillatorType,
ToneOscillatorInterface, ToneOscillatorType } from "./OscillatorInterface";
import { generateWaveform,
OmniOscillatorConstructorOptions, OmniOscillatorOptions,
OmniOscillatorType, ToneOscillatorInterface, ToneOscillatorType } from "./OscillatorInterface";
import { PulseOscillator } from "./PulseOscillator";
import { PWMOscillator } from "./PWMOscillator";

Expand Down Expand Up @@ -474,6 +474,10 @@ export class OmniOscillator<OscType extends AnyOscillator>
}
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

dispose(): this {
super.dispose();
this.detune.dispose();
Expand Down
10 changes: 8 additions & 2 deletions Tone/source/oscillator/Oscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@ import { noOp, readOnly } from "../../core/util/Interface";
import { isDefined } from "../../core/util/TypeCheck";
import { Signal } from "../../signal/Signal";
import { Source } from "../Source";
import { ToneOscillatorConstructorOptions, ToneOscillatorInterface,
import {
generateWaveform,
ToneOscillatorConstructorOptions, ToneOscillatorInterface,
ToneOscillatorOptions, ToneOscillatorType } from "./OscillatorInterface";
import { ToneOscillatorNode } from "./ToneOscillatorNode";

import { OfflineContext } from "../../core/context/OfflineContext";
export { ToneOscillatorOptions, ToneOscillatorType } from "./OscillatorInterface";
/**
* Oscillator supports a number of features including
Expand Down Expand Up @@ -481,6 +483,10 @@ export class Oscillator extends Source<ToneOscillatorOptions> implements ToneOsc
this.type = this._type;
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

dispose(): this {
super.dispose();
if (this._oscillator !== null) {
Expand Down
24 changes: 24 additions & 0 deletions Tone/source/oscillator/OscillatorInterface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { AudioRange, Cents, Degrees, Frequency, Positive } from "../../core/type
import { Omit } from "../../core/util/Interface";
import { Signal } from "../../signal/Signal";
import { SourceOptions } from "../Source";
import { OfflineContext } from "../../core/context/OfflineContext";

/**
* The common interface of all Oscillators
Expand All @@ -14,6 +15,29 @@ export interface ToneOscillatorInterface {
phase: Degrees;
partials: number[];
partialCount?: number;
/**
* Returns an array of values which represents the waveform.
* @param length The length of the waveform to return
*/
asArray(length: number): Promise<Float32Array>;
}

/**
* Render a segment of the oscillator to an offline context and return the results as an array
*/
export async function generateWaveform(instance: any, length: number): Promise<Float32Array> {
const duration = length / instance.context.sampleRate;
const context = new OfflineContext(1, duration, instance.context.sampleRate);
const clone = new instance.constructor(Object.assign(instance.get(), {
// should do 2 iterations
frequency: 2 / duration,
// zero out the detune
detune: 0,
context
})).toDestination();
clone.start(0);
const buffer = await context.render();
return buffer.getChannelData(0);
}

/**
Expand Down
6 changes: 5 additions & 1 deletion Tone/source/oscillator/PWMOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Multiply } from "../../signal/Multiply";
import { Signal } from "../../signal/Signal";
import { Source } from "../Source";
import { Oscillator } from "./Oscillator";
import { PWMOscillatorOptions, ToneOscillatorInterface } from "./OscillatorInterface";
import { generateWaveform, PWMOscillatorOptions, ToneOscillatorInterface } from "./OscillatorInterface";
import { PulseOscillator } from "./PulseOscillator";

export { PWMOscillatorOptions } from "./OscillatorInterface";
Expand Down Expand Up @@ -169,6 +169,10 @@ export class PWMOscillator extends Source<PWMOscillatorOptions> implements ToneO
this._modulator.phase = phase;
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

/**
* Clean up.
*/
Expand Down
6 changes: 5 additions & 1 deletion Tone/source/oscillator/PulseOscillator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Signal } from "../../signal/Signal";
import { WaveShaper } from "../../signal/WaveShaper";
import { Source } from "../Source";
import { Oscillator } from "./Oscillator";
import { PulseOscillatorOptions, ToneOscillatorInterface } from "./OscillatorInterface";
import { generateWaveform, PulseOscillatorOptions, ToneOscillatorInterface } from "./OscillatorInterface";

export { PulseOscillatorOptions } from "./OscillatorInterface";

Expand Down Expand Up @@ -197,6 +197,10 @@ export class PulseOscillator extends Source<PulseOscillatorOptions> implements T
return 0;
}

async asArray(length: number = 1024): Promise<Float32Array> {
return generateWaveform(this, length);
}

/**
* Clean up method.
*/
Expand Down
14 changes: 14 additions & 0 deletions test/helper/OscillatorTests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,5 +60,19 @@ export function OscillatorTests(Constr, args?): void {
expect(buffer.max()).to.be.at.most(1);
});
});

it("can generate a waveform", async () => {
const osc = new Constr();
const waveform = await osc.asArray();
waveform.forEach((v: number) => expect(v).to.be.within(-1, 1));
osc.dispose();
});

it("can generate a waveform of a specific length", async () => {
const osc = new Constr();
const waveform = await osc.asArray(256);
expect(waveform.length).to.equal(256);
osc.dispose();
});
});
}

0 comments on commit 9ad519e

Please sign in to comment.