对于能够确定耳鸣频率的应用程序,会出现以下情况:
用户“mousedown”html5滑块 - >启动一定频率的振荡器。通过移动手柄,用户可以更改音符的音量。
以下是负责整个音频处理的(CoffeeScript-)代码:
# CoffeScript for Tuner element
# Enables playing notes via Web Audio API
class @Tuner
constructor: () ->
@playing = false
@whobbling = false
@stopping = false
@atVolumeChange = false
@atFadeIn = false
@activeBtn = undefined
if typeof AudioContext isnt "undefined"
@audioCtx ?= new AudioContext()
else if typeof webkitAudioContext isnt "undefined"
@audioCtx = new webkitAudioContext()
else
console.log "Browser hat keine WebAudioAPI"
# make sure listener is set correct:
listener = @audioCtx.listener
listener.setOrientation(0,0,-1,0,1,0)
listener.setPosition(0,0,0)
# Create PannerNode and set initially to L and R
@pannerNode = @audioCtx.createPanner()
@pannerNode.setOrientation(0,0,0)
@pannerNode.setPosition(0,0,1)
@pannerNode.connect( @audioCtx.destination )
# Create GainNode and set to 0.0
@gainNode = @audioCtx.createGain()
@gainNode.gain.value = 0.0
@gainNode.connect @pannerNode
@actualFreq = 500
@currentVolume = 0.0
start: (volume, elem_id) ->
if @playing or @stopping
return
@playing = true
@currentVolume = volume
@oscillator = @audioCtx.createOscillator()
@oscillator.type = "sine"
@oscillator.frequency.value = @actualFreq
@oscillator.connect @gainNode
# if whobbling is active, create LFO & LFOGain for effect
if @whobbling
lfo = @audioCtx.createOscillator()
lfo.type = "sine"
lfo.frequency.value = 5
whobGain = @actualFreq * 5.0 / 100.0
lfo_gain = @audioCtx.createGain()
lfo_gain.gain.value = whobGain
lfo.connect(lfo_gain)
lfo_gain.connect(@oscillator.frequency)
lfo.start(0)
# starting process
@activeBtn = elem_id
matchingGUI.highlightPlay( @activeBtn ) if @activeBtn
now = @audioCtx.currentTime
@atFadeIn = true
@gainNode.gain.setValueAtTime 0.0, now + 0.01
@oscillator.start(now + 0.02)
@gainNode.gain.setValueAtTime 0.0, now + 0.03
@gainNode.gain.linearRampToValueAtTime volume, now + 0.2
that = @
setTimeout ->
that.atFadeIn = false
, 200
stop: () ->
if @playing and not @stopping
@stopping = true
now = @audioCtx.currentTime
now += 0.3 if @atVolumeChange
now += 0.3 if @atFadeIn
@gainNode.gain.setValueAtTime @currentVolume, now + 0.01
@gainNode.gain.linearRampToValueAtTime 0.0, now + 0.45
@oscillator.stop( now + 0.5 )
matchingGUI.highlightStop(@activeBtn) if @activeBtn
that = @
setTimeout ->
that.stopping = false
that.playing = false
that.whobbling = false
, 750
setFrequency: (newFreq) ->
@actualFreq = newFreq
@oscillator.frequency.value = newFreq if @playing and not @stopping
changeVolume: (newVolume) ->
newVolumeDb = @linearToDb newVolume
if not @stopping
@atVolumeChange = true
now = @audioCtx.currentTime
@currentVolume = newVolumeDb
@gainNode.gain.exponentialRampToValueAtTime @currentVolume, now + 0.333
that = @
setTimeout ->
that.atVolumeChange = false
, 300
setWhobbling: () ->
@whobbling = true
setPanToLR: () ->
@pannerNode.setPosition(0,0,1) unless @playing
setPanToL: () ->
@pannerNode.setPosition(-3,0,0) unless @playing
setPanToR: () ->
@pannerNode.setPosition(3,0,0) unless @playing
play: (frequency, volume, whob, elem_id) ->
whob ?= false
@setFrequency frequency
@setWhobbling() if whob
volumeDb = @linearToDb( volume )
@start( volumeDb, elem_id )
linearToDb: (s) ->
dbStart = 90
s = s * dbStart - dbStart
return Math.pow 10, s/20
# === End Class Tuner ===
#
# export Tuner
root = exports ? window
root.Tuner = Tuner
Tuner.play()连接到滑块'mousedown'回调和Tuner.changeVolume()到滑块'输入'回调。
问题如下:
每次移动滑块时,都会发生单击。我想这是因为每次滑块触发'输入'时,当前由Tuner.changeVolume方法驱动的斜坡被另一个斜坡覆盖。
我实验了很多(没有调度,cancelScheduledValues,...),上面的版本只留下最后一次点击,最初为Mac上的各种浏览器移动滑块。但是对于Windows机器上的浏览器,点击会显着增加。
(顺便说一句。当驱动斜坡时,似乎无法读出@ gainNode.gain.value。)
知道如何处理这个问题吗? 我会感激任何提示...
答案 0 :(得分:0)
可能是您的振荡器正在重启。不太熟悉CoffeeScript(需要更多咖啡...)所以不能直接解决问题,但如果它是一个点击并拖动滑动事件,也许浏览器不正确地发送带有mousemove事件的多个mousedowns。
相反,为什么不让振荡器始终运行但增益节点为0,实际上没有输出。然后,当用户越过增益斜坡并跟踪用户输入时。一般来说,使用斜坡是一种好习惯,但是如果你用鼠标移动触发音量变化,大多数用户都不会足够快地移动滑动器以便你进行“拉伸”。效果我想你想避免。