Skip to content
This repository was archived by the owner on Nov 6, 2020. It is now read-only.

Commit c0c2d0a

Browse files
committed
too many to list
1 parent 442ebeb commit c0c2d0a

17 files changed

+202
-75
lines changed

dynamic-cache.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ export default class DynamicCache {
22
static async cleanup () {
33
const cacheKeys = await window.caches.keys()
44
await Promise.all(cacheKeys
5-
.filter(key => key.startsWith('dynamic-cache:'))
5+
// .filter(key => key.startsWith('dynamic-cache:')) //TODO: enable this in prod
66
.map(key => window.caches.delete(key))
77
)
88
}

lib/impulse-convolve-stereo.js

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import convolve from './convolve.js'
2+
3+
export default async (c, url, length) => {
4+
const impulse = await c.sample(url)
5+
if (length > -1) {
6+
impulse[0] = impulse[0].subarray(0, length)
7+
impulse[1] = impulse[1].subarray(0, length)
8+
}
9+
const id = 'impulse-convolve-stereo:kernel:' + url + ':' + c.buffer[0].length + ':' + length
10+
let kernel = await c.get(id)
11+
if (kernel === false) {
12+
// console.log('processing kernel:', id)
13+
kernel = [
14+
convolve.fftProcessKernel(c.buffer[0].length, impulse[0]),
15+
convolve.fftProcessKernel(c.buffer[0].length, impulse[1])
16+
]
17+
await c.set(id, kernel)
18+
// console.log('set kernel cache:', id)
19+
} else {
20+
// console.log('got cached kernel:', id)
21+
}
22+
const reverb = [
23+
convolve.fftConvolution(c.buffer[0].length, kernel[0], impulse[0].length),
24+
convolve.fftConvolution(c.buffer[0].length, kernel[1], impulse[0].length)
25+
]
26+
return reverb
27+
}

lib/impulse-convolve.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ export default async (c, url, length) => {
88
const id = 'kernel:' + url + ':' + c.buffer[0].length + ':' + length
99
let kernel = await c.get(id)
1010
if (kernel === false) {
11-
console.log('processing kernel:', id)
11+
// console.log('processing kernel:', id)
1212
kernel = convolve.fftProcessKernel(c.buffer[0].length, impulse[0])
1313
await c.set(id, kernel)
14-
console.log('set kernel cache:', id)
14+
// console.log('set kernel cache:', id)
1515
} else {
16-
console.log('got cached kernel:', id)
16+
// console.log('got cached kernel:', id)
1717
}
1818
const reverb = convolve.fftConvolution(c.buffer[0].length, kernel, impulse[0].length)
1919
return reverb

lib/impulse-reverb-stereo.js

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import impulseConvolve from './impulse-convolve-stereo.js'
2+
3+
export default async (c, { url, offset = 0, length = -1, id = '' }=c) => {
4+
const reverb = await impulseConvolve(c, url, length)
5+
let tail = 0
6+
let prev = (await c.get('impulse-reverb-stereo:prev:'+id+url+(c.n-c.buffer[0].length)))
7+
||[new Float32Array(),new Float32Array()]
8+
let curr
9+
let len = 0
10+
let i = 0
11+
return c => {
12+
len = c.buffer[0].length
13+
curr = [
14+
reverb[0](c.buffer[0]),
15+
reverb[1](c.buffer[1])
16+
]
17+
// add remaining tail from previous step
18+
for (i = 0; i < prev[0].length; i++) {
19+
curr[0][i] += prev[0][i]
20+
curr[1][i] += prev[1][i]
21+
}
22+
tail = (curr[0].length - offset) - len
23+
prev[0] = curr[0].subarray(-tail)
24+
prev[1] = curr[1].subarray(-tail)
25+
c.set('impulse-reverb-stereo:prev:'+id+url+c.n, prev, 5000)
26+
return [
27+
curr[0].subarray(offset, offset + len),
28+
curr[1].subarray(offset, offset + len),
29+
]
30+
}
31+
}

lib/impulse-reverb.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import impulseConvolve from './impulse-convolve.js'
22

3-
export default async (c, { url, offset = 0, length = -1 }=c) => {
3+
export default async (c, { url, offset = 0, length = -1, id = '' }=c) => {
44
const reverb = await impulseConvolve(c, url, length)
55
let tail = 0
6-
let prev = (await c.get('prev:'+url+(c.n-c.buffer[0].length)))||new Float32Array()
6+
let prev = (await c.get('prev:'+id+url+(c.n-c.buffer[0].length)))||new Float32Array()
77
let curr
88
let len = 0
99
let i = 0
@@ -16,7 +16,7 @@ export default async (c, { url, offset = 0, length = -1 }=c) => {
1616
}
1717
tail = (curr.length - offset) - len
1818
prev = curr.subarray(-tail)
19-
c.set('prev:'+url+c.n, prev, 5000)
19+
c.set('prev:'+id+url+c.n, prev, 5000)
2020
return curr.subarray(offset, offset + len)
2121
}
2222
}

src/buffer-service.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ const garbageCollect = match => {
2121
}
2222

2323
const BufferService = {
24+
buffers,
2425
methods: {
2526
getBuffer: (checksum, size, channels = 2) => {
2627
const id = (checksum + size + channels).toString()

src/context.js

Lines changed: 57 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import randomId from '../lib/random-id.js'
22
import checksumOf from '../lib/checksum.js'
33
import ImpulseReverb from '../lib/impulse-reverb.js'
4+
import ImpulseReverbStereo from '../lib/impulse-reverb-stereo.js'
45
import mixWorker from './mix-worker-service.js'
56
import mixBuffers from './mix-buffers.js'
67
import rpc from './lazy-singleton-worker-rpc.js'
@@ -52,7 +53,7 @@ export default class Context {
5253
}
5354

5455
constructor (data) {
55-
this.id = randomId()
56+
this.id = data.id ?? randomId()
5657

5758
this.bpm = 60
5859
this.beatRate = 44100
@@ -108,7 +109,7 @@ export default class Context {
108109

109110
// public api
110111

111-
buf ({ id = '', len = this.buffer[0].length, ch = this.buffer.length } = {}) {
112+
buf ({ id = '', len = this.bufferSize, ch = this.buffer.length } = {}) {
112113
return rpc(BUFFER_SERVICE_URL, 'getBuffer', [
113114
id+checksumOf(this),
114115
len|0,
@@ -132,6 +133,10 @@ export default class Context {
132133
return ImpulseReverb(this, params)
133134
}
134135

136+
reverbStereo (params) {
137+
return ImpulseReverbStereo(this, params)
138+
}
139+
135140
zero (buffer = this.buffer) {
136141
buffer.forEach(b => b.fill(0))
137142
return buffer
@@ -140,22 +145,64 @@ export default class Context {
140145
src (url, params = {}) {
141146
const targetUrl = new URL(url, this.url ?? location.href).href
142147
const context = Object.assign(this.toJSON(), params, { url: targetUrl })
143-
// const checksum = c.checksum
144-
145-
// if (checksums[c.url + c.id] === checksum) return
146-
147-
// checksums[c.url + c.id] = checksum
148-
// console.log('here!')
149148
return mixWorker(targetUrl, context).then(result => {
150149
result.update = c => { c.src(url, params) }
151150
return result
152151
})
153152
}
154153

155-
mix(...args) {
154+
async render (name, params) {
155+
const id = name + checksumOf(params)
156+
const buffer = await this.buf({ ...params, id })
157+
if (buffer.createdNow) {
158+
console.log('shall render', name, id, buffer, params)
159+
await this.src('./' + name + '.js', { buffer, ...params, id })
160+
}
161+
return buffer
162+
}
163+
164+
mix (...args) {
156165
return mixBuffers(...args)
157166
}
158167

168+
async import (sources) {
169+
const entries = await Promise.all(
170+
Object.entries(sources)
171+
.map(async ([key, value]) => {
172+
const params = { ...value }
173+
delete params.src
174+
const buffer = await this.render(value.src ?? key, {
175+
id: key,
176+
...params,
177+
})
178+
return [key, buffer]
179+
}))
180+
181+
return Object.fromEntries(entries)
182+
}
183+
184+
// async import (sources) {
185+
// const entries = await Promise.all(
186+
// Object.entries(sources)
187+
// .map(async ([key, value]) => {
188+
// const buffer = value.buffer ?? await this.buf({
189+
// id: value.id ?? key,
190+
// len: value.len ?? this.br,
191+
// ch: value.ch ?? 1,
192+
// })
193+
// const params = { ...value }
194+
// delete params.src
195+
// const src = await this.src('./' + (value.src ?? key) + '.js', {
196+
// id: key,
197+
// ...params,
198+
// buffer
199+
// })
200+
// return [key, buffer]
201+
// }))
202+
203+
// return Object.fromEntries(entries)
204+
// }
205+
159206
// internals
160207

161208
prepare () {
@@ -195,35 +242,16 @@ export default class Context {
195242
this.k = this.p1 / this.br
196243
}
197244

198-
// get checksum () {
199-
// return checksumOf(this)
200-
// }
201-
202-
// set checksum (value) {
203-
// /* ignore */
204-
// }
205-
206-
get bufferSize () { return this.buffer[0].length }
207-
208-
// get c () { return this }
209-
// get sr () { return this.sampleRate }
210-
// get br () { return this.beatRate }
245+
get bufferSize () { return this.buffer[0].length*4 }
211246

212247
toJSON () {
213248
const json = {}
214-
// this.prepare()
215249
for (const key in this) {
216250
if (key[0] === '_') continue
217251
if (typeof this[key] !== 'function') {
218252
json[key] = this[key]
219253
}
220254
}
221-
// delete json.g
222-
// delete json.worker
223-
// delete json.parent
224-
// json.n = this.n
225-
// json.frame = this.frame
226-
// json.checksum = this.checksum
227255
return json
228256
}
229257

src/global-service.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ const values = new Map
44
const ttlMap = new Map
55

66
const GlobalService = {
7+
values,
8+
ttlMap,
79
methods: {
810
get: id => {
911
const value = values.get(id)
@@ -32,10 +34,10 @@ setInterval(() => {
3234
if (now > time + ttl) {
3335
ttlMap.delete(id)
3436
values.delete(id)
35-
console.warn('gs gc:', id, ttl, [values.size])
37+
console.log('gs gc:', id, ttl, [values.size])
3638
}
3739
}
38-
if (values.size > 10) {
40+
if (values.size > 30) {
3941
console.warn('gs: too many values:', values.size)
4042
}
4143
}, 1000)

src/lazy-singleton-worker-rpc.js

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ export const rpcs = new Map
1010

1111
const rpc = (url, method, args = []) => getRpc(url).rpc(method, args)
1212
rpc.get = url => getRpc(url)
13-
rpc.update = url => getRpc(url).worker.updateInstance()
13+
rpc.update = (url, noCreate = false) => getRpc(url, noCreate)?.worker?.updateInstance()
1414
rpc.markAsSafe = url => getRpc(url).worker.markAsSafe()
1515
rpc.clear = () => rpcs.clear()
1616
rpc.clearHanging = error => { [...callbacks.values()].forEach(fn => fn.reject(error)), callbacks.clear() }
@@ -37,6 +37,8 @@ class Rpc {
3737
this.worker = new SafeDynamicWorker(url)
3838
workers.set(url, this.worker)
3939
this.bindListeners()
40+
} else if (this.worker.paused) {
41+
this.worker.updateInstance()
4042
}
4143
}
4244
}
@@ -49,9 +51,10 @@ class Rpc {
4951
}
5052
this[data.call](data)
5153
}
52-
this.worker.onmessageerror = error => rpc.onmessageerror?.(error, url)
53-
this.worker.onerror = error => rpc.onerror?.(error, url)
54-
this.worker.onfail = fail => rpc.onfail?.(fail, url)
54+
this.worker.onmessageerror = error => rpc.onmessageerror?.(error, this.url)
55+
this.worker.onerror = error => rpc.onerror?.(error, this.url)
56+
this.worker.onfail = fail => rpc.onfail?.(fail, this.url)
57+
this.worker.onpause = () => rpcs.delete(this.url)
5558
}
5659

5760
async proxyRpc ({ url, callbackId, method, args }) {
@@ -133,10 +136,13 @@ class RpcProxy {
133136
}
134137
}
135138

136-
const getRpc = url => {
139+
const getRpc = (url, noCreate = false) => {
137140
url = new URL(url, location.href).href
138141
if (isMain) {
139-
if (!rpcs.has(url)) rpcs.set(url, new Rpc(url))
142+
if (!rpcs.has(url)) {
143+
if (noCreate) return
144+
rpcs.set(url, new Rpc(url))
145+
}
140146
return rpcs.get(url)
141147
} else {
142148
return new RpcProxy(url)

src/loop-node.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ export default class LoopNode {
4646
}
4747

4848
get bufferSize () {
49-
return this.beatRate * 4 /// 5 | 0
49+
return this.beatRate * 4 //* 4 /// 5 | 0
5050
}
5151

5252
resetTime (offset = 0) {
@@ -97,7 +97,6 @@ export default class LoopNode {
9797
}
9898

9999
playBuffer (buffer) {
100-
// console.log('should render buffer:', buffer[0].slice(0,3))
101100
const syncTime = this.syncTime
102101
const output = this.nextBuffer
103102
for (let i = 0; i < this.numberOfChannels; i++) {
@@ -110,7 +109,6 @@ export default class LoopNode {
110109
}
111110

112111
if (!this.scheduledNode) {
113-
// console.log('schedule for', syncTime)
114112
const node = this.scheduledNode = this.context.createBufferSource()
115113
node.buffer = this.nextBuffer
116114
node.connect(this.gain)

0 commit comments

Comments
 (0)