dev-audioprocessing/pages/band2.vue

225 lines
7.8 KiB
Vue

<template>
<div>
<button @click="startAudio">Start</button>
<button @click="stopAudio">Stop</button>
<div>{{ level }}</div>
Masking Gain : <input id="gain-control" v-model="maxGain1000" type="range" min="0" max="1" step="0.01">
Harmonic Gain : <input id="gain-control" v-model="harmonicGain" type="range" min="0" max="1" step="0.01">
</div>
</template>
<script>
export default {
data() {
return {
audioContext: null,
analyserNode: null,
bufferSize: 4096,
snapshotInterval: 125,
snapshotDuration: 5512.5,
level: 0,
snapshots: [],
intervalId: null,
bandPass1:null,
Gain1000:null,
SoundNode:null,
source100:null,
maxGain1000:0.5,
lastGainValue:0,
maskingGain1000:0,
harmonicGain:1,
maskGainControl:0,
};
},
mounted() {
this.audioContext = new (window.AudioContext || window.webkitAudioContext)();
this.source100=this.audioContext.createBufferSource()
this.maskGainControl=this.audioContext.createGain();
fetch('/masking/MaskingNoise_1000.aac')
.then(response => response.arrayBuffer())
.then(arrayBuffer => this.audioContext.decodeAudioData(arrayBuffer))
.then(audioBuffer => {
// Set buffer on AudioBufferSourceNode
this.source100.buffer = audioBuffer;
this.source100.loop = true;
// Connect nodes
// this.source100.connect(compressorNode);
this.source100.connect(this.maskGainControl);
// this.Gain1000.connect(this.compressorNode);
this.maskGainControl.connect(this.audioContext.destination);
// this.Gain1000.gain.setValueAtTime(1,this.audioCtx.currentTime);
// Play source node
});
this.SoundNode=this.audioContext.createBufferSource();
this.harmonicGainNode=this.audioContext.createGain();
fetch('/sounds/Forest.aac')
.then(response => response.arrayBuffer())
.then(arrayBuffer => this.audioContext.decodeAudioData(arrayBuffer))
.then(audioBuffer => {
// Set buffer on AudioBufferSourceNode
this.SoundNode.buffer = audioBuffer;
this.SoundNode.loop = true;
// compressorNode.attack.value = .25;
// this.SoundNode.connect(compressorNode);
// this.harmonicGainNode.gain.value=this.harmonicGain;
this.currentDestination = this.audioContext.destination;
this.SoundNode.connect(this.harmonicGainNode);
this.harmonicGainNode.connect(this.currentDestination);
// Play source node
//1102500
});
},
methods: {
startAudio() {
// Create the AudioContext
// Create the AnalyserNode
this.analyserNode = this.audioContext.createAnalyser();
this.analyserNode.fftSize = this.bufferSize;
this.analyserNode.minDecibels = -100;
this.analyserNode.maxDecibels = -1;
this.analyserNode.smoothingTimeConstant = 0.95;
this.bandPass1=this.audioContext.createBiquadFilter();
this.bandPass1.type='bandpass'
this.bandPass1.frequency.value=63;
this.bandPass1.Q.value=1.41;
// Connect the microphone input to the AnalyserNode
navigator.mediaDevices.getUserMedia({ audio: true })
.then((stream) => {
this.Gain1000=this.audioContext.createGain();
this.Gain1000.gain.value = Math.pow(10, (-39 / 20));
const source = this.audioContext.createMediaStreamSource(stream);
source.connect(this.Gain1000);
this.bandPass1.connect(this.bandPass1);
source.connect(this.analyserNode)
this.source100.start();
this.SoundNode.start();
})
.catch((error) => {
console.error('Error accessing microphone:', error);
});
// Start capturing snapshots at the specified interval
this.intervalId = setInterval(() => {
this.captureSnapshot();
}, this.snapshotInterval);
},
stopAudio() {
// Stop capturing snapshots and clear the interval
clearInterval(this.intervalId);
// Disconnect the audio nodes
this.analyserNode.disconnect();
this.audioContext.close();
// Reset the data
this.snapshots = [];
this.level = 0;
},
captureSnapshot() {
const bufferLength = this.analyserNode.frequencyBinCount;
const frequencyData = new Uint8Array(bufferLength);
this.analyserNode.getByteFrequencyData(frequencyData);
const snapshot = {
data: Array.from(frequencyData),
timestamp: this.audioContext.currentTime,
};
this.snapshots.push(snapshot);
// Remove old snapshots that are older than the snapshot duration
const oldestTimestamp = snapshot.timestamp - this.snapshotDuration / 1000;
while (this.snapshots.length > 0 && this.snapshots[0].timestamp < oldestTimestamp) {
this.snapshots.shift();
this.calculateLevel();
}
this.harmonicGainNode.gain.setValueAtTime(this.harmonicGain,this.audioContext.currentTime);
// Calculate the integrated level value for the bandpass filter
},
calculateLevel() {
// console.log(this.snapshots);
const filteredSnapshots = this.snapshots.filter((snapshot) => {
return (
snapshot.data[63] >= 0 &&
snapshot.data[63] <= 255
);
});
// console.log(this.snapshots);
const levelValues = filteredSnapshots.map((snapshot) => {
return snapshot.data[63];
});
// Convert level values to RMS
const squaredValues = levelValues.map((value) => {
return value ** 2;
});
console.log(levelValues);
const sumOfSquares = squaredValues.reduce((acc, value) => acc + value, 0);
const meanOfSquares = sumOfSquares / squaredValues.length;
const rms = Math.sqrt(meanOfSquares);
const dbfsValues = levelValues.map((value) => {
const rmsValue = value / 255; // Normalize to 0-1 range
const dbfsValue = 20 * Math.log10(rmsValue);
return dbfsValue;
});
console.log(dbfsValues);
// Sort the RMS values in ascending order
const sortedData = dbfsValues.sort((a, b) => a - b);
// console.log(sortedData);
// Calculate the 10th percentile value
const percentile10 = this.calculatePercentile(sortedData, 10);
// Calculate the 90th percentile value
const percentile90 = this.calculatePercentile(sortedData, 90);
const dbfs = 20 * Math.log10(rms / 255);
console.log(rms);
this.level = rms;
this.percentile10 = percentile10;
this.percentile90 = percentile90;
console.log('!0th',this.percentile10);
console.log('90th',this.percentile90);
console.log("Percentile:",this.percentile90-this.percentile10);
const percentile=this.percentile90-this.percentile10;
if (!isFinite(percentile)){
console.log('ok Inf');
return;
}
const rampTime = 2;
const startTime = this.audioContext.currentTime;
// Map the difference to the desired range of GainValues
const minDifference = 0; // Minimum difference value
const maxDifference = 10; // Maximum difference value
const minGainValue = 0.1; // Minimum GainValue
const maxGainValue = this.maxGain1000; // Maximum GainValue
// Map the difference to the GainValue range
const mappedGainValue = ((percentile - minDifference) / (maxDifference - minDifference)) *
(maxGainValue - minGainValue) + minGainValue;
console.log('Maped Gain',mappedGainValue);
this.maskGainControl.gain.setTargetAtTime(mappedGainValue,this.audioContext.currentTime,6);
},
calculatePercentile(sortedData, percentile) {
const index = Math.ceil((percentile / 100) * sortedData.length);
return sortedData[index - 1];
}
},
};
</script>