mirror of
https://github.com/eliasstepanik/strudel-docker.git
synced 2026-01-28 05:58:28 +00:00
channel splitting and channels parameter
This commit is contained in:
parent
f0b458cd17
commit
e419733716
@ -4,7 +4,7 @@ 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/>.
|
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 { Pattern, register, sequence } from './pattern.mjs';
|
import { Pattern, register, reify, sequence } from './pattern.mjs';
|
||||||
import { zipWith } from './util.mjs';
|
import { zipWith } from './util.mjs';
|
||||||
|
|
||||||
const controls = {};
|
const controls = {};
|
||||||
@ -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 {!Float32Array} channels Array<int>
|
||||||
* @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,4 +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) => {
|
||||||
|
channels = !Array.isArray(channels) ? [channels] : channels;
|
||||||
|
|
||||||
|
// channels = channels.map(reify).map((channelPat) => {
|
||||||
|
// // How do I return the current value of the channel pattern here?
|
||||||
|
// });
|
||||||
|
return pat.set({ channels });
|
||||||
|
});
|
||||||
|
|
||||||
export default controls;
|
export default controls;
|
||||||
|
|||||||
@ -31,38 +31,33 @@ let audioContext;
|
|||||||
export const getAudioContext = () => {
|
export const getAudioContext = () => {
|
||||||
if (!audioContext) {
|
if (!audioContext) {
|
||||||
audioContext = new AudioContext();
|
audioContext = new AudioContext();
|
||||||
var maxChannelCount = audioContext.destination.maxChannelCount;
|
const maxChannelCount = audioContext.destination.maxChannelCount;
|
||||||
audioContext.destination.channelCount = maxChannelCount;
|
audioContext.destination.channelCount = maxChannelCount;
|
||||||
}
|
}
|
||||||
//console.log(audioContext.destination.maxChannelCount);
|
|
||||||
|
|
||||||
return audioContext;
|
return audioContext;
|
||||||
};
|
};
|
||||||
// outputs: Map<int, audiGainNode>
|
// outputs: Map<int, GainNode>
|
||||||
const outputs = new Map();
|
const outputs = new Map();
|
||||||
let channelMerger;
|
let channelMerger;
|
||||||
// channels: Array<int>
|
// channels: Array<int>
|
||||||
const getDestinations = (channels) => {
|
const getDestinations = (channels) => {
|
||||||
const ctx = getAudioContext();
|
const ctx = getAudioContext();
|
||||||
if (channelMerger == null) {
|
if (channelMerger == null) {
|
||||||
channelMerger = ctx.createChannelMerger(ctx.destination.channelCount);
|
channelMerger = new ChannelMergerNode(ctx, { numberOfInputs: ctx.destination.channelCount });
|
||||||
channelMerger.connect(ctx.destination);
|
channelMerger.connect(ctx.destination);
|
||||||
}
|
}
|
||||||
channels.forEach((ch) => {
|
channels.forEach((ch) => {
|
||||||
if (!outputs.has(ch)) {
|
if (!outputs.has(ch)) {
|
||||||
const gain = ctx.createGain();
|
const gain = new GainNode(ctx, {
|
||||||
gain.channelInterpretation = 'discrete';
|
channelInterpretation: 'discrete',
|
||||||
|
channelCount: 1,
|
||||||
|
channelCountMode: 'explicit',
|
||||||
|
});
|
||||||
gain.connect(channelMerger, 0, ch);
|
gain.connect(channelMerger, 0, ch);
|
||||||
outputs.set(ch, gain);
|
outputs.set(ch, gain);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// if (!destination) {
|
|
||||||
// destination = ctx.createGain();
|
|
||||||
// channelMerger = ctx.createChannelMerger(ctx.destination.channelCount);
|
|
||||||
// channelMerger.connect(ctx.destination);
|
|
||||||
// destination.connect(channelMerger, 0, 4);
|
|
||||||
// destination.connect(channelMerger, 0, 5);
|
|
||||||
// }
|
|
||||||
return channels.map((ch) => outputs.get(ch));
|
return channels.map((ch) => outputs.get(ch));
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -121,10 +116,15 @@ const maxfeedback = 0.98;
|
|||||||
//input: audioNode, channels: Array<int>
|
//input: audioNode, channels: Array<int>
|
||||||
const connectToOutputs = (input, channels = [0, 1]) => {
|
const connectToOutputs = (input, channels = [0, 1]) => {
|
||||||
const outputs = getDestinations(channels);
|
const outputs = getDestinations(channels);
|
||||||
console.log(input);
|
const ctx = getAudioContext();
|
||||||
|
const center = new StereoPannerNode(ctx);
|
||||||
|
input.connect(center);
|
||||||
|
const splitter = new ChannelSplitterNode(ctx, {
|
||||||
|
numberOfOutputs: input.channelCount,
|
||||||
|
});
|
||||||
|
center.connect(splitter);
|
||||||
outputs.forEach((output, i) => {
|
outputs.forEach((output, i) => {
|
||||||
input.connect(output, 0);
|
splitter.connect(output, i % input.channelCount, 0);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -333,6 +333,7 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||||||
compressorAttack,
|
compressorAttack,
|
||||||
compressorRelease,
|
compressorRelease,
|
||||||
} = value;
|
} = value;
|
||||||
|
|
||||||
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 = () => {
|
||||||
@ -466,11 +467,9 @@ export const superdough = async (value, deadline, hapDuration) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// last gain
|
// last gain
|
||||||
const post = gainNode(postgain);
|
const post = new GainNode(ac, { gain: postgain });
|
||||||
chain.push(post);
|
chain.push(post);
|
||||||
console.log(channels);
|
connectToOutputs(post, channels);
|
||||||
// this should be an array but is getting interpreted as an int for some reason...
|
|
||||||
connectToOutputs(post, [channels]);
|
|
||||||
|
|
||||||
// delay
|
// delay
|
||||||
let delaySend;
|
let delaySend;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user