Skip to content

Commit 77661f6

Browse files
committed
Add doorbell sound
1 parent 1ff2e2b commit 77661f6

File tree

1 file changed

+80
-0
lines changed

1 file changed

+80
-0
lines changed

app/doorbell/page.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ export default function Doorbell() {
1212
const [isRinging, setIsRinging] = useState(false)
1313

1414
const handleDoorbellClick = () => {
15+
playDoorbellSound()
1516
setIsRinging(true)
1617
}
1718

@@ -148,3 +149,82 @@ const AnimatedButtonContent = styled(motion.span)`
148149
font-size: 2rem;
149150
line-height: 1.5;
150151
`
152+
153+
// Constants //
154+
155+
const playDoorbellSound = () => {
156+
try {
157+
const audioContext = new (window.AudioContext || (window as any).webkitAudioContext)()
158+
const now = audioContext.currentTime
159+
160+
const scheduleBellTone = ({
161+
baseFrequency,
162+
startTime,
163+
duration
164+
}: {
165+
baseFrequency: number
166+
startTime: number
167+
duration: number
168+
}) => {
169+
const masterGain = audioContext.createGain()
170+
const shimmerFilter = audioContext.createBiquadFilter()
171+
const resonanceFilter = audioContext.createBiquadFilter()
172+
const delayNode = audioContext.createDelay()
173+
const feedbackGain = audioContext.createGain()
174+
175+
shimmerFilter.type = "highpass"
176+
shimmerFilter.frequency.value = 180
177+
178+
resonanceFilter.type = "bandpass"
179+
resonanceFilter.frequency.value = baseFrequency * 1.3
180+
resonanceFilter.Q.value = 6
181+
182+
delayNode.delayTime.value = 0.42
183+
feedbackGain.gain.value = 0.38
184+
185+
masterGain.connect(shimmerFilter)
186+
shimmerFilter.connect(resonanceFilter)
187+
resonanceFilter.connect(audioContext.destination)
188+
resonanceFilter.connect(delayNode)
189+
delayNode.connect(feedbackGain)
190+
feedbackGain.connect(resonanceFilter)
191+
192+
masterGain.gain.setValueAtTime(0, startTime)
193+
masterGain.gain.linearRampToValueAtTime(0.95, startTime + 0.015)
194+
masterGain.gain.setValueAtTime(0.92, startTime + 0.18)
195+
masterGain.gain.exponentialRampToValueAtTime(0.000005, startTime + duration)
196+
197+
const partials = [
198+
{ ratio: 1, gain: 1 },
199+
{ ratio: 1.99, gain: 0.42 },
200+
{ ratio: 2.54, gain: 0.3 },
201+
{ ratio: 3.01, gain: 0.2 },
202+
{ ratio: 3.96, gain: 0.14 },
203+
{ ratio: 5.43, gain: 0.08 }
204+
]
205+
206+
partials.forEach(({ ratio, gain }) => {
207+
const osc = audioContext.createOscillator()
208+
const partialGain = audioContext.createGain()
209+
210+
osc.type = "sine"
211+
osc.frequency.value = baseFrequency * ratio
212+
osc.detune.value = (Math.random() - 0.5) * 6
213+
partialGain.gain.value = gain
214+
215+
osc.connect(partialGain)
216+
partialGain.connect(masterGain)
217+
218+
osc.start(startTime)
219+
osc.stop(startTime + duration + 0.8)
220+
})
221+
}
222+
223+
// Ding (higher chime) followed by Dong (lower chime) with longer resonance
224+
scheduleBellTone({ baseFrequency: 659, startTime: now, duration: 4 })
225+
scheduleBellTone({ baseFrequency: 415, startTime: now + 0.45, duration: 4.8 })
226+
} catch (error) {
227+
// Fallback: silently fail if audio context is not available
228+
console.warn("Could not play doorbell sound:", error)
229+
}
230+
}

0 commit comments

Comments
 (0)