Guest User

Oscillator.ts

a guest
Nov 12th, 2025
48
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // Oscillator.ts
  2.  
  3. import { SAMPLE_RATE } from "./globals";
  4.  
  5. export enum OscillatorMode {
  6.   OSCILLATOR_MODE_SINE,
  7.   OSCILLATOR_MODE_SAW,
  8.   OSCILLATOR_MODE_SQUARE,
  9.   OSCILLATOR_MODE_TRIANGLE,
  10. }
  11.  
  12. export type FrequencyFunction = (sample_i: number) => number;
  13.  
  14. export type OscillatorArgs = {
  15.   oscillator_mode?: OscillatorMode;
  16.   frequency?: number;
  17.   phase?: number;
  18.   frequency_function?: FrequencyFunction;
  19.   sample_rate?: number;
  20. };
  21.  
  22. export class Oscillator {
  23.   oscillator_mode: OscillatorMode;
  24.   frequency: number;
  25.   phase: number;
  26.   sample_rate: number;
  27.   frequency_function: FrequencyFunction;
  28.   phase_increment: number;
  29.   constructor({
  30.     oscillator_mode = OscillatorMode.OSCILLATOR_MODE_SINE,
  31.     frequency = 440,
  32.     phase = 0,
  33.     frequency_function = () => frequency,
  34.     sample_rate = SAMPLE_RATE,
  35.   }: OscillatorArgs) {
  36.     this.oscillator_mode = oscillator_mode;
  37.     this.frequency = frequency;
  38.     this.phase = phase;
  39.     this.sample_rate = sample_rate;
  40.     this.frequency_function = frequency_function;
  41.     this.phase_increment = (this.frequency * 2 * Math.PI) / this.sample_rate;
  42.   }
  43.   set_mode(mode: OscillatorMode) {
  44.     this.oscillator_mode = mode;
  45.   }
  46.   set_frequency(frequency: number) {
  47.     this.frequency = frequency;
  48.     this.update_increment();
  49.   }
  50.   set_sample_rate(sample_rate: number) {
  51.     this.sample_rate = sample_rate;
  52.     this.update_increment();
  53.   }
  54.   next_sample() {
  55.     const value = this.naive_wave_form(this.oscillator_mode);
  56.     this.phase += this.phase_increment;
  57.     while (this.phase >= 2 * Math.PI) {
  58.       this.phase -= 2 * Math.PI;
  59.     }
  60.     // console.log(value);
  61.     return value;
  62.   }
  63.   generate(buffer: AudioBuffer) {
  64.     for (let channel = 0; channel < buffer.numberOfChannels; channel++) {
  65.       // This gives us the actual array that contains the data
  66.       const now_buffering = buffer.getChannelData(channel);
  67.       for (let sample_i = 0; sample_i < buffer.length; sample_i++) {
  68.         const next_frequency = this.frequency_function(sample_i);
  69.         if (this.frequency !== next_frequency) {
  70.           this.set_frequency(next_frequency);
  71.         }
  72.         now_buffering[sample_i] = this.next_sample();
  73.       }
  74.     }
  75.   }
  76.   naive_wave_form(oscillator_mode: OscillatorMode) {
  77.     let buffer_value = 0;
  78.     switch (oscillator_mode) {
  79.       case OscillatorMode.OSCILLATOR_MODE_SINE:
  80.         buffer_value = Math.sin(this.phase);
  81.         break;
  82.       case OscillatorMode.OSCILLATOR_MODE_SAW:
  83.         buffer_value = (2 * this.phase) / (2 * Math.PI) - 1;
  84.         break;
  85.       case OscillatorMode.OSCILLATOR_MODE_SQUARE:
  86.         buffer_value = this.phase <= Math.PI ? 1 : -1;
  87.         break;
  88.       case OscillatorMode.OSCILLATOR_MODE_TRIANGLE:
  89.         const value = -1 + (2 * this.phase) / (2 * Math.PI);
  90.         buffer_value = 2 * (Math.abs(value) - 0.5);
  91.         break;
  92.       default:
  93.         break;
  94.     }
  95.     return buffer_value;
  96.   }
  97.   update_increment() {
  98.     this.phase_increment = (this.frequency * 2 * Math.PI) / this.sample_rate;
  99.   }
  100. }
  101.  
Advertisement
Add Comment
Please, Sign In to add comment