Skip to content

Commit

Permalink
feat(synths/settings): octaves range setting
Browse files Browse the repository at this point in the history
  • Loading branch information
domi7777 committed Nov 14, 2024
1 parent a7f06ed commit ef5dee6
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 8 deletions.
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"preview": "vite preview"
},
"dependencies": {
"@tweakpane/plugin-essentials": "^0.2.1",
"phaser": "^3.85.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
Expand Down
24 changes: 22 additions & 2 deletions src/scenes/PadsScene.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,35 @@ import {rotateArray} from '../utils/math.ts';
import {hexToColor} from '../utils/colors.ts';
import {FontColor, FontFamily, FontSize} from '../utils/fonts.ts';
import {EVENTS} from '../events.ts';
import {logger} from '../utils/logger.ts';

type Pad = {
instrument: number,
button: Phaser.GameObjects.Rectangle,
text?: Phaser.GameObjects.Text,
}

export type Setting = Partial<Omit<PadsSceneSettings, 'onChange'>>;

export type PadsSceneSettings = {
volume: number;
noteDuration?: number;
octaveRange?: {
min: number;
max: number;
};
onChange?: (setting: Setting) => void;
}

export abstract class PadsScene extends Phaser.Scene {

private pads: Pad[] = [];
readonly settings: PadsSceneSettings = {
volume: 50
volume: 50,
onChange: (setting) => this.onSettingChange(setting),
}

protected constructor(private cols: number, private rows: number) {
protected constructor(protected cols: number, protected rows: number) {
super();
}

Expand All @@ -34,6 +43,12 @@ export abstract class PadsScene extends Phaser.Scene {
this.game.events.emit(EVENTS.sceneChange, this.settings);
}

protected changePadNumber(cols: number, rows: number) {
this.cols = cols;
this.rows = rows;
this.scene.restart();
}

protected createPads() {
const numberOfPads = this.cols * this.rows;
this.pads = new Array(numberOfPads).fill(0).map((_, index) => {
Expand Down Expand Up @@ -130,4 +145,9 @@ export abstract class PadsScene extends Phaser.Scene {
protected getPadText(_index: number): string | undefined {
return undefined;
}

// eslint-disable-next-line @typescript-eslint/no-unused-vars
onSettingChange(_setting: Setting) {
logger.log('Setting changed', _setting);
}
}
39 changes: 35 additions & 4 deletions src/scenes/SimpleSynthScene.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,55 @@
import {PadsScene, PadsSceneSettings} from './PadsScene.ts';
import {PadsScene, PadsSceneSettings, Setting} from './PadsScene.ts';
import {allFrequencies} from '../samples/synth-frequencies.ts';
import {createAudioContext} from '../samples/sample-utils.ts';
import Phaser from 'phaser';
import {logger} from '../utils/logger.ts';

const numberOfNotes = 12;
const maxNumberOfOctaves = 6;
const maxNumberOfPads = numberOfNotes * maxNumberOfOctaves;

export class SimpleSynthScene extends PadsScene {

constructor() {
super(6, 12);
super(maxNumberOfOctaves, numberOfNotes);
this.settings.noteDuration = 1.5;
this.settings.octaveRange = {
min: 1,
max: maxNumberOfOctaves,
};
}

getPadText(index: number) {
const note = allFrequencies[index];
return note?.key;
}

getPadColor(numberOfPads: number, index: number): Phaser.Display.Color {
const color = super.getPadColor(numberOfPads, index);
getPadColor(_numberOfPads: number, index: number): Phaser.Display.Color {
index += this.getNoteIndexOffset();
const color = super.getPadColor(
maxNumberOfPads,
index
);
const key = allFrequencies[index]?.key;
if (key?.includes('#')) {
return color.darken(70);
}
return color.darken(50);
}

/**
* when changing the range of the notes, we need to offset the index to get the correct note
*/
private getNoteIndexOffset() {
return this.getLowerRangeIndex() * numberOfNotes;
}

private getLowerRangeIndex() {
return this.settings.octaveRange!.min - 1;
}

playSound(index: number): void {
index += this.getNoteIndexOffset();
const note = allFrequencies[index].freq;
logger.log('Playing note', note);
// play the sound
Expand All @@ -34,6 +58,13 @@ export class SimpleSynthScene extends PadsScene {
...this.settings
});
}

onSettingChange(setting: Setting) {
super.onSettingChange(setting);
if (setting.octaveRange) {
super.changePadNumber(setting.octaveRange.max + 1 - setting.octaveRange.min, 12);
}
}
}

const playPianoTone = ({ frequency, volume = 50, noteDuration = 1.5 }: { frequency: number } & PadsSceneSettings) => {
Expand Down
27 changes: 25 additions & 2 deletions src/settings/TweakPane.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,28 @@
import Phaser from 'phaser';
import {ButtonApi, Pane} from 'tweakpane';
import * as EssentialsPlugin from '@tweakpane/plugin-essentials';
import {LoopTracksScene} from '../scenes/LoopTracksScene.ts';
import {logger} from '../utils/logger.ts';
import {BindingApi} from '@tweakpane/core';
import {EVENTS} from '../events.ts';
import {PadsSceneSettings} from '../scenes/PadsScene.ts';

type MinMax = { min: number; max: number; };

export class TweakPane {

private static logsParams= {
logs: '',
}
private pane: Pane;
private settings?: PadsSceneSettings;

private sceneControls: {
deleteInstrument?: ButtonApi;
deleteLoop?: ButtonApi;
volume?: BindingApi,
noteDuration?: BindingApi
volume?: BindingApi;
noteDuration?: BindingApi;
octaveRange?: BindingApi<unknown, MinMax>;
} = {};

public static log(message: string) {
Expand All @@ -33,8 +39,16 @@ export class TweakPane {
expanded: false,
container,
});
this.pane.registerPlugin(EssentialsPlugin);
this.pane.on('change', (event) => {
const bindingKey = (event.target as any).key as string;
if (this.settings && event.last && bindingKey in this.settings) {
this.settings.onChange?.({[bindingKey]: event.value});
}
});
game.events.on(EVENTS.sceneChange, (settings?: PadsSceneSettings) => {
this.deleteSettings();
this.settings = settings;
if (settings) {
this.addSettings(settings);
}
Expand Down Expand Up @@ -85,6 +99,15 @@ export class TweakPane {
index
});
}
if (settings.octaveRange) {
this.sceneControls.octaveRange = this.pane.addBinding(settings, 'octaveRange', {
label: 'Octave range',
min: 1,
max: 6,
step: 1,
index
});
}
this.sceneControls.volume = this.pane.addBinding(settings, 'volume', {
min: 0,
max: 100,
Expand Down

0 comments on commit ef5dee6

Please sign in to comment.