添加音调升降调节

This commit is contained in:
lyswhut
2023-05-31 21:40:25 +08:00
parent 677c3f16e4
commit 40997c34ff
21 changed files with 1435 additions and 20 deletions
+77 -11
View File
@@ -38,12 +38,19 @@ export const convolutions = [
{ name: 'feedback_spring', mainGain: 1.8, sendGain: 0.8, source: 'feedback-spring.wav' },
// { name: 'tim_omni_rear_blend', mainGain: 1.8, sendGain: 0.8, source: 'tim-omni-rear-blend.wav' },
] as const
// 半音
export const semitones = [-1.5, -1, -0.5, 0.5, 1, 1.5, 2, 2.5, 3, 3.5] as const
let convolver: ConvolverNode
let convolverSourceGainNode: GainNode
let convolverOutputGainNode: GainNode
let convolverDynamicsCompressor: DynamicsCompressorNode
let gainNode: GainNode
let panner: PannerNode
let pitchShifterNode: AudioWorkletNode
let pitchShifterNodeAudioParam: AudioParam
let pitchShifterNodeLoadStatus: 'none' | 'loading' | 'unconnect' | 'connected' = 'none'
let pitchShifterNodeTempValue = 1
export const soundR = 0.5
@@ -101,26 +108,21 @@ const initAdvancedAudioFeatures = () => {
if (audioContext) return
if (!audio) throw new Error('audio not defined')
audioContext = new window.AudioContext()
mediaSource = audioContext.createMediaElementSource(audio)
initAnalyser()
mediaSource.connect(analyser)
// analyser.connect(audioContext.destination)
initBiquadFilter()
analyser.connect(biquads.get(`hz${freqs[0]}`) as BiquadFilterNode)
initConvolver()
initPanner()
initGain()
// source -> analyser -> biquadFilter -> [(convolver & convolverSource)->convolverDynamicsCompressor] -> panner -> gain
mediaSource = audioContext.createMediaElementSource(audio)
mediaSource.connect(analyser)
analyser.connect(biquads.get(`hz${freqs[0]}`) as BiquadFilterNode)
const lastBiquadFilter = (biquads.get(`hz${freqs.at(-1) as Freqs}`) as BiquadFilterNode)
lastBiquadFilter.connect(convolverSourceGainNode)
lastBiquadFilter.connect(convolver)
initPanner()
convolverDynamicsCompressor.connect(panner)
initGain()
panner.connect(gainNode)
gainNode.connect(audioContext.destination)
}
@@ -217,6 +219,70 @@ export const startPanner = () => {
}, pannerInfo.speed * 10)
}
const loadPitchShifterNode = () => {
pitchShifterNodeLoadStatus = 'loading'
initAdvancedAudioFeatures()
// source -> analyser -> biquadFilter -> audioWorklet(pitch shifter) -> [(convolver & convolverSource)->convolverDynamicsCompressor] -> panner -> gain
void audioContext.audioWorklet.addModule(new URL(
/* webpackChunkName: 'pitch_shifter.audioWorklet' */
'@renderer/utils/pitch-shifter/phase-vocoder.js',
import.meta.url,
)).then(() => {
console.log('pitch shifter audio worklet loaded')
pitchShifterNode = new AudioWorkletNode(audioContext, 'phase-vocoder-processor')
let audioParam = pitchShifterNode.parameters.get('pitchFactor')
if (!audioParam) return
pitchShifterNodeAudioParam = audioParam
pitchShifterNodeLoadStatus = 'unconnect'
if (pitchShifterNodeTempValue == 1) return
connectPitchShifterNode()
})
}
const connectPitchShifterNode = () => {
const lastBiquadFilter = (biquads.get(`hz${freqs.at(-1) as Freqs}`) as BiquadFilterNode)
lastBiquadFilter.disconnect()
lastBiquadFilter.connect(pitchShifterNode)
pitchShifterNode.connect(convolver)
pitchShifterNode.connect(convolverSourceGainNode)
// convolverDynamicsCompressor.disconnect(panner)
// convolverDynamicsCompressor.connect(pitchShifterNode)
// pitchShifterNode.connect(panner)
pitchShifterNodeLoadStatus = 'connected'
pitchShifterNodeAudioParam.value = pitchShifterNodeTempValue
}
// const disconnectPitchShifterNode = () => {
// const lastBiquadFilter = (biquads.get(`hz${freqs.at(-1) as Freqs}`) as BiquadFilterNode)
// lastBiquadFilter.disconnect()
// lastBiquadFilter.connect(convolver)
// lastBiquadFilter.connect(convolverSourceGainNode)
// pitchShifterNodeLoadStatus = 'unconnect'
// }
export const setPitchShifter = (val: number) => {
// console.log('setPitchShifter', val)
pitchShifterNodeTempValue = val
// if (val == 1 && pitchShifterNodeLoadStatus == 'connected') {
// disconnectPitchShifterNode()
// return
// }
switch (pitchShifterNodeLoadStatus) {
case 'loading':
break
case 'none':
loadPitchShifterNode()
break
case 'connected':
// a: 1 = 半音
// value = 2 ** (a / 12)
pitchShifterNodeAudioParam.value = val
break
case 'unconnect':
connectPitchShifterNode()
break
}
}
export const hasInitedAdvancedAudioFeatures = (): boolean => audioContext != null
export const setResource = (src: string) => {