I have built a browser synthesizer with next.js. Everything seems to work ok but the oscillators act weird. Every time I initialize the oscillator after a refresh, it will play until I change something and then nothing. I thought that it had something to do with re-rendering and the audio context but I used a package called react-frequency and what i tried to do worked well in their example.
this is my page.tsx file -
"use client";
import H1 from "@/components/H1";
import SynthControls from "@/components/SynthControls";
import SynthLayout from "@/components/SynthLayout";
import { getFrequencyOfNoteInHz, synthNotes } from "@/lib/constants";
import { useEffect, useState } from "react";
import { Frequency } from "react-frequency";
export default function BassSynth() {
const [isPlaying, setIsPlaying] = useState(false);
const [currentPitch, setCurrentPitch] = useState("C1");
const [isInitialized, setIsInitialized] = useState(false);
const [osc1Waveform, setOsc1Waveform] = useState<TWaveForm>("sawtooth");
const [osc2Waveform, setOsc2Waveform] = useState<TWaveForm>("sawtooth");
const [oscMix, setOscMix] = useState(0.5);
const currentHzPitch = getFrequencyOfNoteInHz(currentPitch);
// event listener for the keyboard
useEffect(() => {
const handleKeyDown = (event: KeyboardEvent) => {
const keyPressed = synthNotes.find(
(element) => element.keyboardKey === event.key.toUpperCase()
);
if (keyPressed) {
setCurrentPitch(keyPressed.note);
setIsPlaying(true);
} else {
return;
}
};
const handleKeyUp = () => {
setIsPlaying(false);
};
document.addEventListener("keydown", handleKeyDown);
document.addEventListener("keyup", handleKeyUp);
return () => {
document.removeEventListener("keydown", handleKeyDown);
document.removeEventListener("keyup", handleKeyUp);
};
}, []);
return (
<main className="flex flex-col items-center p-10">
<H1 className="mb-4">SJS Bass-1</H1>
<SynthLayout
synthColor="red-900"
setIsPlaying={setIsPlaying}
setCurrentPitch={setCurrentPitch}
currentPitch={currentPitch}
isPlaying={isPlaying}
/>
<SynthControls
setIsInitialized={setIsInitialized}
isInitialized={isInitialized}
setOsc1Waveform={setOsc1Waveform}
setOsc2Waveform={setOsc2Waveform}
setOscMix={setOscMix}
/>
{isInitialized && (
<>
<Frequency
hz={currentHzPitch}
gain={isPlaying ? 1 - oscMix : 0}
oscillator={osc1Waveform}
/>
<Frequency
hz={currentHzPitch}
gain={isPlaying ? oscMix : 0}
oscillator={osc2Waveform}
/>
</>
)}
</main>
);
}
The other components simply do as their names suggest. there is an ON button in which sets isInitialized to true so the audio context won't complain about a user gesture
thanks a lot!