mirror of
https://codeberg.org/uzu/strudel
synced 2026-07-23 21:47:16 -04:00
Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 947dd76823 | |||
| 28eedae730 | |||
| e075095e8b | |||
| 84e3f12171 | |||
| 260c6e0783 | |||
| bc3481822c |
@@ -2320,6 +2320,23 @@ export const { miditouch } = registerControl('miditouch');
|
|||||||
// TODO: what is this?
|
// TODO: what is this?
|
||||||
export const { polyTouch } = registerControl('polyTouch');
|
export const { polyTouch } = registerControl('polyTouch');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a control name exists in the controlAlias map.
|
||||||
|
* @name hasControlName
|
||||||
|
* @param {string} alias The control name to check
|
||||||
|
* @returns {boolean} True if the control name exists, false otherwise
|
||||||
|
*/
|
||||||
|
export const hasControlName = (alias) => {
|
||||||
|
// Check if the name exists as a key (alias) or value (main control name)
|
||||||
|
return controlAlias.has(alias) || Array.from(controlAlias.values()).includes(alias);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the control name from the controlAlias map.
|
||||||
|
* @name getControlName
|
||||||
|
* @param {string} alias The control name to get
|
||||||
|
* @returns {string} The control name
|
||||||
|
*/
|
||||||
export const getControlName = (alias) => {
|
export const getControlName = (alias) => {
|
||||||
if (controlAlias.has(alias)) {
|
if (controlAlias.has(alias)) {
|
||||||
return controlAlias.get(alias);
|
return controlAlias.get(alias);
|
||||||
|
|||||||
@@ -8,6 +8,14 @@ This package adds midi functionality to strudel Patterns.
|
|||||||
npm i @strudel/midi --save
|
npm i @strudel/midi --save
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Enabling MIDI for Local Development in Chrome
|
||||||
|
|
||||||
|
1. Open Chrome and navigate to `chrome://flags`
|
||||||
|
2. Search for "Insecure origins treated as secure"
|
||||||
|
3. In the text field that appears, add your development origin (e.g., http://localhost:3000)
|
||||||
|
4. Enable the flag
|
||||||
|
5. Restart Chrome
|
||||||
|
|
||||||
## Available Controls
|
## Available Controls
|
||||||
|
|
||||||
The following MIDI controls are available:
|
The following MIDI controls are available:
|
||||||
|
|||||||
+40
-7
@@ -6,7 +6,7 @@ This program is free software: you can redistribute it and/or modify it under th
|
|||||||
|
|
||||||
import * as _WebMidi from 'webmidi';
|
import * as _WebMidi from 'webmidi';
|
||||||
import { Pattern, getEventOffsetMs, isPattern, logger, ref } from '@strudel/core';
|
import { Pattern, getEventOffsetMs, isPattern, logger, ref } from '@strudel/core';
|
||||||
import { noteToMidi, getControlName } from '@strudel/core';
|
import { noteToMidi, hasControlName, getControlName, registerControl } from '@strudel/core';
|
||||||
import { Note } from 'webmidi';
|
import { Note } from 'webmidi';
|
||||||
|
|
||||||
// if you use WebMidi from outside of this package, make sure to import that instance:
|
// if you use WebMidi from outside of this package, make sure to import that instance:
|
||||||
@@ -100,10 +100,34 @@ export const midicontrolMap = new Map();
|
|||||||
function unifyMapping(mapping) {
|
function unifyMapping(mapping) {
|
||||||
return Object.fromEntries(
|
return Object.fromEntries(
|
||||||
Object.entries(mapping).map(([key, mapping]) => {
|
Object.entries(mapping).map(([key, mapping]) => {
|
||||||
|
// Convert number to object with ccn property
|
||||||
if (typeof mapping === 'number') {
|
if (typeof mapping === 'number') {
|
||||||
mapping = { ccn: mapping };
|
mapping = { ccn: mapping };
|
||||||
}
|
}
|
||||||
return [getControlName(key), mapping];
|
|
||||||
|
// Get the non-aliased control name from the key
|
||||||
|
const controlName = getControlName(key);
|
||||||
|
|
||||||
|
// Check if the key or controlName already exists in the controlAlias map
|
||||||
|
if (hasControlName(key) || hasControlName(controlName)) {
|
||||||
|
// Show warning and carry on.
|
||||||
|
logger(`[midimap] '[${key}, ${controlName}]' overwrites a Strudel API.`);
|
||||||
|
|
||||||
|
// Throw error to stop the music
|
||||||
|
//throw new Error(`[midimap] '${key}' overwrites a Strudel API.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the control in the midicontrolMap if it doesn't exist
|
||||||
|
if (!midicontrolMap.has(controlName)) {
|
||||||
|
try {
|
||||||
|
registerControl(controlName);
|
||||||
|
} catch (err) {
|
||||||
|
throw new Error(`[midimap] Failed to register midimap control '${controlName}': ${err.message}`);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger(`[midimap] '${controlName}' already registered as a midimap control. Skipping registration.`);
|
||||||
|
}
|
||||||
|
return [controlName, mapping];
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -162,7 +186,14 @@ export async function midimaps(map) {
|
|||||||
map = await loadCache[map];
|
map = await loadCache[map];
|
||||||
}
|
}
|
||||||
if (typeof map === 'object') {
|
if (typeof map === 'object') {
|
||||||
Object.entries(map).forEach(([name, mapping]) => midicontrolMap.set(name, unifyMapping(mapping)));
|
Object.entries(map).forEach(([name, mapping]) => {
|
||||||
|
try {
|
||||||
|
midicontrolMap.set(name, unifyMapping(mapping));
|
||||||
|
} catch (err) {
|
||||||
|
logger(`[midi] Error setting midimap '${name}': ${err.message}`);
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,18 +355,18 @@ Pattern.prototype.midi = function (midiport, options = {}) {
|
|||||||
const device = getDevice(midiConfig.midiport, outputs);
|
const device = getDevice(midiConfig.midiport, outputs);
|
||||||
const otherOutputs = outputs.filter((o) => o.name !== device.name);
|
const otherOutputs = outputs.filter((o) => o.name !== device.name);
|
||||||
logger(
|
logger(
|
||||||
`Midi enabled! Using "${device.name}". ${
|
`[midi] Midi enabled! Using "${device.name}". ${
|
||||||
otherOutputs?.length ? `Also available: ${getMidiDeviceNamesString(otherOutputs)}` : ''
|
otherOutputs?.length ? `Also available: ${getMidiDeviceNamesString(otherOutputs)}` : ''
|
||||||
}`,
|
}`,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
onDisconnected: ({ outputs }) =>
|
onDisconnected: ({ outputs }) =>
|
||||||
logger(`Midi device disconnected! Available: ${getMidiDeviceNamesString(outputs)}`),
|
logger(`[midi] Midi device disconnected! Available: ${getMidiDeviceNamesString(outputs)}`),
|
||||||
});
|
});
|
||||||
|
|
||||||
return this.onTrigger((hap, currentTime, cps, targetTime) => {
|
return this.onTrigger((hap, currentTime, cps, targetTime) => {
|
||||||
if (!WebMidi.enabled) {
|
if (!WebMidi.enabled) {
|
||||||
logger('Midi not enabled');
|
logger('[midi] Midi not enabled');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
hap.ensureObjectValue();
|
hap.ensureObjectValue();
|
||||||
@@ -383,7 +414,9 @@ Pattern.prototype.midi = function (midiport, options = {}) {
|
|||||||
ccs.forEach(({ ccn, ccv }) => sendCC(ccn, ccv, device, midichan, timeOffsetString));
|
ccs.forEach(({ ccn, ccv }) => sendCC(ccn, ccv, device, midichan, timeOffsetString));
|
||||||
} else if (midimap !== 'default') {
|
} else if (midimap !== 'default') {
|
||||||
// Add warning when a non-existent midimap is specified
|
// Add warning when a non-existent midimap is specified
|
||||||
logger(`[midi] midimap "${midimap}" not found! Available maps: ${[...midicontrolMap.keys()].join(', ')}`);
|
throw new Error(
|
||||||
|
`[midimap] midimap "${midimap}" not found! Available maps: ${[...midicontrolMap.keys()].join(', ')}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle note
|
// Handle note
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { getCommonSampleInfoFromBank } from './util.mjs';
|
import { getCommonSampleInfo } from './util.mjs';
|
||||||
import { registerSound, registerWaveTable } from './index.mjs';
|
import { registerSound, registerWaveTable } from './index.mjs';
|
||||||
import { getAudioContext } from './audioContext.mjs';
|
import { getAudioContext } from './audioContext.mjs';
|
||||||
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
import { getADSRValues, getParamADSR, getPitchEnvelope, getVibratoOscillator } from './helpers.mjs';
|
||||||
@@ -23,34 +23,35 @@ function humanFileSize(bytes, si) {
|
|||||||
return bytes.toFixed(1) + ' ' + units[u];
|
return bytes.toFixed(1) + ' ' + units[u];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function getSampleInfo(hapValue, bank) {
|
||||||
|
const { speed = 1.0 } = hapValue;
|
||||||
|
const { transpose, url, index, midi, label } = getCommonSampleInfo(hapValue, bank);
|
||||||
|
let playbackRate = Math.abs(speed) * Math.pow(2, transpose / 12);
|
||||||
|
return { transpose, url, index, midi, label, playbackRate };
|
||||||
|
}
|
||||||
|
|
||||||
export const getSampleBuffer = async (label, sampleUrl, resolveUrl) => {
|
// takes hapValue and returns buffer + playbackRate.
|
||||||
|
export const getSampleBuffer = async (hapValue, bank, resolveUrl) => {
|
||||||
|
let { url: sampleUrl, label, playbackRate } = getSampleInfo(hapValue, bank);
|
||||||
if (resolveUrl) {
|
if (resolveUrl) {
|
||||||
sampleUrl = await resolveUrl(sampleUrl);
|
sampleUrl = await resolveUrl(sampleUrl);
|
||||||
}
|
}
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
const buffer = await loadBuffer(sampleUrl, ac, label);
|
const buffer = await loadBuffer(sampleUrl, ac, label);
|
||||||
return buffer
|
|
||||||
};
|
|
||||||
|
|
||||||
function getBufferPlaybackRate(hapValue, buffer, transpose) {
|
|
||||||
const { speed = 1.0 } = hapValue;
|
|
||||||
let playbackRate = Math.abs(speed) * Math.pow(2, transpose / 12);
|
|
||||||
if (hapValue.unit === 'c') {
|
if (hapValue.unit === 'c') {
|
||||||
playbackRate = playbackRate * buffer.duration;
|
playbackRate = playbackRate * buffer.duration;
|
||||||
}
|
}
|
||||||
return playbackRate;
|
return { buffer, playbackRate };
|
||||||
}
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// creates playback ready AudioBufferSourceNode from hapValue
|
// creates playback ready AudioBufferSourceNode from hapValue
|
||||||
export function getSampleBufferSource(hapValue, buffer,transpose) {
|
export const getSampleBufferSource = async (hapValue, bank, resolveUrl) => {
|
||||||
|
let { buffer, playbackRate } = await getSampleBuffer(hapValue, bank, resolveUrl);
|
||||||
if (hapValue.speed < 0) {
|
if (hapValue.speed < 0) {
|
||||||
// should this be cached?
|
// should this be cached?
|
||||||
buffer = reverseBuffer(buffer);
|
buffer = reverseBuffer(buffer);
|
||||||
}
|
}
|
||||||
const playbackRate = getBufferPlaybackRate(hapValue, buffer, transpose)
|
|
||||||
const ac = getAudioContext();
|
const ac = getAudioContext();
|
||||||
const bufferSource = ac.createBufferSource();
|
const bufferSource = ac.createBufferSource();
|
||||||
bufferSource.buffer = buffer;
|
bufferSource.buffer = buffer;
|
||||||
@@ -263,7 +264,7 @@ export const samples = async (sampleMap, baseUrl = sampleMap._base || '', option
|
|||||||
|
|
||||||
const cutGroups = [];
|
const cutGroups = [];
|
||||||
|
|
||||||
export async function onTriggerSample(t, value, onended, bufferSrc) {
|
export async function onTriggerSample(t, value, onended, bank, resolveUrl) {
|
||||||
let {
|
let {
|
||||||
s,
|
s,
|
||||||
nudge = 0, // TODO: is this in seconds?
|
nudge = 0, // TODO: is this in seconds?
|
||||||
@@ -285,7 +286,7 @@ export async function onTriggerSample(t, value, onended, bufferSrc) {
|
|||||||
// destructure adsr here, because the default should be different for synths and samples
|
// destructure adsr here, because the default should be different for synths and samples
|
||||||
let [attack, decay, sustain, release] = getADSRValues([value.attack, value.decay, value.sustain, value.release]);
|
let [attack, decay, sustain, release] = getADSRValues([value.attack, value.decay, value.sustain, value.release]);
|
||||||
|
|
||||||
const { bufferSource, sliceDuration, offset } = bufferSrc
|
const { bufferSource, sliceDuration, offset } = await getSampleBufferSource(value, bank, resolveUrl);
|
||||||
|
|
||||||
// asny stuff above took too long?
|
// asny stuff above took too long?
|
||||||
if (ac.currentTime > t) {
|
if (ac.currentTime > t) {
|
||||||
@@ -347,21 +348,14 @@ export async function onTriggerSample(t, value, onended, bufferSrc) {
|
|||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getBufferSrcFromBank(hapValue, bank, resolveUrl = undefined) {
|
|
||||||
const { transpose, url, label } = getCommonSampleInfoFromBank(hapValue, bank)
|
|
||||||
let buffer = await getSampleBuffer(label,url, resolveUrl);
|
|
||||||
return getSampleBufferSource(hapValue, buffer, transpose)
|
|
||||||
}
|
|
||||||
|
|
||||||
function registerSample(key, bank, params) {
|
function registerSample(key, bank, params) {
|
||||||
registerSound(key, async (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, await getBufferSrcFromBank(hapValue, bank, undefined)), {
|
registerSound(key, (t, hapValue, onended) => onTriggerSample(t, hapValue, onended, bank), {
|
||||||
type: 'sample',
|
type: 'sample',
|
||||||
samples: bank,
|
samples: bank,
|
||||||
...params,
|
...params,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function registerSampleSource(key, bank, params) {
|
export function registerSampleSource(key, bank, params) {
|
||||||
const isWavetable = key.startsWith('wt_');
|
const isWavetable = key.startsWith('wt_');
|
||||||
if (isWavetable) {
|
if (isWavetable) {
|
||||||
|
|||||||
@@ -80,13 +80,12 @@ export function secondsToCycle(t, cps) {
|
|||||||
// deduces relevant info for sample loading from hap.value and sample definition
|
// deduces relevant info for sample loading from hap.value and sample definition
|
||||||
// it encapsulates the core sampler logic into a pure and synchronous function
|
// it encapsulates the core sampler logic into a pure and synchronous function
|
||||||
// hapValue: Hap.value, bank: sample bank definition for sound "s" (values in strudel.json format)
|
// hapValue: Hap.value, bank: sample bank definition for sound "s" (values in strudel.json format)
|
||||||
export function getCommonSampleInfoFromBank(hapValue, bank) {
|
export function getCommonSampleInfo(hapValue, bank) {
|
||||||
const { s, n = 0 } = hapValue;
|
const { s, n = 0 } = hapValue;
|
||||||
let midi = valueToMidi(hapValue, 36);
|
let midi = valueToMidi(hapValue, 36);
|
||||||
|
let transpose = midi - 36; // C3 is middle C;
|
||||||
let url;
|
let url;
|
||||||
let index = 0;
|
let index = 0;
|
||||||
let {transpose, label} = getCommonSampleInfo(hapValue)
|
|
||||||
|
|
||||||
if (Array.isArray(bank)) {
|
if (Array.isArray(bank)) {
|
||||||
index = getSoundIndex(n, bank.length);
|
index = getSoundIndex(n, bank.length);
|
||||||
url = bank[index];
|
url = bank[index];
|
||||||
@@ -103,20 +102,6 @@ export function getCommonSampleInfoFromBank(hapValue, bank) {
|
|||||||
index = getSoundIndex(n, bank[closest].length);
|
index = getSoundIndex(n, bank[closest].length);
|
||||||
url = bank[closest][index];
|
url = bank[closest][index];
|
||||||
}
|
}
|
||||||
label = `${s}:${index}`;
|
const label = `${s}:${index}`;
|
||||||
return { transpose, url, label };
|
return { transpose, url, index, midi, label };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
export function getCommonSampleInfo(hapValue) {
|
|
||||||
const { s, n = 0 } = hapValue;
|
|
||||||
let midi = valueToMidi(hapValue, 36);
|
|
||||||
let transpose = midi - 36; // C3 is middle C;
|
|
||||||
const label = `${s}:${n}`;
|
|
||||||
return { transpose, label };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { getAudioContext, registerSound } from './index.mjs';
|
import { getAudioContext, registerSound } from './index.mjs';
|
||||||
import { getCommonSampleInfoFromBank } from './util.mjs';
|
import { getCommonSampleInfo } from './util.mjs';
|
||||||
import {
|
import {
|
||||||
applyFM,
|
applyFM,
|
||||||
applyParameterModulators,
|
applyParameterModulators,
|
||||||
@@ -216,7 +216,7 @@ export async function onTriggerSynth(t, value, onended, tables, cps, frameLen) {
|
|||||||
warpmode = Warpmode[warpmode.toUpperCase()] ?? Warpmode.NONE;
|
warpmode = Warpmode[warpmode.toUpperCase()] ?? Warpmode.NONE;
|
||||||
}
|
}
|
||||||
const frequency = getFrequencyFromValue(value);
|
const frequency = getFrequencyFromValue(value);
|
||||||
const { url, label } = getCommonSampleInfoFromBank(value, tables);
|
const { url, label } = getCommonSampleInfo(value, tables);
|
||||||
const payload = await getPayload(url, label, frameLen);
|
const payload = await getPayload(url, label, frameLen);
|
||||||
let holdEnd = t + duration;
|
let holdEnd = t + duration;
|
||||||
if (clip !== undefined) {
|
if (clip !== undefined) {
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
import { getSampleBufferSource, onTriggerSample, registerSampleSource } from '@strudel/webaudio';
|
import { registerSampleSource } from '@strudel/webaudio';
|
||||||
import { isAudioFile } from './files.mjs';
|
import { isAudioFile } from './files.mjs';
|
||||||
import { getSoundIndex, logger } from '@strudel/core';
|
import { logger } from '@strudel/core';
|
||||||
import { registerSound } from '@strudel/webaudio';
|
|
||||||
import { getCommonSampleInfo } from '../../../packages/superdough/util.mjs';
|
|
||||||
|
|
||||||
//utilites for writing and reading to the indexdb
|
//utilites for writing and reading to the indexdb
|
||||||
|
|
||||||
@@ -27,15 +25,6 @@ function clearAllIDB() {
|
|||||||
|
|
||||||
export function clearIDB(dbName) {
|
export function clearIDB(dbName) {
|
||||||
return window.indexedDB.deleteDatabase(dbName);
|
return window.indexedDB.deleteDatabase(dbName);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function registerSampleFromIdb(key, bank, params) {
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// queries the DB, and registers the sounds so they can be played
|
// queries the DB, and registers the sounds so they can be played
|
||||||
@@ -63,76 +52,31 @@ export function registerSamplesFromDB(config = userSamplesDBConfig, onComplete =
|
|||||||
if (!isAudioFile(title)) {
|
if (!isAudioFile(title)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const splitRelativePath = soundFile.id.split('/');
|
const splitRelativePath = soundFile.id.split('/');
|
||||||
let parentDirectory =
|
let parentDirectory =
|
||||||
//fallback to file name before period and seperator if no parent directory
|
//fallback to file name before period and seperator if no parent directory
|
||||||
splitRelativePath[splitRelativePath.length - 2] ?? soundFile.id.split(/\W+/)[0] ?? 'user';
|
splitRelativePath[splitRelativePath.length - 2] ?? soundFile.id.split(/\W+/)[0] ?? 'user';
|
||||||
|
const blob = soundFile.blob;
|
||||||
// const blob = soundFile.blob;
|
|
||||||
|
return blobToDataUrl(blob).then((soundPath) => {
|
||||||
const titlePathMap = sounds.get(parentDirectory) ?? new Map();
|
const titlePathMap = sounds.get(parentDirectory) ?? new Map();
|
||||||
|
|
||||||
titlePathMap.set(title, soundFile.id);
|
titlePathMap.set(title, soundPath);
|
||||||
|
|
||||||
sounds.set(parentDirectory, titlePathMap);
|
sounds.set(parentDirectory, titlePathMap);
|
||||||
|
return;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
// return blobToDataUrl(blob).then((soundPath) => {
|
|
||||||
// const titlePathMap = sounds.get(parentDirectory) ?? new Map();
|
|
||||||
|
|
||||||
// titlePathMap.set(title, soundPath);
|
|
||||||
|
|
||||||
// sounds.set(parentDirectory, titlePathMap);
|
|
||||||
// return;
|
|
||||||
// });
|
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
sounds.forEach((titlePathMap, key) => {
|
sounds.forEach((titlePathMap, key) => {
|
||||||
const bank = Array.from(titlePathMap.keys())
|
const value = Array.from(titlePathMap.keys())
|
||||||
.sort((a, b) => {
|
.sort((a, b) => {
|
||||||
return a.localeCompare(b);
|
return a.localeCompare(b);
|
||||||
})
|
})
|
||||||
.map((title) => titlePathMap.get(title));
|
.map((title) => titlePathMap.get(title));
|
||||||
|
|
||||||
|
registerSampleSource(key, value, { prebake: false });
|
||||||
|
|
||||||
|
|
||||||
registerSound(key, async (t, hapValue, onended) => {
|
|
||||||
const { s, n = 0 } = hapValue;
|
|
||||||
const index = getSoundIndex(n, bank.length);
|
|
||||||
let {transpose, label} = getCommonSampleInfo(hapValue)
|
|
||||||
const storeKey = bank[index];
|
|
||||||
|
|
||||||
openDB(config, (objectStore) => {
|
|
||||||
const getRequest = objectStore.get(storeKey);
|
|
||||||
getRequest.onsuccess = async (event) => {
|
|
||||||
const result = event.target.result;
|
|
||||||
let buffer = result?.blob.arrayBuffer ? await result.blob.arrayBuffer() : null;
|
|
||||||
console.info(buffer)
|
|
||||||
if (buffer) {
|
|
||||||
const bufferSource = getSampleBufferSource(hapValue,buffer,transpose)
|
|
||||||
onTriggerSample(t, hapValue, onended, bufferSource)
|
|
||||||
} else {
|
|
||||||
logger(`Could not load sample for ${storeKey}`, 'error');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
// const buffer = objectStore.getKey(key)
|
|
||||||
// const bufferSource = getSampleBufferSource(hapValue,buffer,transpose)
|
|
||||||
|
|
||||||
// onTriggerSample(t, hapValue, onended, await getBufferSrcFromBank(hapValue, bank, undefined))
|
|
||||||
|
|
||||||
}, {
|
|
||||||
type: 'sample',
|
|
||||||
samples: bank,
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
// registerSampleSource(key, value, { prebake: false });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
logger('imported sounds registered!', 'success');
|
logger('imported sounds registered!', 'success');
|
||||||
|
|||||||
Reference in New Issue
Block a user