Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: sound select indexes out of bounds #871

Merged
merged 3 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 14 additions & 0 deletions packages/core/util.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ Copyright (C) 2022 Strudel contributors - see <https://github.com/tidalcycles/st
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*/

import { logger } from './logger.mjs';

// returns true if the given string is a note
export const isNoteWithOctave = (name) => /^[a-gA-G][#bs]*[0-9]$/.test(name);
export const isNote = (name) => /^[a-gA-G][#bsf]*[0-9]?$/.test(name);
Expand Down Expand Up @@ -84,6 +86,18 @@ export const midi2note = (n) => {
// modulo that works with negative numbers e.g. _mod(-1, 3) = 2. Works on numbers (rather than patterns of numbers, as @mod@ from pattern.mjs does)
export const _mod = (n, m) => ((n % m) + m) % m;

export function nanFallback(value, fallback) {
if (isNaN(Number(value))) {
logger(`"${value}" is not a number, falling back to ${fallback}`, 'warning');
return fallback;
}
return value;
}
// round to nearest int, negative numbers will output a subtracted index
export const getSoundIndex = (n, numSounds) => {
return _mod(Math.round(nanFallback(n, 0)), numSounds);
};

export const getPlayableNoteValue = (hap) => {
let { value, context } = hap;
let note = value;
Expand Down
6 changes: 3 additions & 3 deletions packages/soundfonts/fontloader.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { noteToMidi, freqToMidi } from '@strudel.cycles/core';
import { noteToMidi, freqToMidi, getSoundIndex } from '@strudel.cycles/core';
import { getAudioContext, registerSound, getEnvelope } from '@strudel.cycles/webaudio';
import gm from './gm.mjs';

Expand Down Expand Up @@ -130,9 +130,9 @@ export function registerSoundfonts() {
registerSound(
name,
async (time, value, onended) => {
const { n = 0 } = value;
const n = getSoundIndex(value.n, fonts.length);
const { attack = 0.001, decay = 0.001, sustain = 1, release = 0.001 } = value;
const font = fonts[n % fonts.length];
const font = fonts[n];
const ctx = getAudioContext();
const bufferSource = await getFontBufferSource(font, value, ctx);
bufferSource.start(time);
Expand Down
13 changes: 8 additions & 5 deletions packages/superdough/sampler.mjs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { noteToMidi, valueToMidi, nanFallback } from './util.mjs';
import { noteToMidi, valueToMidi, getSoundIndex } from './util.mjs';
import { getAudioContext, registerSound } from './index.mjs';
import { getEnvelope } from './helpers.mjs';
import { logger } from './logger.mjs';
Expand Down Expand Up @@ -31,10 +31,12 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resol
transpose = midi - 36; // C3 is middle C

const ac = getAudioContext();

let sampleUrl;
let index = 0;
if (Array.isArray(bank)) {
n = nanFallback(n, 0);
sampleUrl = bank[n % bank.length];
index = getSoundIndex(n, bank.length);
sampleUrl = bank[index];
} else {
const midiDiff = (noteA) => noteToMidi(noteA) - midi;
// object format will expect keys as notes
Expand All @@ -45,12 +47,13 @@ export const getSampleBufferSource = async (s, n, note, speed, freq, bank, resol
null,
);
transpose = -midiDiff(closest); // semitones to repitch
sampleUrl = bank[closest][n % bank[closest].length];
index = getSoundIndex(n, bank[closest].length);
sampleUrl = bank[closest][index];
}
if (resolveUrl) {
sampleUrl = await resolveUrl(sampleUrl);
}
let buffer = await loadBuffer(sampleUrl, ac, s, n);
let buffer = await loadBuffer(sampleUrl, ac, s, index);
if (speed < 0) {
// should this be cached?
buffer = reverseBuffer(buffer);
Expand Down
7 changes: 7 additions & 0 deletions packages/superdough/util.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,10 @@ export function nanFallback(value, fallback) {
}
return value;
}
// modulo that works with negative numbers e.g. _mod(-1, 3) = 2. Works on numbers (rather than patterns of numbers, as @mod@ from pattern.mjs does)
export const _mod = (n, m) => ((n % m) + m) % m;

// round to nearest int, negative numbers will output a subtracted index
export const getSoundIndex = (n, numSounds) => {
return _mod(Math.round(nanFallback(n, 0)), numSounds);
};