javascript - Web Audio API: Clicks on volume change with slider -
for application makes 1 able determine ones tinnitus frequency, following scenario occurs:
a user 'mousedown' html5 slider -> oscillator @ frequency started. moving handle user can change volume of note.
here (coffeescript-)code responsible whole audio processing:
# coffescript 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 set correct: listener = @audioctx.listener listener.setorientation(0,0,-1,0,1,0) listener.setposition(0,0,0) # create pannernode , set l , r @pannernode = @audioctx.createpanner() @pannernode.setorientation(0,0,0) @pannernode.setposition(0,0,1) @pannernode.connect( @audioctx.destination ) # create gainnode , set 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 active, create lfo & lfogain 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 = @audioctx.currenttime @atfadein = true @gainnode.gain.setvalueattime 0.0, + 0.01 @oscillator.start(now + 0.02) @gainnode.gain.setvalueattime 0.0, + 0.03 @gainnode.gain.linearramptovalueattime volume, + 0.2 = @ settimeout -> that.atfadein = false , 200 stop: () -> if @playing , not @stopping @stopping = true = @audioctx.currenttime += 0.3 if @atvolumechange += 0.3 if @atfadein @gainnode.gain.setvalueattime @currentvolume, + 0.01 @gainnode.gain.linearramptovalueattime 0.0, + 0.45 @oscillator.stop( + 0.5 ) matchinggui.highlightstop(@activebtn) if @activebtn = @ settimeout -> that.stopping = false that.playing = false that.whobbling = false , 750 setfrequency: (newfreq) -> @actualfreq = newfreq @oscillator.frequency.value = newfreq if @playing , not @stopping changevolume: (newvolume) -> newvolumedb = @lineartodb newvolume if not @stopping @atvolumechange = true = @audioctx.currenttime @currentvolume = newvolumedb @gainnode.gain.exponentialramptovalueattime @currentvolume, + 0.333 = @ 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() connected sliders 'mousedown' callback , tuner.changevolume() sliders 'input' callback.
the problem follows:
every time slider moved, clicking occurs. guess reason every time slider fires 'input', ramp, driven tuner.changevolume method, overlaid ramp.
i experimented lot (no scheduling, cancelscheduledvalues, ...) , version above leaves 1 last clicking when slider moved various browsers on mac. browsers on windows machine clicking increases significantly.
(btw. seems not possible read out @gainnode.gain.value when ramp driven.)
any idea how handle problem? i'd thankful hint...
it may oscillators restarting. not familiar coffeescript (need more coffee...) can't directly root out problem if click , drag sliding event perhaps browser improperly sending multiple mousedowns mousemove event.
instead why not have oscillators running gain node @ 0, no output. when user goes on gain ramps , tracks user input. practice use ramps, if trigger volume change occur mousemove, users not move slidders fast enough 'zipping' effect think want avoid.
Comments
Post a Comment