Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // Oscillator.ts
- import { SAMPLE_RATE } from "./globals";
- export enum OscillatorMode {
- OSCILLATOR_MODE_SINE,
- OSCILLATOR_MODE_SAW,
- OSCILLATOR_MODE_SQUARE,
- OSCILLATOR_MODE_TRIANGLE,
- }
- export type FrequencyFunction = (sample_i: number) => number;
- export type OscillatorArgs = {
- oscillator_mode?: OscillatorMode;
- frequency?: number;
- phase?: number;
- frequency_function?: FrequencyFunction;
- sample_rate?: number;
- };
- export class Oscillator {
- oscillator_mode: OscillatorMode;
- frequency: number;
- phase: number;
- sample_rate: number;
- frequency_function: FrequencyFunction;
- phase_increment: number;
- constructor({
- oscillator_mode = OscillatorMode.OSCILLATOR_MODE_SINE,
- frequency = 440,
- phase = 0,
- frequency_function = () => frequency,
- sample_rate = SAMPLE_RATE,
- }: OscillatorArgs) {
- this.oscillator_mode = oscillator_mode;
- this.frequency = frequency;
- this.phase = phase;
- this.sample_rate = sample_rate;
- this.frequency_function = frequency_function;
- this.phase_increment = (this.frequency * 2 * Math.PI) / this.sample_rate;
- }
- set_mode(mode: OscillatorMode) {
- this.oscillator_mode = mode;
- }
- set_frequency(frequency: number) {
- this.frequency = frequency;
- this.update_increment();
- }
- set_sample_rate(sample_rate: number) {
- this.sample_rate = sample_rate;
- this.update_increment();
- }
- next_sample() {
- const value = this.naive_wave_form(this.oscillator_mode);
- this.phase += this.phase_increment;
- while (this.phase >= 2 * Math.PI) {
- this.phase -= 2 * Math.PI;
- }
- // console.log(value);
- return value;
- }
- generate(buffer: AudioBuffer) {
- for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
- // This gives us the actual array that contains the data
- const now_buffering = buffer.getChannelData(channel);
- for (let sample_i = 0; sample_i < buffer.length; sample_i++) {
- const next_frequency = this.frequency_function(sample_i);
- if (this.frequency !== next_frequency) {
- this.set_frequency(next_frequency);
- }
- now_buffering[sample_i] = this.next_sample();
- }
- }
- }
- naive_wave_form(oscillator_mode: OscillatorMode) {
- let buffer_value = 0;
- switch (oscillator_mode) {
- case OscillatorMode.OSCILLATOR_MODE_SINE:
- buffer_value = Math.sin(this.phase);
- break;
- case OscillatorMode.OSCILLATOR_MODE_SAW:
- buffer_value = (2 * this.phase) / (2 * Math.PI) - 1;
- break;
- case OscillatorMode.OSCILLATOR_MODE_SQUARE:
- buffer_value = this.phase <= Math.PI ? 1 : -1;
- break;
- case OscillatorMode.OSCILLATOR_MODE_TRIANGLE:
- const value = -1 + (2 * this.phase) / (2 * Math.PI);
- buffer_value = 2 * (Math.abs(value) - 0.5);
- break;
- default:
- break;
- }
- return buffer_value;
- }
- update_increment() {
- this.phase_increment = (this.frequency * 2 * Math.PI) / this.sample_rate;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment