我对这个问题很陌生,但我尝试了这样的事情。
我知道 Audio api 很强大,但我不太了解,所以我来了:
let asClap = false;
let tampon = 60;
navigator.mediaDevices.getUserMedia({
"audio": {
"mandatory": {
"googEchoCancellation": "false",
"googAutoGainControl": "false",
"googNoiseSuppression": "false",
"googHighpassFilter": "false"
},
"optional": []
},
}).then(function(stream) {
const audioContext = new AudioContext();
/* use the stream */
let gain_node = audioContext.createGain();
gain_node.connect( audioContext.destination );
let microphone_stream = audioContext.createMediaStreamSource(stream);
let analyser = audioContext.createAnalyser()
microphone_stream.connect(analyser)
analyser.fftSize = 256;
isClaping(analyser)
}).catch(function(err) {
console.log(err)
});
function isClaping(analyser){
const bufferLength = analyser.frequencyBinCount;
var data = new Uint8Array(bufferLength);
analyser.getByteFrequencyData(data);
const arraySum = data.reduce((a, value) => a + value);
if(arraySum >= 3000){
if(!asClap){
asClap = true;
clap()
}
}
requestAnimationFrame(()=>{isClaping(analyser)});
tampon--
if(tampon === 0){
tampon = 60
asClap = false
}
}
我真的需要用 Javascript 来做,因为我更熟悉 这是正确的吗?我如何检测双拍?
最佳答案
这是一个用于检测拍手的简单能量分析器。它将 2200-2800 频率范围内的振幅相加,并在该能量超过阈值时触发事件。
export class ClapDetector {
options = {
// energy threshold for claps
clapThreshold: 70,
// typical freq range for claps
highFrequencyRange: [2200, 2800],
minClapInterval: 300
}
lastClapTime: number = 0
frameRequeust: number = null
bufferLength: number = 0
analyserNode: AnalyserNode = null
frequencyData: Uint8Array = null
audioContext: AudioContext = null
constructor(options = {}) {
this.options = Object.assign(this.options, options)
this.lastClapTime = 0
this.detectClap = this.detectClap.bind(this)
this.audioContext = new AudioContext()
this.analyserNode = this.audioContext.createAnalyser()
// high frequency, short fft size
this.analyserNode.fftSize = 2048
this.analyserNode.minDecibels = -90
this.analyserNode.maxDecibels = -10
this.analyserNode.smoothingTimeConstant = 0.85
this.bufferLength = this.analyserNode.frequencyBinCount
this.frequencyData = new Uint8Array(this.bufferLength)
navigator.mediaDevices.getUserMedia({ audio: true }).then(stream => {
const mediaStreamSource = this.audioContext.createMediaStreamSource(stream)
// connect the mediaStreamSource to the analyserNode
mediaStreamSource.connect(this.analyserNode)
this.start()
})
}
start() {
this.frameRequeust = requestAnimationFrame(this.detectClap)
}
stop() {
cancelAnimationFrame(this.frameRequeust)
}
detectClap() {
this.analyserNode.getByteFrequencyData(this.frequencyData)
const highFrequencyData = this.frequencyData.slice(
Math.round(this.options.highFrequencyRange[0] / this.audioContext.sampleRate * this.bufferLength),
Math.round(this.options.highFrequencyRange[1] / this.audioContext.sampleRate * this.bufferLength)
)
const highFrequencyEnergy = highFrequencyData.reduce((sum, value) => sum + value) / highFrequencyData.length
console.log(highFrequencyEnergy)
const metClapThreshold = highFrequencyEnergy > this.options.clapThreshold
const timeSinceLastClap = Date.now() - this.lastClapTime
const metMinClapInterval = timeSinceLastClap > this.options.minClapInterval
if (metClapThreshold && metMinClapInterval) {
console.log('Clap detected!')
this.lastClapTime = Date.now()
this.clapListeners.forEach(listener => listener())
}
this.frameRequeust = requestAnimationFrame(this.detectClap)
}
clapListeners = []
// add listener
onClap(listener) {
this.clapListeners.push(listener)
}
// remove listener
offClap(listener) {
this.clapListeners = this.clapListeners.filter(l => l !== listener)
}
}
如果您想检测双拍,您可以添加一个选项来检查最大时间阈值,并触发双拍处理程序。
if (metClapThreshold && metMinClapInterval) {
//...
const underMaxDoubleClapInterval = timeSinceLastClap < this.options.maxDoubleClapInterval
if(underMaxDoubleClapInterval) {
this.doubleClapListeners.forEach(listener => listener())
// increase last clap time to prevent unlimited double claps
this.lastClapTime += this.options.maxDoubleClapInterval
}
}
关于javascript - 使用 Javascript 进行拍手检测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72092757/