diff --git a/apps/common-app/src/examples/Oscillator/Oscillator.tsx b/apps/common-app/src/examples/Oscillator/Oscillator.tsx index ad32abff4..b80c4b8fc 100644 --- a/apps/common-app/src/examples/Oscillator/Oscillator.tsx +++ b/apps/common-app/src/examples/Oscillator/Oscillator.tsx @@ -1,12 +1,12 @@ import React, { useRef, useState, useEffect, FC } from 'react'; -import { StyleSheet, Text, View, Pressable } from 'react-native'; +import { StyleSheet, Text, View, Pressable, Image } from 'react-native'; import { AudioContext, GainNode, OscillatorNode, StereoPannerNode, } from 'react-native-audio-api'; -import type { OscillatorType } from 'react-native-audio-api'; +import type { OscillatorType, AudioBuffer, ConvolverNode } from 'react-native-audio-api'; import { Container, Slider, Spacer, Button } from '../../components'; import { layout, colors } from '../../styles'; @@ -29,16 +29,48 @@ const Oscillator: FC = () => { const audioContextRef = useRef(null); const oscillatorRef = useRef(null); + const oscillatorRef2 = useRef(null); const gainRef = useRef(null); const panRef = useRef(null); + const convolverRef = useRef(null); - const setup = () => { + useEffect(() => { + const fetchImpulseResponse = async () => { + if (!audioContextRef.current) { + audioContextRef.current = new AudioContext(); + } + + const length = audioContextRef.current.sampleRate * 2; // 2 seconds + const impulse = audioContextRef.current.createBuffer(2, length, audioContextRef.current.sampleRate); + + for (let channel = 0; channel < impulse.numberOfChannels; channel++) { + const channelData = impulse.getChannelData(channel); + for (let i = 0; i < length; i++) { + // Exponentially decay the impulse + channelData[i] = (Math.random() * 2 - 1) * Math.pow(1 - i / length, 2); + } + } + + convolverRef.current = audioContextRef.current?.createConvolver(); + convolverRef.current.buffer = impulse; + } + + fetchImpulseResponse(); + + return () => { + audioContextRef.current?.close(); + }; + }, []); + + const setup = (reverb: boolean) => { if (!audioContextRef.current) { audioContextRef.current = new AudioContext(); } oscillatorRef.current = audioContextRef.current.createOscillator(); + oscillatorRef2.current = audioContextRef.current.createOscillator(); oscillatorRef.current.frequency.value = frequency; + oscillatorRef2.current.frequency.value = frequency; oscillatorRef.current.detune.value = detune; oscillatorRef.current.type = oscillatorType; @@ -50,7 +82,12 @@ const Oscillator: FC = () => { oscillatorRef.current.connect(gainRef.current); gainRef.current.connect(panRef.current); - panRef.current.connect(audioContextRef.current.destination); + if (convolverRef.current && reverb) { + panRef.current.connect(convolverRef.current); + convolverRef.current.connect(audioContextRef.current.destination); + } else { + panRef.current.connect(audioContextRef.current.destination); + } }; const handleGainChange = (newValue: number) => { @@ -85,12 +122,17 @@ const Oscillator: FC = () => { } }; - const handlePlayPause = () => { + const handlePlayPause = (reverb: boolean) => { if (isPlaying) { oscillatorRef.current?.stop(0); } else { - setup(); + setup(reverb); oscillatorRef.current?.start(0); + oscillatorRef.current?.stop(audioContextRef.current?.currentTime!! + 2); + gainRef.current?.gain.setValueAtTime(0, audioContextRef.current?.currentTime!! + 2); + oscillatorRef2.current?.start(audioContextRef.current?.currentTime!! + 2); + oscillatorRef2.current?.connect(gainRef.current!); + oscillatorRef2.current?.stop(audioContextRef.current?.currentTime!! + 3); } setIsPlaying((prev) => !prev); @@ -103,19 +145,10 @@ const Oscillator: FC = () => { } }; - useEffect(() => { - if (!audioContextRef.current) { - audioContextRef.current = new AudioContext(); - } - - return () => { - audioContextRef.current?.close(); - }; - }, []); - return ( -