Skip to content

Commit

Permalink
refactor(hooks): nodes - into factory audioNodes createAudioNode
Browse files Browse the repository at this point in the history
  • Loading branch information
calinalexandru committed Aug 18, 2023
1 parent d21e69b commit cb2e0c1
Show file tree
Hide file tree
Showing 14 changed files with 95 additions and 174 deletions.
25 changes: 2 additions & 23 deletions src/constants/map.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { NODE_TYPE, } from ".";
import { NODE_TYPE, } from '.';
import Analyser from '../components/Analyser';
import BiquadFilter from '../components/BiquadFilter';
import Buffer from '../components/Buffer';
Expand All @@ -9,16 +9,6 @@ import Gain from '../components/Gain';
import Microphone from '../components/Microphone';
import Oscillator from '../components/Oscillator';
import Pan from '../components/Pan';
import oscillatorNode from '../hooks/nodes/oscillator';
import biquadFilterNode from '../hooks/nodes/biquadFilter';
import dynamicsCompressorNode from '../hooks/nodes/dynamicsCompressor';
import microphoneNode from '../hooks/nodes/microphone';
import bufferNode from '../hooks/nodes/buffer';
import gainNode from '../hooks/nodes/gain';
import convolverNode from '../hooks/nodes/convolver';
import analyserNode from '../hooks/nodes/analyser';
import delayNode from '../hooks/nodes/delay';
import panNode from '../hooks/nodes/pan';

export const NODES_COMPONENTS_MAP = {
[NODE_TYPE.OSCILLATOR]: Oscillator,
Expand All @@ -33,15 +23,4 @@ export const NODES_COMPONENTS_MAP = {
[NODE_TYPE.PAN]: Pan,
};

export const AUDIO_NODES_MAP = {
[NODE_TYPE.OSCILLATOR]: oscillatorNode,
[NODE_TYPE.BIQUAD_FILTER]: biquadFilterNode,
[NODE_TYPE.DYNAMICS_COMPRESSOR]: dynamicsCompressorNode,
[NODE_TYPE.MICROPHONE]: microphoneNode,
[NODE_TYPE.BUFFER]: bufferNode,
[NODE_TYPE.GAIN]: gainNode,
[NODE_TYPE.CONVOLVER]: convolverNode,
[NODE_TYPE.ANALYSER]: analyserNode,
[NODE_TYPE.DELAY]: delayNode,
[NODE_TYPE.PAN]: panNode,
};
export const noop = () => {}
87 changes: 87 additions & 0 deletions src/factories/audioNodes.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
import { setValueByType, } from './util';

export default async function createAudioNode(
audioCtx,
nodeType,
properties,
mediaStreamRef,
) {
const config = {
microphone: {
create: async () => {
try {
mediaStreamRef.current = await navigator.mediaDevices.getUserMedia({
audio: true,
},);
return audioCtx.createMediaStreamSource(mediaStreamRef.current,);
} catch (err) {
console.warn('Microphone not found', err,);
return false;
}
},
},
oscillator: {
create: () => audioCtx.createOscillator(),
properties: ['type', 'detune', 'frequency', 'type', 'duration',],
},
analyser: {
create: () => audioCtx.createAnalyser(),
properties: ['fftSize',],
},
gain: {
create: () => audioCtx.createGain(),
properties: ['gain',],
},
biquadFilter: {
create: () => audioCtx.createBiquadFilter(),
properties: ['type', 'detune', 'gain', 'Q', 'frequency',],
},
convolver: {
create: () => audioCtx.createConvolver(),
properties: ['normalize', 'buffer',],
},
dynamicsCompressor: {
create: () => audioCtx.createDynamicsCompressor(),
properties: ['threshold', 'knee', 'ratio', 'attack', 'release',],
},
buffer: {
create: () => audioCtx.createBufferSource(),
properties: ['loop', 'detune', 'playbackRate', 'loopStart', 'loopEnd', 'buffer',],
},
delay: {
create: () => audioCtx.createDelay(),
properties: ['delayTime',],
},
pan: {
create: () => audioCtx.createStereoPanner(),
properties: ['pan',],
},
};

const nodeConfig = config[nodeType];
if (!nodeConfig) {
throw new Error(`Unsupported node type: ${nodeType}`,);
}

const node = await nodeConfig.create();

if (typeof node.start === 'function') {
node.start();
}

nodeConfig?.properties?.forEach((property,) => {
if (Object.prototype.hasOwnProperty.call(properties, property,)) {
if (node[property] instanceof AudioParam) {
setValueByType(audioCtx, property, node[property], properties,);
} else if (property === 'duration' && Number(properties.duration,)) {
node.stop(audioCtx.currentTime + Number(properties.duration,),);
} else {
node[property] = properties[property];
}
}
},);

return node;
}

export const noop = () => {};
File renamed without changes.
5 changes: 0 additions & 5 deletions src/hooks/nodes/analyser.js

This file was deleted.

11 changes: 0 additions & 11 deletions src/hooks/nodes/biquadFilter.js

This file was deleted.

13 changes: 0 additions & 13 deletions src/hooks/nodes/buffer.js

This file was deleted.

5 changes: 0 additions & 5 deletions src/hooks/nodes/convolver.js

This file was deleted.

7 changes: 0 additions & 7 deletions src/hooks/nodes/delay.js

This file was deleted.

12 changes: 0 additions & 12 deletions src/hooks/nodes/dynamicsCompressor.js

This file was deleted.

7 changes: 0 additions & 7 deletions src/hooks/nodes/gain.js

This file was deleted.

13 changes: 0 additions & 13 deletions src/hooks/nodes/microphone.js

This file was deleted.

13 changes: 0 additions & 13 deletions src/hooks/nodes/oscillator.js

This file was deleted.

7 changes: 0 additions & 7 deletions src/hooks/nodes/pan.js

This file was deleted.

64 changes: 6 additions & 58 deletions src/hooks/useAudioNodes.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useEffect, useRef, useState, } from 'preact/hooks';
import { NODE_TYPE, } from '../constants';
import { AUDIO_NODES_MAP, } from '../constants/map';
import createAudioNode from '../factories/audioNodes';

export default function useAudioNodes(signal, isPlaying, { nodes, wires, },) {
const mediaStreamRef = useRef(null,);
Expand All @@ -17,75 +17,23 @@ export default function useAudioNodes(signal, isPlaying, { nodes, wires, },) {
}

const audioNodes = nodes.map(async (node,) => {
if (typeof AUDIO_NODES_MAP[node.type] === 'function') {
return AUDIO_NODES_MAP[node.type]?.(
try {
return await createAudioNode(
audioCtx.current,
node.type,
node.properties,
mediaStreamRef,
);
} catch (e) {
return audioCtx.current.destination;
}
return audioCtx.current.destination;
},);

// const sampleData = ({
// analyser,
// buffer,
// dataArray,
// properties: { duration = 1, },
// },) =>
// new Promise((resolve, reject,) => {
// const myArrayBuffer = audioCtx.createBuffer(
// 2,
// audioCtx.sampleRate * duration,
// audioCtx.sampleRate,
// );
// // myArrayBuffer
// const offset = 0;
// try {
// setTimeout(() => {
// analyser.getFloatTimeDomainData(dataArray,);
// myArrayBuffer.copyToChannel(
// dataArray,
// 0,
// offset * analyser.frequencyBinCount,
// );
// myArrayBuffer.copyToChannel(
// dataArray,
// 1,
// offset * analyser.frequencyBinCount,
// );
// buffer.buffer = myArrayBuffer;
// buffer.start();
// resolve(true,);
// }, duration * 1000,);
// } catch (e) {
// reject(e,);
// }
// },);

wires.forEach(async (wire,) => {
const from = await audioNodes[wire.from];
const to = await audioNodes[wire.to];
try {
// if (nodes[wire.to].type === NODE_TYPE.BUFFER) {
// const analyser = audioCtx.createAnalyser();
// from.connect(analyser,);
// analyser.fftSize = 32768;
// const bufferLength = analyser.frequencyBinCount;
// const dataArray = new Float32Array(bufferLength,);
// // const dataArray = new Uint8Array(bufferLength,);

// await sampleData({
// analyser,
// buffer: to,
// dataArray,
// properties: nodes[wire.from].properties,
// },);

// // analyser.connect(to,);
// } else {
from.connect(to,);
// }

if (nodes[wire.to].type === NODE_TYPE.ANALYSER) {
//* mutate live node with current audio
Expand Down

0 comments on commit cb2e0c1

Please sign in to comment.