New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

audio-slot

Package Overview
Dependencies
Maintainers
1
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

audio-slot - npm Package Compare versions

Comparing version 4.9.2 to 5.0.0

lib/computed-next-tick.js

8

index.js

@@ -26,5 +26,2 @@ var Observ = require('observ')

var refreshingConnections = false
var extraConnections = []
input.connect(pre)

@@ -145,3 +142,8 @@ pre.connect(toProcessors)

}
})
}
obs.cancelFrom = function (at) {
obs.sources.forEach(function (source) {
source.cancelFrom && source.cancelFrom(at)
})

@@ -148,0 +150,0 @@ }

@@ -100,5 +100,6 @@ var Observ = require('observ')

lastBuffer = buffer()
obs.set(true)
if (obs()) {
obs.set(true)
}
}
}

@@ -105,0 +106,0 @@ }

{
"name": "audio-slot",
"version": "4.9.2",
"version": "5.0.0",
"description": "Web Audio API FRP wrapper for creating, routing, and triggering AudioNodes.",

@@ -16,3 +16,3 @@ "main": "index.js",

"array-union": "^1.0.1",
"audio-slot-param": "~1.1.1",
"audio-slot-param": "~2.2.0",
"bitcrusher": "^0.3.0",

@@ -22,5 +22,7 @@ "deep-equal": "~0.2.1",

"geval": "^2.1.1",
"make-distortion-curve": "^1.0.0",
"noise-buffer": "^2.0.0",
"observ": "^0.2.0",
"observ-default": "^1.0.0",
"observ-node-array": "^1.10.0",
"observ-node-array": "^1.11.1",
"observ-struct": "^6.0.0",

@@ -27,0 +29,0 @@ "setimmediate2": "^2.0.1",

@@ -13,6 +13,6 @@ var ObservStruct = require('observ-struct')

var obs = ObservStruct({
attack: Property(0),
decay: Property(0),
sustain: Property(1),
release: Property(0),
attack: Param(context, 0),
decay: Param(context, 0),
release: Param(context, 0),
sustain: Param(context, 1),
value: Param(context, 1)

@@ -33,3 +33,3 @@ })

{ param: obs.value },
{ param: eventSource, transform: multiply }
{ param: eventSource, transform: multiply, watchingYou: true }
])

@@ -49,6 +49,5 @@

broadcast({
fromValue: 0,
value: 1,
at: at,
duration: obs.attack(),
duration: obs.attack.getValueAt(at),
mode: 'log'

@@ -62,5 +61,5 @@ })

broadcast({
value: obs.sustain(),
value: obs.sustain.getValueAt(peakTime),
at: peakTime,
duration: obs.decay(),
duration: obs.decay.getValueAt(peakTime),
mode: 'log'

@@ -77,3 +76,3 @@ })

value: 0, at: at,
duration: obs.release(),
duration: obs.release.getValueAt(at),
mode: 'log'

@@ -88,2 +87,7 @@ })

obs.cancelFrom = function (at) {
at = Math.max(at, context.audio.currentTime)
broadcast({ mode: 'cancel', at: at })
}
obs.getReleaseDuration = function () {

@@ -90,0 +94,0 @@ return obs.release()

@@ -33,3 +33,3 @@ var Observ = require('observ')

curve: Param(context, 0.5),
curve: Param(context, 1),
skew: Param(context, 0)

@@ -58,3 +58,3 @@ })

var transform = Transform(context, [
{ param: eventSource },
{ param: eventSource, transform: offsetForOperation },
{ param: obs.amp, transform: multiply },

@@ -172,10 +172,8 @@ { param: obs.value, transform: operation }

function step (start, duration) {
var skew = clamp((obs.skew.getValueAt(start) + 1) / 2, 0, 0.999999999)
var skew = clamp((obs.skew.getValueAt(start) + 1), 0, 1.9999999999)
var curve = clamp(obs.curve.getValueAt(start), 0, 1)
var stepDuration = duration / 4
var up = stepDuration * skew * curve
var down = stepDuration * (1 - skew) * curve
var mid = start + (duration * skew)
var end = start + duration
var pause = (stepDuration - curve * stepDuration) * 2
var down = stepDuration * (2 - skew) * curve

@@ -189,3 +187,3 @@ broadcast({

broadcast({
at: mid - down,
at: start + up + pause,
value: 0,

@@ -196,13 +194,23 @@ duration: down

broadcast({
at: mid + up,
at: start + up + pause + down,
value: -1,
duration: up
duration: down
})
broadcast({
at: end - down,
at: start + up + pause + down + down + pause,
value: 0,
duration: down
duration: up
})
}
function offsetForOperation (_, value) {
var mode = obs.mode()
if (mode === 'add') {
return value
} else if (mode === 'subtract') {
return value
} else {
return (value + 1) / 2
}
}

@@ -209,0 +217,0 @@

@@ -6,3 +6,3 @@ var ObservStruct = require('observ-struct')

function ProcessorNode (context, input, output, params) {
function ProcessorNode (context, input, output, params, releases) {
var obs = ObservStruct(params)

@@ -28,3 +28,18 @@

obs.cancelFrom = function (at) {
Param.cancelFrom(obs, at)
}
obs.destroy = function () {
while (releases && releases.length) {
releases.pop()()
}
Object.keys(obs).forEach(function (key) {
if (obs[key] && typeof obs[key].destroy === 'function') {
obs[key].destroy()
}
})
}
return obs
}

@@ -33,2 +33,4 @@ var Processor = require('../processor.js')

var releases = []
var obs = Processor(context, input, output, {

@@ -44,3 +46,3 @@ time: Param(context, 0.25),

dry: Param(context, 1)
})
}, releases)

@@ -52,2 +54,5 @@ var rateMultiplier = Transform(context, [

// release context.tempo
releases.push(rateMultiplier.destroy)
var time = Transform(context, [

@@ -70,7 +75,2 @@ { param: obs.time },

obs.destroy = function () {
// release context.tempo
rateMultiplier.destroy()
}
return obs

@@ -77,0 +77,0 @@ }

@@ -25,3 +25,6 @@ var Processor = require('../processor.js')

ratio: Param(context, 1)
})
}, [
to.disconnect.bind(to),
from.disconnect.bind(from)
])

@@ -38,7 +41,2 @@ watch(obs.mode, function (value) {

obs.destroy = function () {
to.disconnect()
from.disconnect()
}
Apply(context, to.gain, obs.ratio)

@@ -45,0 +43,0 @@ Apply(context, from.gain, obs.ratio)

@@ -23,2 +23,3 @@ var Processor = require('../processor.js')

var wet = context.audio.createGain()
var releases = []

@@ -52,3 +53,3 @@ // feedback loop

dry: Param(context, 1)
})
}, releases)

@@ -60,2 +61,5 @@ var rateMultiplier = Transform(context, [

// release context.tempo
releases.push(rateMultiplier.destroy)
var time = Transform(context, [

@@ -79,7 +83,2 @@ { param: obs.time },

obs.destroy = function () {
// release context.tempo
rateMultiplier.destroy()
}
return obs

@@ -86,0 +85,0 @@ }

@@ -42,3 +42,3 @@ var Processor = require('../processor.js')

dry: Param(context, 1)
})
}, [cancel])

@@ -57,4 +57,6 @@ obs.time(refreshImpulse)

obs.destroy = function () {
// release context.tempo
return obs
// scoped
function cancel () {
if (building) {

@@ -65,13 +67,6 @@ buildImpulse.cancel(building)

return obs
// scoped
function refreshImpulse () {
var rate = context.audio.sampleRate
var length = Math.max(rate * obs.time(), 1)
if (building) {
buildImpulse.cancel(building)
}
cancel()
building = buildImpulse(length, obs.decay(), obs.reverse(), function (channels) {

@@ -78,0 +73,0 @@ var impulse = context.audio.createBuffer(2, length, rate)

@@ -10,3 +10,3 @@ var Observ = require('observ')

function RoutableSlot (context, properties, input, output) {
function RoutableSlot (context, properties, input, output, releases) {
var audioContext = context.audio

@@ -56,2 +56,7 @@

obs.destroy = function () {
Object.keys(obs).forEach(function (key) {
if (obs[key] && typeof obs[key].destroy === 'function') {
obs[key].destroy()
}
})
removeSlotWatcher && removeSlotWatcher()

@@ -58,0 +63,0 @@ removeSlotWatcher = null

@@ -1,12 +0,12 @@

var ObservStruct = require('observ-struct')
var Node = require('observ-node-array/single')
var ResolvedValue = require('observ-node-array/resolved-value')
var Param = require('audio-slot-param')
var Property = require('observ-default')
var Param = require('audio-slot-param')
var Transform = require('audio-slot-param/transform')
var Apply = require('audio-slot-param/apply')
var ResolvedValue = require('observ-node-array/resolved-value')
var Triggerable = require('../triggerable')
var ScheduleList = require('../lib/schedule-list')
var ScheduleEvent = require('../lib/schedule-event')
var SyncProperty = require('../lib/granular-sync')
var applyScheduler = require('../lib/apply-scheduler')

@@ -17,3 +17,5 @@ module.exports = GranularNode

var output = context.audio.createGain()
var releaseSchedule = applyScheduler(context, handleSchedule)
var amp = context.audio.createGain()
amp.gain.value = 0
amp.connect(output)

@@ -26,3 +28,3 @@ var offset = Property([0, 1])

var obs = ObservStruct({
var obs = Triggerable(context, {
mode: Property('loop'),

@@ -44,6 +46,5 @@

amp: Param(context, 1)
})
}, trigger)
Apply(context, output.gain, obs.amp)
obs.resolvedBuffer = resolvedBuffer
obs.context = context

@@ -57,125 +58,115 @@

obs.resolvedBuffer = resolvedBuffer
Apply(context, amp.gain, obs.amp)
var active = []
var scheduledTo = 0
var lastBeatDuration = 1
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
obs.choke = function (at) {
at = at || context.audio.currentTime
var event = eventAt(at - 0.02)
if (event) {
var stopAt = at + (0.02 * 6)
event.output.gain.setTargetAtTime(0, at, 0.02)
event.end = stopAt
}
return obs
// scoped
function trigger (at) {
return new GranularSample(obs, amp, playbackRate, at)
}
}
obs.triggerOn = function (at) {
obs.choke(at)
function noteOffsetToRate (baseRate, value) {
return baseRate * Math.pow(2, value / 12)
}
var amp = context.audio.createGain()
amp.connect(output)
function centsToRate (baseRate, value) {
return baseRate * Math.pow(2, value / 1200)
}
var stopAt = null
var event = {
start: at,
end: null,
nextTime: at,
nextOffset: 0,
output: amp
}
// internal class
if (obs.mode() === 'oneshot') {
event.oneshot = true
var duration = obs.sync() ? obs.duration() * lastBeatDuration : obs.duration()
stopAt = at + duration
Param.triggerOff(obs, stopAt)
truncate(stopAt)
event.end = stopAt
}
function GranularSample (obs, output, playbackRate, from) {
var clock = obs.context.scheduler
var nextTime = clock.getNextScheduleTime()
var schedule = {
time: from,
duration: nextTime - from,
beatDuration: clock.getBeatDuration()
}
at = at || context.audio.currentTime
truncate(at)
var length = obs.duration()
if (obs.sync()) {
length = length * schedule.beatDuration
}
Param.triggerOn(obs, at)
this.context = obs.context
this.obs = obs
this.from = from
this.to = NaN
this.nextTime = from
this.nextOffset = 0
this.choker = obs.context.audio.createGain()
this.choked = false
this.oneshot = obs.mode() === 'oneshot'
this.events = ScheduleList()
this.releases = [this.events.destroy]
this.playbackRate = playbackRate
active.push(event)
if (this.oneshot) {
this.to = from + length
}
if (at < scheduledTo) {
scheduleEvent(event, at, scheduledTo, lastBeatDuration)
}
this.choker.connect(output)
return stopAt
if (handleSchedule.call(this, schedule)) {
this.releases.push(clock.onSchedule(handleSchedule.bind(this)))
}
}
obs.triggerOff = function (at) {
at = at || context.audio.currentTime
var event = eventAt(at)
if (event && !event.oneshot) {
var stopAt = obs.getReleaseDuration() + at
Param.triggerOff(obs, stopAt)
truncate(stopAt)
event.end = stopAt
}
GranularSample.prototype.choke = function (at) {
if (!this.to || at < this.to) {
this.choker.gain.cancelScheduledValues(this.choker.context.currentTime)
this.choker.gain.setTargetAtTime(0, at, 0.02)
this.choked = true
this.to = at + 0.1
}
}
obs.destroy = function () {
// release context.noteOffset
playbackRate.destroy()
releaseSchedule && releaseSchedule()
releaseSchedule = null
GranularSample.prototype.cancelChoke = function (at) {
if (this.choked && this.stopAt) {
this.choker.gain.cancelScheduledValues(this.to - 0.1)
this.stop(this.stopAt)
}
}
obs.getReleaseDuration = Param.getReleaseDuration.bind(this, obs)
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
GranularSample.prototype.stop = function (at) {
at = at || this.choker.context.currentTime
this.events.truncateTo(this.context.audio.currentTime)
this.choker.gain.cancelScheduledValues(this.choker.context.currentTime)
this.choker.gain.setValueAtTime(0, at)
this.choked = false
this.stopAt = at
this.to = at
}
return obs
function handleSchedule (schedule) {
var obs = this.obs
var endTime = schedule.time + schedule.duration
// scoped
this.events.truncateTo(this.context.audio.currentTime)
if (endTime >= this.from && (!this.to || schedule.time < this.to)) {
var length = obs.duration()
var rate = obs.rate()
function handleSchedule (schedule) {
var from = schedule.time
var to = schedule.time + schedule.duration
for (var i = active.length - 1;i >= 0;i--) {
var event = active[i]
// clean up old events
if (event.end && event.end < context.audio.currentTime) {
event.output.disconnect()
active.splice(i, 1)
continue
}
scheduleEvent(event, from, to, schedule.beatDuration)
if (obs.sync()) {
length = length * schedule.beatDuration
rate = rate / schedule.beatDuration
}
lastBeatDuration = schedule.beatDuration
scheduledTo = to
}
var slices = Math.max(1, rate) * length
var duration = length / slices
function scheduleEvent (event, from, to, beatDuration) {
if (event.start <= from && (!event.end || event.end > to)) {
var length = obs.duration()
var rate = obs.rate()
if (obs.sync()) {
length = length * beatDuration
rate = rate / beatDuration
while (this.nextTime < endTime) {
var event = play.call(this, this.nextTime, this.nextOffset, duration)
if (event) {
this.events.push(event)
}
var slices = Math.max(1, rate) * length
var duration = length / slices
while (event.nextTime < to) {
play(event.output, event.nextTime, event.nextOffset, duration)
event.nextTime += duration
event.nextOffset += 1 / slices
if (obs.mode() !== 'oneshot') {
event.nextOffset = event.nextOffset % 1
}
this.nextTime += duration
this.nextOffset += 1 / slices
if (obs.mode() !== 'oneshot') {
this.nextOffset = this.nextOffset % 1
}

@@ -185,71 +176,57 @@ }

function play (output, at, startOffset, grainDuration) {
var event = eventAt(at)
if (!this.to || this.to > endTime) {
return true
}
}
var buffer = obs.resolvedBuffer()
if (buffer instanceof window.AudioBuffer) {
var source = context.audio.createBufferSource()
source.buffer = buffer
function play (at, startOffset, grainDuration) {
var obs = this.obs
var context = this.context
var buffer = obs.resolvedBuffer()
if (buffer instanceof window.AudioBuffer && isFinite(startOffset) && grainDuration) {
var source = context.audio.createBufferSource()
source.buffer = buffer
var offset = obs.offset()
var start = offset[0] * source.buffer.duration
var end = offset[1] * source.buffer.duration
var duration = end - start
var offset = obs.offset()
var start = offset[0] * source.buffer.duration
var end = offset[1] * source.buffer.duration
var duration = end - start
var release = grainDuration * obs.release()
var attack = grainDuration * obs.attack()
var release = grainDuration * obs.release()
var attack = grainDuration * obs.attack()
// make sure it doesn't exceed the stop time
var maxTime = (event && event.end || Infinity) - release
var releaseAt = Math.min(at + grainDuration * obs.hold(), maxTime)
// make sure it doesn't exceed the stop time
var maxTime = (this.to || Infinity) - release
var releaseAt = Math.min(at + grainDuration * obs.hold(), maxTime)
source.playbackRate.value = playbackRate.getValueAt(at)
source.playbackRate.value = this.playbackRate.getValueAt(at)
if (obs.mode() !== 'oneshot' && releaseAt + release > startOffset * duration) {
source.loop = true
source.loopStart = start
source.loopEnd = end
}
if (obs.mode() !== 'oneshot' && releaseAt + release > startOffset * duration) {
source.loop = true
source.loopStart = start
source.loopEnd = end
}
source.start(at, startOffset * duration + start)
source.stop(releaseAt + release * 2)
source.start(at, startOffset * duration + start)
source.stop(releaseAt + release * 2)
var envelope = context.audio.createGain()
envelope.gain.value = 0
source.connect(envelope)
var envelope = context.audio.createGain()
envelope.gain.value = 0
source.connect(envelope)
// envelope
if (attack) {
envelope.gain.setTargetAtTime(1, at, attack / 4)
}
envelope.gain.setTargetAtTime(0, releaseAt, release / 4)
envelope.connect(output)
// envelope
if (attack) {
envelope.gain.setTargetAtTime(1, at, attack / 4)
}
}
envelope.gain.setTargetAtTime(0, releaseAt, release / 4)
envelope.connect(this.choker)
function truncate (at) {
for (var i = active.length - 1;i >= 0;i--) {
if (active[i].start >= at) {
active.splice(i, 1)
} else if (active[i].end && active[i].end > at) {
active[i].end = at
}
}
}
var event = new ScheduleEvent(at, source, envelope, [
Apply(context, source.playbackRate, this.playbackRate)
])
function eventAt (time) {
for (var i = 0;i < active.length;i++) {
if (active[i].start <= time && (!active[i].end || active[i].end > time)) {
return active[i]
}
}
event.to = releaseAt + release
return event
}
}
function noteOffsetToRate (baseRate, value) {
return baseRate * Math.pow(2, value / 12)
}
function centsToRate (baseRate, value) {
return baseRate * Math.pow(2, value / 1200)
}

@@ -1,2 +0,2 @@

var computed = require('observ/computed')
var computed = require('../lib/computed-next-tick')
var ObservStruct = require('observ-struct')

@@ -7,2 +7,4 @@ var Property = require('observ-default')

var Apply = require('audio-slot-param/apply')
var Triggerable = require('../triggerable')
var ScheduleEvent = require('../lib/schedule-event')

@@ -13,79 +15,46 @@ module.exports = NoiseNode

var output = context.audio.createGain()
var amp = context.audio.createGain()
amp.gain.value = 0
amp.connect(output)
var obs = ObservStruct({
var obs = Triggerable(context, {
type: Property('white'),
stereo: Property(false),
amp: Param(context, 0.4)
})
}, trigger)
obs.context = context
obs.resolvedBuffer = computed([obs.type, obs.stereo], function (type, stereo) {
if (type === 'pink') {
return generatePinkNoise(context.audio, 4096 * 2, stereo ? 2 : 1)
return generatePinkNoise(context.audio, 4096 * 4, stereo ? 2 : 1)
} else {
return generateWhiteNoise(context.audio, 4096 * 2, stereo ? 2 : 1)
return generateWhiteNoise(context.audio, 4096 * 4, stereo ? 2 : 1)
}
})
var player = null
var choker = null
var amp = null
var releaseAmp = null
var playTo = false
obs.context = context
obs.getReleaseDuration = Param.getReleaseDuration.bind(this, obs)
Apply(context, amp.gain, obs.amp)
obs.choke = function (at) {
stop(at + (0.02 * 6))
if (choker && at < playTo) {
choker.gain.setTargetAtTime(0, at, 0.02)
}
}
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
obs.triggerOn = function (at) {
obs.choke(at)
return obs
// scoped
function trigger (at) {
var buffer = obs.resolvedBuffer()
if (buffer instanceof window.AudioBuffer) {
choker = context.audio.createGain()
amp = context.audio.createGain()
player = context.audio.createBufferSource()
var choker = context.audio.createGain()
var player = context.audio.createBufferSource()
player.connect(choker)
choker.connect(amp)
amp.gain.value = 0
releaseAmp = Apply(context, amp.gain, obs.amp)
player.connect(amp)
amp.connect(choker)
choker.connect(output)
player.buffer = buffer
player.loop = true
player.start(at, 0)
Param.triggerOn(obs, at)
}
}
obs.triggerOff = function (at) {
at = at || context.audio.currentTime
var stopAt = obs.getReleaseDuration() + at
Param.triggerOff(obs, stopAt)
stop(stopAt)
}
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
return obs
// scoped
function stop (at) {
if (player) {
playTo = at
player.stop(at)
releaseAmp()
return new ScheduleEvent(at, player, choker, [
choker.disconnect.bind(choker)
])
}

@@ -92,0 +61,0 @@ }

@@ -1,9 +0,9 @@

var ObservStruct = require('observ-struct')
var Triggerable = require('../triggerable')
var Param = require('audio-slot-param')
var Property = require('observ-default')
var Transform = require('audio-slot-param/transform')
var Apply = require('audio-slot-param/apply')
var applyScheduler = require('../lib/apply-scheduler')
var watch = require('observ/watch')
var Property = require('observ-default')
var ScheduleEvent = require('../lib/schedule-event')

@@ -13,18 +13,10 @@ module.exports = OscillatorNode

function OscillatorNode (context) {
var oscillator = null
var output = context.audio.createGain()
var amp = context.audio.createGain()
var power = context.audio.createGain()
var amp = context.audio.createGain()
var choker = context.audio.createGain()
var output = context.audio.createGain()
choker.gain.value = 0
amp.gain.value = 0
power.connect(amp)
amp.connect(choker)
amp.connect(output)
var releaseSchedule = applyScheduler(context, handleSchedule)
var releaseSync = []
var obs = ObservStruct({
var obs = Triggerable(context, {
amp: Param(context, 1),

@@ -36,8 +28,4 @@ frequency: Param(context, 440),

shape: Property('sine') // Param(context, multiplier.gain, 1)
})
}, trigger)
var maxTime = null
var lastOn = -1
var lastOff = 0
obs.context = context

@@ -56,105 +44,40 @@

Apply(context, power.gain, powerRolloff)
Apply(context, amp.gain, obs.amp)
Apply(context, power.gain, powerRolloff)
obs.shape(refreshShape)
obs.getReleaseDuration = Param.getReleaseDuration.bind(this, obs)
obs.choke = function (at) {
if (choker) {
choker.gain.setTargetAtTime(0, at, 0.02)
}
}
obs.triggerOn = function (at) {
at = at || context.audio.currentTime
choker.connect(output)
choker.gain.cancelScheduledValues(at)
choker.gain.setValueAtTime(1, at)
// start modulators
Param.triggerOn(obs, at)
maxTime = null
if (lastOn < at) {
lastOn = at
}
}
obs.triggerOff = function (at) {
at = at || context.audio.currentTime
var stopAt = obs.getReleaseDuration() + at
// stop modulators
Param.triggerOff(obs, stopAt)
choker.gain.setValueAtTime(0, stopAt)
if (stopAt > maxTime) {
maxTime = stopAt
}
if (lastOff < at) {
lastOff = at
}
}
obs.destroy = function () {
// release context.noteOffset
frequency.destroy()
releaseSchedule && releaseSchedule()
releaseSchedule = null
}
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
resync()
return obs
//
// scoped
function trigger (at) {
var oscillator = context.audio.createOscillator()
var choker = context.audio.createGain()
oscillator.start(at)
oscillator.connect(choker)
choker.connect(amp)
function handleSchedule (schedule) {
if (maxTime && context.audio.currentTime > maxTime) {
maxTime = null
choker.disconnect()
resync()
}
return new ScheduleEvent(at, oscillator, choker, [
Apply(context, oscillator.detune, obs.detune),
Apply(context, oscillator.frequency, frequency),
ApplyShape(context, oscillator, obs.shape),
choker.disconnect.bind(choker)
])
}
}
function resync () {
while (releaseSync.length) {
releaseSync.pop()()
}
function ApplyShape (context, target, shape) {
return watch(shape, setShape.bind(this, context, target))
}
if (oscillator) {
oscillator.disconnect()
function setShape (context, target, value) {
if (value !== target.lastShape) {
if (context.periodicWaves && context.periodicWaves[value]) {
target.setPeriodicWave(context.periodicWaves[value])
} else {
target.type = value
}
oscillator = context.audio.createOscillator()
oscillator.lastShape = 'sine'
refreshShape()
oscillator.connect(power)
oscillator.start()
releaseSync.push(
Apply(context, oscillator.detune, obs.detune),
Apply(context, oscillator.frequency, frequency)
)
target.lastShape = value
}
function refreshShape () {
var shape = obs.shape()
if (shape !== oscillator.lastShape) {
if (context.periodicWaves && context.periodicWaves[shape]) {
oscillator.setPeriodicWave(context.periodicWaves[shape])
} else {
oscillator.type = shape
}
oscillator.lastShape = shape
}
}
}

@@ -161,0 +84,0 @@

@@ -1,10 +0,11 @@

var ObservStruct = require('observ-struct')
var Node = require('observ-node-array/single')
var ResolvedValue = require('observ-node-array/resolved-value')
var Param = require('audio-slot-param')
var Property = require('observ-default')
var Param = require('audio-slot-param')
var Transform = require('audio-slot-param/transform')
var Apply = require('audio-slot-param/apply')
var watch = require('observ/watch')
var ResolvedValue = require('observ-node-array/resolved-value')
var Triggerable = require('../triggerable')
var ScheduleEvent = require('../lib/schedule-event')

@@ -15,4 +16,7 @@ module.exports = SampleNode

var output = context.audio.createGain()
var amp = context.audio.createGain()
amp.gain.value = 0
amp.connect(output)
var obs = ObservStruct({
var obs = Triggerable(context, {
mode: Property('hold'),

@@ -25,20 +29,7 @@ offset: Property([0, 1]),

tune: Param(context, 0)
}, trigger)
})
obs.resolvedBuffer = ResolvedValue(obs.buffer)
obs.context = context
var player = null
var choker = null
var amp = null
var lastChoke = 0
var releases = []
var playTo = false
var triggerOnRelease = false
var isOneshot = false
var playbackRate = Transform(context, [ 1,

@@ -50,119 +41,51 @@ { param: context.noteOffset, transform: noteOffsetToRate },

obs.offset(function (value) {
var buffer = obs.resolvedBuffer()
if (buffer && player && Array.isArray(value)) {
player.loopStart = buffer.duration * value[0]
player.loopEnd = buffer.duration * value[1]
}
})
Apply(context, amp.gain, obs.amp)
obs.choke = function (at) {
stop(at + (0.02 * 6))
if (choker && at < playTo) {
lastChoke = at
choker.gain.setTargetAtTime(0, at, 0.02)
}
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
// clean up
while (releases.length) {
releases.pop()()
}
}
return obs
obs.triggerOn = function (at) {
obs.choke(at)
// scoped
function trigger (at) {
var buffer = obs.resolvedBuffer()
var mode = obs.mode()
var buffer = obs.resolvedBuffer()
if (buffer instanceof window.AudioBuffer) {
playTo = null
choker = context.audio.createGain()
amp = context.audio.createGain()
player = context.audio.createBufferSource()
var choker = context.audio.createGain()
var player = context.audio.createBufferSource()
player.connect(choker)
choker.connect(amp)
releases.push(
Apply(context, amp.gain, obs.amp),
Apply(context, player.playbackRate, playbackRate)
)
// nice fade on retrigger (after choke)
if (Math.abs(at - lastChoke) < 0.02) {
choker.gain.setValueAtTime(0, at)
choker.gain.setTargetAtTime(1, at, 0.001)
}
player.connect(amp)
amp.connect(choker)
choker.connect(output)
player.buffer = buffer
player.loopStart = buffer.duration * obs.offset()[0]
player.loopEnd = buffer.duration * obs.offset()[1]
player.onended = disconnectSelf
if (mode === 'loop') {
player.loop = true
player.start(at, player.loopStart, 1000)
Param.triggerOn(obs, at)
} else if (mode === 'release') {
triggerOnRelease = true
} else if (mode === 'oneshot') {
var event = new ScheduleEvent(at, player, choker, [
Apply(context, player.playbackRate, playbackRate),
ApplyLoopMode(context, player, obs.mode),
choker.disconnect.bind(choker)
])
event.to = at + (player.loopEnd - player.loopStart) / playbackRate.getValueAt(at)
if (mode !== 'release') {
player.start(at, player.loopStart)
Param.triggerOn(obs, at)
var duration = (player.loopEnd - player.loopStart) / playbackRate.getValueAt(at)
var maxDuration = buffer.duration - player.loopStart / playbackRate.getValueAt(at)
var extra = Math.max(0, obs.getReleaseDuration() - maxDuration)
obs.triggerOff(at + duration - extra)
isOneshot = true
} else {
player.start(at, player.loopStart, player.loopEnd - player.loopStart)
Param.triggerOn(obs, at)
}
}
}
obs.triggerOff = function (at) {
if (isOneshot) {
isOneshot = false
} else {
at = at || context.audio.currentTime
var stopAt = obs.getReleaseDuration() + at
if (triggerOnRelease) {
Param.triggerOn(obs, at)
player.start(at, player.loopStart, player.loopEnd - player.loopStart)
stopAt += player.loopEnd - player.loopStart
triggerOnRelease = false
if (mode === 'oneshot') {
event.oneshot = true
}
Param.triggerOff(obs, stopAt)
stop(stopAt)
return event
}
}
}
obs.destroy = function () {
// release context.noteOffset
playbackRate.destroy()
}
obs.getReleaseDuration = Param.getReleaseDuration.bind(this, obs)
obs.connect = output.connect.bind(output)
obs.disconnect = output.disconnect.bind(output)
return obs
// scoped
function stop (at) {
if ((!playTo || at < playTo) && player) {
playTo = at
player.stop(at)
}
}
function ApplyLoopMode (context, target, mode) {
return watch(mode, setLoopMode.bind(this, context, target))
}
function disconnectSelf () {
this.disconnect()
function setLoopMode (context, target, mode) {
target.loop = mode === 'loop'
}

@@ -169,0 +92,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc