mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-23 11:38:37 +00:00
preview outputs should be stereo
This commit is contained in:
parent
e419733716
commit
3fd5fdf1ee
@ -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;
|
||||||
|
|||||||
@ -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 = () => {
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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);
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user