preview outputs should be stereo

This commit is contained in:
Jade Rowland 2023-11-23 12:43:51 -05:00
parent e419733716
commit 3fd5fdf1ee
4 changed files with 40 additions and 29 deletions

View File

@ -381,18 +381,18 @@ const generic_params = [
*/ */
['coarse'], ['coarse'],
// /** /**
// * Allows you to set the output channels on the interface * Allows you to set the output channels on the interface
// * *
// * @name channels * @name channels
// * @synonyms ch * @synonyms ch
// * *
// * @param {!Float32Array} channels Array<int> * @param {number | Pattern} channels pattern the output channels
// * @example * @example
// * note("e a d b g").channels([2, 3]).room(1) * note("e a d b g").channels("2:3").room(1)
// * *
// */ */
// ['channels', 'ch'], ['channels', 'ch'],
['phaserrate', 'phasr'], // superdirt only ['phaserrate', 'phasr'], // superdirt only
@ -1390,13 +1390,13 @@ controls.ds = register('ds', (ds, pat) => {
return pat.set({ decay, sustain }); return pat.set({ decay, sustain });
}); });
controls.ch = register(['channels', 'ch'], (channels, pat) => { // controls.ch = register(['channels', 'ch'], (channels, pat) => {
channels = !Array.isArray(channels) ? [channels] : channels; // channels = !Array.isArray(channels) ? [channels] : channels;
// channels = channels.map(reify).map((channelPat) => { // // channels = channels.map(reify).map((channelPat) => {
// // How do I return the current value of the channel pattern here? // // // How do I return the current value of the channel pattern here?
// }); // // });
return pat.set({ channels }); // return pat.set({ channels });
}); // });
export default controls; export default controls;

View File

@ -23,6 +23,13 @@ export function registerSound(key, onTrigger, data = {}) {
export function getSound(s) { export function getSound(s) {
return soundMap.get()[s]; return soundMap.get()[s];
} }
// sounds with only one active channel will get upmixed to two, stereo sounds should remain unaffected
// There might be a better way to do this
export const upMixToStereo = (ctx, node) => {
const stereo = new StereoPannerNode(ctx);
node.connect(stereo);
return stereo;
};
export const resetLoadedSounds = () => soundMap.set({}); export const resetLoadedSounds = () => soundMap.set({});
@ -117,14 +124,16 @@ const maxfeedback = 0.98;
const connectToOutputs = (input, channels = [0, 1]) => { const connectToOutputs = (input, channels = [0, 1]) => {
const outputs = getDestinations(channels); const outputs = getDestinations(channels);
const ctx = getAudioContext(); const ctx = getAudioContext();
const center = new StereoPannerNode(ctx);
input.connect(center); //This upmix can be avoided if correct channel counts are set throughout the app,
//could theoretically support surround sound audio files if that work was done
const stereo = upMixToStereo(ctx, input);
const splitter = new ChannelSplitterNode(ctx, { const splitter = new ChannelSplitterNode(ctx, {
numberOfOutputs: input.channelCount, numberOfOutputs: stereo.channelCount,
}); });
center.connect(splitter); stereo.connect(splitter);
outputs.forEach((output, i) => { outputs.forEach((output, i) => {
splitter.connect(output, i % input.channelCount, 0); splitter.connect(output, i % stereo.channelCount, 0);
}); });
}; };
@ -334,6 +343,8 @@ export const superdough = async (value, deadline, hapDuration) => {
compressorRelease, compressorRelease,
} = value; } = value;
channels = Array.isArray(channels) ? channels : [channels];
gain *= velocity; // legacy fix for velocity gain *= velocity; // legacy fix for velocity
let toDisconnect = []; // audio nodes that will be disconnected when the source has ended let toDisconnect = []; // audio nodes that will be disconnected when the source has ended
const onended = () => { const onended = () => {

View File

@ -71,8 +71,7 @@ export function waveformN(partials, type) {
const real = new Float32Array(partials + 1); const real = new Float32Array(partials + 1);
const imag = new Float32Array(partials + 1); const imag = new Float32Array(partials + 1);
const ac = getAudioContext(); const ac = getAudioContext();
const osc = ac.createOscillator(); const osc = new OscillatorNode(ac, { channelCount: 1, channelCountMode: 'explicit' });
const terms = { const terms = {
sawtooth: (n) => [0, -1 / n], sawtooth: (n) => [0, -1 / n],
square: (n) => [0, n % 2 === 0 ? 0 : 1 / n], square: (n) => [0, n % 2 === 0 ? 0 : 1 / n],
@ -125,7 +124,8 @@ export function getOscillator(
let o; let o;
// If no partials are given, use stock waveforms // If no partials are given, use stock waveforms
if (!partials || s === 'sine') { if (!partials || s === 'sine') {
o = getAudioContext().createOscillator(); o = new OscillatorNode(ac, { channelCount: 1, channelCountMode: 'explicit' });
console.log(o);
o.type = s || 'triangle'; o.type = s || 'triangle';
} }
// generate custom waveform if partials are given // generate custom waveform if partials are given

View File

@ -7,7 +7,7 @@ import React, { useMemo, useCallback, useLayoutEffect, useRef, useState } from '
import { Reference } from './Reference'; import { Reference } from './Reference';
import { themes } from './themes.mjs'; import { themes } from './themes.mjs';
import { useSettings, settingsMap, setActiveFooter, defaultSettings } from '../settings.mjs'; import { useSettings, settingsMap, setActiveFooter, defaultSettings } from '../settings.mjs';
import { getAudioContext, soundMap } from '@strudel.cycles/webaudio'; import { getAudioContext, soundMap, upMixToStereo } from '@strudel.cycles/webaudio';
import { useStore } from '@nanostores/react'; import { useStore } from '@nanostores/react';
import { FilesTab } from './FilesTab'; import { FilesTab } from './FilesTab';
@ -271,7 +271,7 @@ function SoundsTab() {
const onended = () => trigRef.current?.node?.disconnect(); const onended = () => trigRef.current?.node?.disconnect();
trigRef.current = Promise.resolve(onTrigger(time, params, onended)); trigRef.current = Promise.resolve(onTrigger(time, params, onended));
trigRef.current.then((ref) => { trigRef.current.then((ref) => {
ref?.node.connect(ctx.destination); upMixToStereo(ctx, ref?.node).connect(ctx.destination);
}); });
}} }}
> >