Skip to content

Commit

Permalink
feat: noise generator example
Browse files Browse the repository at this point in the history
  • Loading branch information
danigb committed Sep 3, 2024
1 parent d124ad4 commit 867b53d
Show file tree
Hide file tree
Showing 22 changed files with 171 additions and 24 deletions.
10 changes: 5 additions & 5 deletions packages/noise/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ export type NoiseInputParams = {
type: ParamInput;
};

export function getNoiseTypes() {
export function getNoiseTypes(): { name: string; value: number }[] {
return [
{ name: "WHITE_RND", value: NoiseType.WHITE_RND },
{ name: "WHITE_FAST", value: NoiseType.WHITE_FAST },
{ name: "PINK_COOPER", value: NoiseType.PINK_COOPER },
{ name: "PINK_LARRY_TRAMMEL", value: NoiseType.PINK_LARRY_TRAMMEL },
{ name: "White Random", value: NoiseType.WHITE_RND },
{ name: "White Fast", value: NoiseType.WHITE_FAST },
{ name: "Pink Cooper", value: NoiseType.PINK_COOPER },
{ name: "Pink Larry Trammel", value: NoiseType.PINK_LARRY_TRAMMEL },
];
}

Expand Down
18 changes: 9 additions & 9 deletions site/.source/index.js

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

File renamed without changes.
File renamed without changes.
File renamed without changes.
18 changes: 13 additions & 5 deletions site/app/components/Selector.tsx → site/components/Selector.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { useEffect, useState } from "react";

export function Selector({
type SelectorValue<T> = T | { name: string; value: T };

export function Selector<T>({
name,
initialValue,
values,
Expand All @@ -9,14 +11,20 @@ export function Selector({
initialize,
}: {
name: string;
values: readonly string[];
onChange: (value: string) => void;
values: readonly SelectorValue<T>[];
onChange: (value: T) => void;
initialValue: string;
selectClassName?: string;
initialize?: boolean;
format?: (value: string) => string;
}) {
const [value, setValue] = useState<string>(initialValue);

const valueOf = (value: SelectorValue<T>) =>
typeof value === "string" ? value : value.value;
const nameOf = (value: SelectorValue<T>) =>
typeof value === "string" ? value : value.name;

useEffect(() => {
if (initialize) {
onChange(initialValue);
Expand All @@ -35,8 +43,8 @@ export function Selector({
onChange(e.target.value);
}}
>
{values.map((type) => (
<option key={type}>{type}</option>
{values.map((value) => (
<option key={valueOf(value)}>{nameOf(value)}</option>
))}
</select>
</>
Expand Down
File renamed without changes.
8 changes: 6 additions & 2 deletions site/content/docs/(sources)/noise.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ title: Noise
description: Noise
---

A Noise generator. Currently only white and pink noise are supported.
import { NoiseExample } from "../../../examples/NoiseExample";

Example:
A Noise generator. Currently only white and pink noise are supported.

```ts
import { registerNoiseWorkletOnce, createNoiseNode, NoiseType } from "synthlet";
Expand All @@ -22,6 +22,10 @@ noise.connect(audioContext.destination);
noise.type.value = NoiseType.PINK_COOPER;
```

## Example

<NoiseExample />

## Parameters

- `type`: The type of noise to generate. Can be one of:
Expand Down
2 changes: 1 addition & 1 deletion site/content/docs/examples.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ title: Examples
description: Some examples
---

import { ClockExample } from "../../app/examples/clock/ClockExample";
import { ClockExample } from "../../examples/clock/ClockExample";

<ClockExample />

Expand Down
103 changes: 103 additions & 0 deletions site/examples/NoiseExample.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
"use client";

import { useState } from "react";
import { createNoiseNode, getNoiseTypes, NoiseWorkletNode } from "synthlet";
import { useSynth } from "./useSynth";

export function NoiseExample() {
return (
<ExampleButton label="Start Noise example">
<NoiseSynthUI />
</ExampleButton>
);
}

function NoiseSynthUI() {
const [selectedNoiseType, setSelectedNoiseType] = useState(0);
const [volume, setVolume] = useState(-60);
const synth = useSynth((context) => new NoiseSynth(context));
if (!synth) return null;

return (
<div className="bg-slate-800 text-white p-2 border border-slate-600 rounded">
<div className="text-xl mb-4">Noise generator example</div>
<div className="flex items-center gap-2">
<div className="w-16 text-right">Type:</div>
<select
className="p-1 rounded bg-slate-700 text-slate-200"
value={selectedNoiseType}
onChange={(e) => {
console.log(e.target.value);
const noiseType = parseInt(e.target.value);
setSelectedNoiseType(noiseType);
synth.noise.type.setValueAtTime(noiseType, 0);
}}
>
{getNoiseTypes().map((type) => (
<option key={type.value} value={type.value}>
{type.name}
</option>
))}
</select>
</div>
<div className="flex items-center gap-2 mt-1">
<div className="w-16 text-right">Volume:</div>
<input
type="range"
className="w-64"
min={-60}
max={0}
step={1}
value={volume}
onChange={(e) => {
const db = e.target.valueAsNumber;
setVolume(db);
const gain = db < -60 ? 0 : Math.pow(10, db / 20);
synth.gain.gain.setValueAtTime(gain, 0);
}}
/>
<div>{volume <= -60 ? "Muted" : volume + "dB"}</div>
</div>
</div>
);
}

class NoiseSynth {
gain: GainNode;
noise: NoiseWorkletNode;
constructor(context: AudioContext) {
this.gain = new GainNode(context, { gain: 0 });

this.noise = createNoiseNode(context, {
type: "White Random",
});
this.noise.connect(this.gain).connect(context.destination);
}

disconnect() {
this.gain.disconnect();
this.noise.disconnect();
}
}

function ExampleButton({
label,
children,
}: {
label: string;
children: React.ReactNode;
}) {
const [show, setShow] = useState(false);
if (show) return children;

return (
<button
className="border border-white p-2 rounded opacity-50"
onClick={() => {
setShow(true);
}}
>
{label}
</button>
);
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { createSynthAudioContext } from "@/app/audio-context";
import { Slider } from "@/app/components/Slider";
import { Slider } from "@/components/Slider";
import { Drum8WorkletNode } from "@synthlet/drum8";
import { useEffect, useState } from "react";
import { ClockWorkletNode, createClockNode, createDrum8Node } from "synthlet";
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
2 changes: 1 addition & 1 deletion site/app/examples/layout.tsx → site/examples/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "../global.css";
import "../app/global.css";

const inter = Inter({ subsets: ["latin"] });

Expand Down
31 changes: 31 additions & 0 deletions site/examples/useSynth.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { createSynthAudioContext } from "@/app/audio-context";
import { useEffect, useState } from "react";

type Synth = {
disconnect: () => void;
};

export function useSynth<T extends Synth>(
createSynth: (context: AudioContext) => T
) {
const [synth, setSynth] = useState<T | null>(null);

useEffect(() => {
console.log("connecting");
let bye = false;
let synth: T;
createSynthAudioContext().then((context) => {
if (bye) return;
synth = createSynth(context);
console.log("connected", synth);
setSynth(synth);
});
return () => {
bye = true;
console.log("disconnecting", synth);
synth?.disconnect();
};
}, []);

return synth;
}
1 change: 1 addition & 0 deletions site/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { createPreset } from "fumadocs-ui/tailwind-plugin";
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./examples/**/*.{ts,tsx}",
"./components/**/*.{ts,tsx}",
"./app/**/*.{ts,tsx}",
"./content/**/*.{md,mdx}",
Expand Down

0 comments on commit 867b53d

Please sign in to comment.