mirror of
https://github.com/monkeytypegame/monkeytype.git
synced 2026-01-09 00:45:32 +08:00
yyyriyriy ppp[i6riy (#3603) Bruception
* Add new synth click sounds * Use key codes instead * Fix Sound preview * Check for caps lock * Add new quote - imperial march
This commit is contained in:
parent
4f146ae5a8
commit
e6a8747d41
7 changed files with 235 additions and 3 deletions
|
|
@ -75,7 +75,9 @@ const CONFIG_SCHEMA = joi.object({
|
|||
singleListCommandLine: joi.string().valid("manual", "on"),
|
||||
capsLockWarning: joi.boolean(),
|
||||
playSoundOnError: joi.boolean(),
|
||||
playSoundOnClick: joi.string().valid("off", ..._.range(1, 8).map(_.toString)),
|
||||
playSoundOnClick: joi
|
||||
.string()
|
||||
.valid("off", ..._.range(1, 11).map(_.toString)),
|
||||
soundVolume: joi.string().valid("0.1", "0.5", "1.0"),
|
||||
startGraphsAtZero: joi.boolean(),
|
||||
showOutOfFocusWarning: joi.boolean(),
|
||||
|
|
|
|||
|
|
@ -97,6 +97,54 @@ const subgroup: MonkeyTypes.CommandsSubgroup = {
|
|||
SoundController.playClick();
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setSoundOnClick8",
|
||||
display: "sine",
|
||||
configValue: "8",
|
||||
hover: (): void => {
|
||||
SoundController.playNote("KeyQ", "sine");
|
||||
},
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnClick("8");
|
||||
SoundController.playNote("KeyQ", "sine");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setSoundOnClick9",
|
||||
display: "sawtooth",
|
||||
configValue: "9",
|
||||
hover: (): void => {
|
||||
SoundController.playNote("KeyQ", "sawtooth");
|
||||
},
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnClick("9");
|
||||
SoundController.playNote("KeyQ", "sawtooth");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setSoundOnClick10",
|
||||
display: "square",
|
||||
configValue: "10",
|
||||
hover: (): void => {
|
||||
SoundController.playNote("KeyQ", "square");
|
||||
},
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnClick("10");
|
||||
SoundController.playNote("KeyQ", "square");
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "setSoundOnClick11",
|
||||
display: "triangle",
|
||||
configValue: "11",
|
||||
hover: (): void => {
|
||||
SoundController.playNote("KeyQ", "triangle");
|
||||
},
|
||||
exec: (): void => {
|
||||
UpdateConfig.setPlaySoundOnClick("11");
|
||||
SoundController.playNote("KeyQ", "triangle");
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ export function setPlaySoundOnClick(
|
|||
): boolean {
|
||||
if (
|
||||
!isConfigValueValid("play sound on click", val, [
|
||||
["off", "1", "2", "3", "4", "5", "6", "7"],
|
||||
["off", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11"],
|
||||
])
|
||||
) {
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -2,6 +2,8 @@ import Config from "../config";
|
|||
import Howler, { Howl } from "howler";
|
||||
import * as ConfigEvent from "../observables/config-event";
|
||||
import { randomElementFromArray } from "../utils/misc";
|
||||
import { leftState, rightState } from "../test/shift-tracker";
|
||||
import { capsState } from "../test/caps-warning";
|
||||
|
||||
interface ClickSounds {
|
||||
[key: string]: {
|
||||
|
|
@ -233,8 +235,134 @@ export function previewClick(val: string): void {
|
|||
(clickSounds as ClickSounds)[val][0].sounds[0].play();
|
||||
}
|
||||
|
||||
let currentCode = "KeyA";
|
||||
|
||||
$(document).on("keydown", (event) => {
|
||||
currentCode = event.code || "KeyA";
|
||||
});
|
||||
|
||||
const notes = {
|
||||
C: [16.35, 32.7, 65.41, 130.81, 261.63, 523.25, 1046.5, 2093.0, 4186.01],
|
||||
Db: [17.32, 34.65, 69.3, 138.59, 277.18, 554.37, 1108.73, 2217.46, 4434.92],
|
||||
D: [18.35, 36.71, 73.42, 146.83, 293.66, 587.33, 1174.66, 2349.32, 4698.64],
|
||||
Eb: [19.45, 38.89, 77.78, 155.56, 311.13, 622.25, 1244.51, 2489.02, 4978.03],
|
||||
E: [20.6, 41.2, 82.41, 164.81, 329.63, 659.26, 1318.51, 2637.02],
|
||||
F: [21.83, 43.65, 87.31, 174.61, 349.23, 698.46, 1396.91, 2793.83],
|
||||
Gb: [23.12, 46.25, 92.5, 185.0, 369.99, 739.99, 1479.98, 2959.96],
|
||||
G: [24.5, 49.0, 98.0, 196.0, 392.0, 783.99, 1567.98, 3135.96],
|
||||
Ab: [25.96, 51.91, 103.83, 207.65, 415.3, 830.61, 1661.22, 3322.44],
|
||||
A: [27.5, 55.0, 110.0, 220.0, 440.0, 880.0, 1760.0, 3520.0],
|
||||
Bb: [29.14, 58.27, 116.54, 233.08, 466.16, 932.33, 1864.66, 3729.31],
|
||||
B: [30.87, 61.74, 123.47, 246.94, 493.88, 987.77, 1975.53, 3951.07],
|
||||
};
|
||||
|
||||
type GetNoteFrequencyCallback = (octave: number) => number;
|
||||
|
||||
function bindToNote(
|
||||
noteFrequencies: number[],
|
||||
octaveOffset = 0
|
||||
): GetNoteFrequencyCallback {
|
||||
return (octave: number): number => {
|
||||
return noteFrequencies[octave + octaveOffset];
|
||||
};
|
||||
}
|
||||
|
||||
const codeToNote: Record<string, GetNoteFrequencyCallback> = {
|
||||
KeyZ: bindToNote(notes.C),
|
||||
KeyS: bindToNote(notes.Db),
|
||||
KeyX: bindToNote(notes.D),
|
||||
KeyD: bindToNote(notes.Eb),
|
||||
KeyC: bindToNote(notes.E),
|
||||
KeyV: bindToNote(notes.F),
|
||||
KeyG: bindToNote(notes.Gb),
|
||||
KeyB: bindToNote(notes.G),
|
||||
KeyH: bindToNote(notes.Ab),
|
||||
KeyN: bindToNote(notes.A),
|
||||
KeyJ: bindToNote(notes.Bb),
|
||||
KeyM: bindToNote(notes.B),
|
||||
Comma: bindToNote(notes.C, 1),
|
||||
KeyL: bindToNote(notes.Db, 1),
|
||||
Period: bindToNote(notes.D, 1),
|
||||
Semicolon: bindToNote(notes.Eb, 1),
|
||||
Slash: bindToNote(notes.E, 1),
|
||||
KeyQ: bindToNote(notes.C, 1),
|
||||
Digit2: bindToNote(notes.Db, 1),
|
||||
KeyW: bindToNote(notes.D, 1),
|
||||
Digit3: bindToNote(notes.Eb, 1),
|
||||
KeyE: bindToNote(notes.E, 1),
|
||||
KeyR: bindToNote(notes.F, 1),
|
||||
Digit5: bindToNote(notes.Gb, 1),
|
||||
KeyT: bindToNote(notes.G, 1),
|
||||
Digit6: bindToNote(notes.Ab, 1),
|
||||
KeyY: bindToNote(notes.A, 1),
|
||||
Digit7: bindToNote(notes.Bb, 1),
|
||||
KeyU: bindToNote(notes.B, 1),
|
||||
KeyI: bindToNote(notes.C, 2),
|
||||
Digit9: bindToNote(notes.Db, 2),
|
||||
KeyO: bindToNote(notes.D, 2),
|
||||
Digit0: bindToNote(notes.Eb, 2),
|
||||
KeyP: bindToNote(notes.E, 2),
|
||||
BracketLeft: bindToNote(notes.F, 2),
|
||||
Equal: bindToNote(notes.Gb, 2),
|
||||
BracketRight: bindToNote(notes.G, 2),
|
||||
};
|
||||
|
||||
type DynamicClickSounds = Extract<
|
||||
MonkeyTypes.PlaySoundOnClick,
|
||||
"8" | "9" | "10" | "11"
|
||||
>;
|
||||
type SupportedOscillatorTypes = Exclude<OscillatorType, "custom">;
|
||||
|
||||
const clickSoundIdsToOscillatorType: Record<
|
||||
DynamicClickSounds,
|
||||
SupportedOscillatorTypes
|
||||
> = {
|
||||
"8": "sine",
|
||||
"9": "sawtooth",
|
||||
"10": "square",
|
||||
"11": "triangle",
|
||||
};
|
||||
|
||||
const audioCtx = new AudioContext();
|
||||
|
||||
export function playNote(
|
||||
codeOverride?: string,
|
||||
oscillatorTypeOverride?: SupportedOscillatorTypes
|
||||
): void {
|
||||
currentCode = codeOverride ?? currentCode;
|
||||
if (!(currentCode in codeToNote)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const baseOctave = 3;
|
||||
const octave = baseOctave + (leftState || rightState || capsState ? 1 : 0);
|
||||
const currentFrequency = codeToNote[currentCode](octave);
|
||||
|
||||
const oscillatorNode = audioCtx.createOscillator();
|
||||
const gainNode = audioCtx.createGain();
|
||||
|
||||
oscillatorNode.type =
|
||||
oscillatorTypeOverride ??
|
||||
clickSoundIdsToOscillatorType[
|
||||
Config.playSoundOnClick as DynamicClickSounds
|
||||
];
|
||||
gainNode.gain.value = parseFloat(Config.soundVolume) / 10;
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(audioCtx.destination);
|
||||
|
||||
oscillatorNode.frequency.value = currentFrequency;
|
||||
oscillatorNode.start(audioCtx.currentTime);
|
||||
oscillatorNode.stop(audioCtx.currentTime + 0.15);
|
||||
}
|
||||
|
||||
export function playClick(): void {
|
||||
if (Config.playSoundOnClick === "off") return;
|
||||
if (Config.playSoundOnClick in clickSoundIdsToOscillatorType) {
|
||||
playNote();
|
||||
return;
|
||||
}
|
||||
|
||||
if (clickSounds === null) init();
|
||||
|
||||
const randomSound = randomElementFromArray(
|
||||
|
|
|
|||
18
frontend/src/ts/types/types.d.ts
vendored
18
frontend/src/ts/types/types.d.ts
vendored
|
|
@ -87,8 +87,24 @@ declare namespace MonkeyTypes {
|
|||
5 = typewriter
|
||||
6 = osu
|
||||
7 = hitmarker
|
||||
8 = sine
|
||||
9 = sawtooth
|
||||
10 = square
|
||||
11 = triangle
|
||||
*/
|
||||
type PlaySoundOnClick = "off" | "1" | "2" | "3" | "4" | "5" | "6" | "7";
|
||||
type PlaySoundOnClick =
|
||||
| "off"
|
||||
| "1"
|
||||
| "2"
|
||||
| "3"
|
||||
| "4"
|
||||
| "5"
|
||||
| "6"
|
||||
| "7"
|
||||
| "8"
|
||||
| "9"
|
||||
| "10"
|
||||
| "11";
|
||||
|
||||
type SoundVolume = "0.1" | "0.5" | "1.0";
|
||||
|
||||
|
|
|
|||
|
|
@ -894,6 +894,38 @@
|
|||
>
|
||||
hitmarker
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnClick="8"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
sine
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnClick="9"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
sawtooth
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnClick="10"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
square
|
||||
</div>
|
||||
<div
|
||||
class="button"
|
||||
playSoundOnClick="11"
|
||||
tabindex="0"
|
||||
onclick="this.blur();"
|
||||
>
|
||||
triangle
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section playSoundOnError">
|
||||
|
|
|
|||
|
|
@ -35466,6 +35466,12 @@
|
|||
"source": "Fight Club",
|
||||
"length": 827,
|
||||
"id": 6231
|
||||
},
|
||||
{
|
||||
"text": "yyy riy riy ppp [i6 riy",
|
||||
"source": "John Williams - The Imperial March",
|
||||
"length": 23,
|
||||
"id": 6232
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue