<code>const LiveAudioProcessor: React.FC<LiveAudioProcessorProps> = ({ audioFiles, rpm }) => {
const [isStarted, setIsStarted] = useState(false);
const audioSourcesRef = useRef<Map<AudioFile, { source: AudioBufferSourceNode, gain: GainNode }>>(new Map());
const audioBuffersRef = useRef<Map<AudioFile, AudioBuffer>>(new Map());
const startAudio = async () => {
audioContext.resume();
for (const file of audioFiles) {
if (!audioSourcesRef.current.has(file)) {
const response = await fetch(file.url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
audioBuffersRef.current.set(file, audioBuffer);
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.loop = true;
const gain = audioContext.createGain();
source.connect(gain);
gain.connect(audioContext.destination);
audioSourcesRef.current.set(file, { source, gain });
source.start();
}
}
setIsStarted(true);
playAudio();
};
const playAudio = () => {
if (!audioContext) return;
const sortedAudioFiles = [...audioFiles].sort((a, b) => a.rpm - b.rpm);
const lowerFile = sortedAudioFiles.find((file, i) => file.rpm <= rpm && sortedAudioFiles[i + 1]?.rpm > rpm);
if (!lowerFile) {
// Handle the case where lowerFile is undefined
return;
}
const lowerFileIndex = sortedAudioFiles.findIndex((file) => file === lowerFile);
const upperFile = sortedAudioFiles[lowerFileIndex + 1];
if (!upperFile) {
// Handle the case where upperFile is undefined
return;
}
const crossfadeLevel = (rpm - lowerFile.rpm) / (upperFile.rpm - lowerFile.rpm);
// Adjust the gain of the audio sources
audioSourcesRef.current.forEach(({ source, gain }, file) => {
if (file === lowerFile) {
gain.gain.value = 1 - crossfadeLevel;
} else if (file === upperFile) {
gain.gain.value = crossfadeLevel;
} else {
gain.gain.value = 0.001;
}
});
};
useEffect(() => {
console.log('RPM changed:', rpm);
if (isStarted) {
playAudio();
} else {
console.log('Audio not started');
}
}, [rpm, isStarted]);
useEffect(() => {
return () => {
audioSourcesRef.current.forEach(({ source }) => source.stop());
};
}, []);
return (
<>
<button onClick={startAudio} disabled={isStarted}>
Start Audio
</button>
</>
);
};
</code>
<code>const LiveAudioProcessor: React.FC<LiveAudioProcessorProps> = ({ audioFiles, rpm }) => {
const [isStarted, setIsStarted] = useState(false);
const audioSourcesRef = useRef<Map<AudioFile, { source: AudioBufferSourceNode, gain: GainNode }>>(new Map());
const audioBuffersRef = useRef<Map<AudioFile, AudioBuffer>>(new Map());
const startAudio = async () => {
audioContext.resume();
for (const file of audioFiles) {
if (!audioSourcesRef.current.has(file)) {
const response = await fetch(file.url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
audioBuffersRef.current.set(file, audioBuffer);
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.loop = true;
const gain = audioContext.createGain();
source.connect(gain);
gain.connect(audioContext.destination);
audioSourcesRef.current.set(file, { source, gain });
source.start();
}
}
setIsStarted(true);
playAudio();
};
const playAudio = () => {
if (!audioContext) return;
const sortedAudioFiles = [...audioFiles].sort((a, b) => a.rpm - b.rpm);
const lowerFile = sortedAudioFiles.find((file, i) => file.rpm <= rpm && sortedAudioFiles[i + 1]?.rpm > rpm);
if (!lowerFile) {
// Handle the case where lowerFile is undefined
return;
}
const lowerFileIndex = sortedAudioFiles.findIndex((file) => file === lowerFile);
const upperFile = sortedAudioFiles[lowerFileIndex + 1];
if (!upperFile) {
// Handle the case where upperFile is undefined
return;
}
const crossfadeLevel = (rpm - lowerFile.rpm) / (upperFile.rpm - lowerFile.rpm);
// Adjust the gain of the audio sources
audioSourcesRef.current.forEach(({ source, gain }, file) => {
if (file === lowerFile) {
gain.gain.value = 1 - crossfadeLevel;
} else if (file === upperFile) {
gain.gain.value = crossfadeLevel;
} else {
gain.gain.value = 0.001;
}
});
};
useEffect(() => {
console.log('RPM changed:', rpm);
if (isStarted) {
playAudio();
} else {
console.log('Audio not started');
}
}, [rpm, isStarted]);
useEffect(() => {
return () => {
audioSourcesRef.current.forEach(({ source }) => source.stop());
};
}, []);
return (
<>
<button onClick={startAudio} disabled={isStarted}>
Start Audio
</button>
</>
);
};
</code>
const LiveAudioProcessor: React.FC<LiveAudioProcessorProps> = ({ audioFiles, rpm }) => {
const [isStarted, setIsStarted] = useState(false);
const audioSourcesRef = useRef<Map<AudioFile, { source: AudioBufferSourceNode, gain: GainNode }>>(new Map());
const audioBuffersRef = useRef<Map<AudioFile, AudioBuffer>>(new Map());
const startAudio = async () => {
audioContext.resume();
for (const file of audioFiles) {
if (!audioSourcesRef.current.has(file)) {
const response = await fetch(file.url);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
audioBuffersRef.current.set(file, audioBuffer);
const source = audioContext.createBufferSource();
source.buffer = audioBuffer;
source.loop = true;
const gain = audioContext.createGain();
source.connect(gain);
gain.connect(audioContext.destination);
audioSourcesRef.current.set(file, { source, gain });
source.start();
}
}
setIsStarted(true);
playAudio();
};
const playAudio = () => {
if (!audioContext) return;
const sortedAudioFiles = [...audioFiles].sort((a, b) => a.rpm - b.rpm);
const lowerFile = sortedAudioFiles.find((file, i) => file.rpm <= rpm && sortedAudioFiles[i + 1]?.rpm > rpm);
if (!lowerFile) {
// Handle the case where lowerFile is undefined
return;
}
const lowerFileIndex = sortedAudioFiles.findIndex((file) => file === lowerFile);
const upperFile = sortedAudioFiles[lowerFileIndex + 1];
if (!upperFile) {
// Handle the case where upperFile is undefined
return;
}
const crossfadeLevel = (rpm - lowerFile.rpm) / (upperFile.rpm - lowerFile.rpm);
// Adjust the gain of the audio sources
audioSourcesRef.current.forEach(({ source, gain }, file) => {
if (file === lowerFile) {
gain.gain.value = 1 - crossfadeLevel;
} else if (file === upperFile) {
gain.gain.value = crossfadeLevel;
} else {
gain.gain.value = 0.001;
}
});
};
useEffect(() => {
console.log('RPM changed:', rpm);
if (isStarted) {
playAudio();
} else {
console.log('Audio not started');
}
}, [rpm, isStarted]);
useEffect(() => {
return () => {
audioSourcesRef.current.forEach(({ source }) => source.stop());
};
}, []);
return (
<>
<button onClick={startAudio} disabled={isStarted}>
Start Audio
</button>
</>
);
};
Whenever the rpm value changes, the audio just completely stops instead of muting the irrelevant tracks.
I’ve tried removing old audio sources using disconnect, stopping and starting them but as soon as the RPM changes the audio stops working. I was expecting a smooth transition between the audio sources.
New contributor
Oliver Jackson is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.