simple generic recording, hook up audio
This commit is contained in:
parent
50126f7cd4
commit
4cb5742afb
6 changed files with 200 additions and 18 deletions
|
@ -145,7 +145,6 @@ const Audio = function(tp, record) {
|
||||||
const bb = fft_Dom.getBoundingClientRect();
|
const bb = fft_Dom.getBoundingClientRect();
|
||||||
const x = e.clientX - bb.x;
|
const x = e.clientX - bb.x;
|
||||||
freq_down = mapValue(e.clientX, bb.x, bb.x + bb.width, 0, 256 * 8 / 2, true);
|
freq_down = mapValue(e.clientX, bb.x, bb.x + bb.width, 0, 256 * 8 / 2, true);
|
||||||
console.log('up',JSON.parse(JSON.stringify(e)), e);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
//removeAudioOptions();
|
//removeAudioOptions();
|
||||||
|
@ -182,8 +181,9 @@ const Audio = function(tp, record) {
|
||||||
console.log("Audio::addAudioButton",
|
console.log("Audio::addAudioButton",
|
||||||
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
||||||
} else if (container.querySelector('.audioButton') !== null) {
|
} else if (container.querySelector('.audioButton') !== null) {
|
||||||
console.log("Audio::addAudioButton",
|
// this is super verbose, let's not log by default
|
||||||
`already added an audio button for ${propTitle}`);
|
//console.log("Audio::addAudioButton",
|
||||||
|
//`already added an audio button for ${propTitle}`);
|
||||||
} else {
|
} else {
|
||||||
const button = document.createElement('div');
|
const button = document.createElement('div');
|
||||||
button.classList.add('audioButton');
|
button.classList.add('audioButton');
|
||||||
|
@ -478,6 +478,7 @@ const Audio = function(tp, record) {
|
||||||
let a = mapValue(max_v, 0, 255, m.min_out, m.max_out, true);
|
let a = mapValue(max_v, 0, 255, m.min_out, m.max_out, true);
|
||||||
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
||||||
propsToSet.push({
|
propsToSet.push({
|
||||||
|
title: propTitle,
|
||||||
prop: layer.theatreObject.props[propTitle],
|
prop: layer.theatreObject.props[propTitle],
|
||||||
value: m.value,
|
value: m.value,
|
||||||
});
|
});
|
||||||
|
@ -487,6 +488,7 @@ const Audio = function(tp, record) {
|
||||||
let a = mapValue(max_i, 0, bufferLengthAlt-1, m.min_out, m.max_out, true);
|
let a = mapValue(max_i, 0, bufferLengthAlt-1, m.min_out, m.max_out, true);
|
||||||
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
m.value = m.value * m.smoothing + (1.0 - m.smoothing) * a;
|
||||||
propsToSet.push({
|
propsToSet.push({
|
||||||
|
title: propTitle,
|
||||||
prop: layer.theatreObject.props[propTitle],
|
prop: layer.theatreObject.props[propTitle],
|
||||||
value: m.value,
|
value: m.value,
|
||||||
});
|
});
|
||||||
|
@ -501,6 +503,7 @@ const Audio = function(tp, record) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (propsToSet.length > 0 && frameCount % 2 === 0) {
|
if (propsToSet.length > 0 && frameCount % 2 === 0) {
|
||||||
|
if (!record.isRecording()) {
|
||||||
tp.studio.transaction(({
|
tp.studio.transaction(({
|
||||||
set
|
set
|
||||||
}) => {
|
}) => {
|
||||||
|
@ -508,14 +511,25 @@ const Audio = function(tp, record) {
|
||||||
set(p.prop, p.value, true);
|
set(p.prop, p.value, true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
propsToSet.forEach((p) => {
|
||||||
|
// TODO: this does not have to be queried
|
||||||
|
// but we could store it in a map/set/dictionary/array/object
|
||||||
|
const inputElement = tp
|
||||||
|
.getPanelPropContainer(p.title)
|
||||||
|
.querySelector('input.recording');
|
||||||
|
|
||||||
|
if (inputElement !== null) {
|
||||||
|
inputElement.value = p.value;
|
||||||
|
inputElement.dispatchEvent(new Event('change'));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const panel = tp.getPanel();
|
const panel = tp.getPanel();
|
||||||
const fft_images = panel.querySelectorAll('.audio_fft');
|
const fft_images = panel.querySelectorAll('.audio_fft');
|
||||||
if (fft_images !== null) {
|
if (fft_images !== null) {
|
||||||
const src = canvas.toDataURL();
|
const src = canvas.toDataURL();
|
||||||
if (window.printDebug === true) {
|
|
||||||
console.log({canvas, src, fft_images, panel}, "DEBUG AUDIO");
|
|
||||||
}
|
|
||||||
fft_images.forEach((e) => {
|
fft_images.forEach((e) => {
|
||||||
e.src = src;
|
e.src = src;
|
||||||
});
|
});
|
||||||
|
|
|
@ -85,6 +85,9 @@ const config = {
|
||||||
ignoreProps: ['transformOrigin', 'fontFamily', 'text', 'mirror_x', 'mirror_y', 'mirror_xy', 'fontVariationAxes', 'color'],
|
ignoreProps: ['transformOrigin', 'fontFamily', 'text', 'mirror_x', 'mirror_y', 'mirror_xy', 'fontVariationAxes', 'color'],
|
||||||
defaultSmoothing: 0.7,
|
defaultSmoothing: 0.7,
|
||||||
},
|
},
|
||||||
|
record: {
|
||||||
|
ignoreProps: ['fontVariationAxes','letterDelays','color'],
|
||||||
|
},
|
||||||
midi: {
|
midi: {
|
||||||
touchTimeThreshold_s: 0.5,
|
touchTimeThreshold_s: 0.5,
|
||||||
smoothingMix: 0.1,
|
smoothingMix: 0.1,
|
||||||
|
|
|
@ -55,6 +55,7 @@ const Layer = function(tp, layerID, fontsAndAxes, autoInit = true) {
|
||||||
text: config.layer.defaultTexts[Math.floor(Math.random()*config.layer.defaultTexts.length)],
|
text: config.layer.defaultTexts[Math.floor(Math.random()*config.layer.defaultTexts.length)],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let updateValuesViaTheatre = true;
|
||||||
let lastValues = {};
|
let lastValues = {};
|
||||||
let fontsHashMap = {};
|
let fontsHashMap = {};
|
||||||
let sequenceEventBuffer = [];
|
let sequenceEventBuffer = [];
|
||||||
|
@ -204,6 +205,8 @@ const Layer = function(tp, layerID, fontsAndAxes, autoInit = true) {
|
||||||
const onValuesChange = (values) => {
|
const onValuesChange = (values) => {
|
||||||
if (values.dummy === true)
|
if (values.dummy === true)
|
||||||
return;
|
return;
|
||||||
|
if (!updateValuesViaTheatre)
|
||||||
|
return;
|
||||||
window.isRenderDirty = true;
|
window.isRenderDirty = true;
|
||||||
if (Object.keys(values).length > 1) {
|
if (Object.keys(values).length > 1) {
|
||||||
values.text = values.text.trim();
|
values.text = values.text.trim();
|
||||||
|
@ -792,11 +795,18 @@ const Layer = function(tp, layerID, fontsAndAxes, autoInit = true) {
|
||||||
panel.addEventListener("mouseover", showBoundingBoxDivIfSelected);
|
panel.addEventListener("mouseover", showBoundingBoxDivIfSelected);
|
||||||
panel.addEventListener("mouseleave", hideBoundingBoxDiv);
|
panel.addEventListener("mouseleave", hideBoundingBoxDiv);
|
||||||
|
|
||||||
|
// should we have an audio object, let's inject the buttons, etc
|
||||||
if (typeof audio === 'object' && audio.hasOwnProperty('injectPanel')) {
|
if (typeof audio === 'object' && audio.hasOwnProperty('injectPanel')) {
|
||||||
audio.injectPanel(this);
|
audio.injectPanel(this);
|
||||||
} else {
|
} else {
|
||||||
console.log('Layer::findInjectPanel', `cannot inject audio panel for ${this.id()} for some reason.`);
|
console.log('Layer::findInjectPanel', `cannot inject audio panel for ${this.id()} for some reason.`);
|
||||||
}
|
}
|
||||||
|
// should we have a record object, let's inject the buttons, etc
|
||||||
|
if (typeof record === 'object' && record.hasOwnProperty('injectPanel')) {
|
||||||
|
record.injectPanel(this);
|
||||||
|
} else {
|
||||||
|
console.log('Layer::findInjectPanel', `cannot inject record panel for ${this.id()} for some reason.`);
|
||||||
|
}
|
||||||
|
|
||||||
injectedPanel = true;
|
injectedPanel = true;
|
||||||
const detail = {titles: Object.keys(panelPropTitles), containers: Object.keys(panelPropContainers)};
|
const detail = {titles: Object.keys(panelPropTitles), containers: Object.keys(panelPropContainers)};
|
||||||
|
@ -1036,6 +1046,9 @@ const Layer = function(tp, layerID, fontsAndAxes, autoInit = true) {
|
||||||
return cppProps;
|
return cppProps;
|
||||||
};
|
};
|
||||||
this.onValuesChange = onValuesChange;
|
this.onValuesChange = onValuesChange;
|
||||||
|
this.updateValuesViaTheatre = (doIt) => {
|
||||||
|
updateValuesViaTheatre = doIt;
|
||||||
|
};
|
||||||
this.prepareForDepartureFromThisBeautifulExperience = () => {
|
this.prepareForDepartureFromThisBeautifulExperience = () => {
|
||||||
this.hide();
|
this.hide();
|
||||||
hideBoundingBoxDiv();
|
hideBoundingBoxDiv();
|
||||||
|
|
|
@ -72,8 +72,8 @@ const interactor = new Interactor();
|
||||||
const moduleFS = new ModuleFS();
|
const moduleFS = new ModuleFS();
|
||||||
window.moduleFS = moduleFS;
|
window.moduleFS = moduleFS;
|
||||||
const record = new Record(tp);
|
const record = new Record(tp);
|
||||||
window.debug_record = record;
|
window.record = record;
|
||||||
const audio = new Audio(tp, record); // possibly nicer if we pass tp instead of attaching to window
|
const audio = new Audio(tp, record);
|
||||||
window.audio = audio;
|
window.audio = audio;
|
||||||
|
|
||||||
window.panelFinderTimeout = false;
|
window.panelFinderTimeout = false;
|
||||||
|
@ -410,6 +410,10 @@ window.getLayers = () => {
|
||||||
return layers;
|
return layers;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
window.getLayer = (layerID) => {
|
||||||
|
return layers.find((layer) => layer.id() === layerID);
|
||||||
|
};
|
||||||
|
|
||||||
window.moveLayerUp = (layerID) => {
|
window.moveLayerUp = (layerID) => {
|
||||||
layerOrder.moveUp(layerID);
|
layerOrder.moveUp(layerID);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
const Record = function(tp) {
|
const Record = function(tp) {
|
||||||
|
|
||||||
const hot = {};
|
const hot = {};
|
||||||
|
let isRecording = false;
|
||||||
|
|
||||||
const addRecordButton = (layer, propTitle, isActive) => {
|
const addRecordButton = (layer, propTitle) => {
|
||||||
const panel = tp.getPanel();
|
const panel = tp.getPanel();
|
||||||
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
||||||
if (panelPropTitle !== null) {
|
if (panelPropTitle !== null) {
|
||||||
|
@ -11,8 +12,9 @@ const Record = function(tp) {
|
||||||
console.log("Record::addRecordButton",
|
console.log("Record::addRecordButton",
|
||||||
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
||||||
} else if (container.querySelector('.recordButton') !== null) {
|
} else if (container.querySelector('.recordButton') !== null) {
|
||||||
console.log("Record::addRecordButton",
|
// this is super verbose, let's not log by default
|
||||||
`already added an record button for ${propTitle}`);
|
//console.log("Record::addRecordButton",
|
||||||
|
//`already added an record button for ${propTitle}`);
|
||||||
} else {
|
} else {
|
||||||
const button = document.createElement('div');
|
const button = document.createElement('div');
|
||||||
button.classList.add('recordButton');
|
button.classList.add('recordButton');
|
||||||
|
@ -24,9 +26,13 @@ const Record = function(tp) {
|
||||||
hot[layer.id()] = {};
|
hot[layer.id()] = {};
|
||||||
}
|
}
|
||||||
if (!hot[layer.id()].hasOwnProperty(propTitle)) {
|
if (!hot[layer.id()].hasOwnProperty(propTitle)) {
|
||||||
hot[layer.id()][propTitle] = {};
|
hot[layer.id()][propTitle] = {
|
||||||
|
recording: [],
|
||||||
|
};
|
||||||
button.classList.add('active');
|
button.classList.add('active');
|
||||||
|
startRecording();
|
||||||
} else {
|
} else {
|
||||||
|
stopRecording();
|
||||||
delete hot[layer.id()][propTitle];
|
delete hot[layer.id()][propTitle];
|
||||||
if (Object.keys(hot[layer.id()]).length === 0) {
|
if (Object.keys(hot[layer.id()]).length === 0) {
|
||||||
delete hot[layer.id()];
|
delete hot[layer.id()];
|
||||||
|
@ -41,8 +47,142 @@ const Record = function(tp) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const cloneInput = (layer, propTitle) => {
|
||||||
|
const panel = tp.getPanel();
|
||||||
|
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
||||||
|
if (panelPropTitle !== null) {
|
||||||
|
const container = tp.getPanelPropContainer(panelPropTitle);
|
||||||
|
if (container === null) {
|
||||||
|
console.log("Record::cloneInput",
|
||||||
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
||||||
|
} else if (container.querySelector('input.recording') !== null) {
|
||||||
|
console.log("Record::cloneInput",
|
||||||
|
`already cloned input for ${propTitle}`);
|
||||||
|
} else {
|
||||||
|
const input = container.querySelector('input');
|
||||||
|
if (input === null) {
|
||||||
|
console.log("Record::cloneInput",
|
||||||
|
`uuh.. seems there is no input to clone for ${propTitle}`);
|
||||||
|
} else {
|
||||||
|
const input_clone = input.cloneNode();
|
||||||
|
input_clone.classList.value = '';
|
||||||
|
input_clone.classList.add('recording');
|
||||||
|
input.parentNode.after(input_clone);
|
||||||
|
input.setAttribute('data-previousDisplay', input.style.display);
|
||||||
|
input.style.display = 'none';
|
||||||
|
return input_clone;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const uncloneInput = (layer, propTitle) => {
|
||||||
|
const panel = tp.getPanel();
|
||||||
|
const panelPropTitle = tp.getPanelPropTitle(propTitle);
|
||||||
|
if (panelPropTitle !== null) {
|
||||||
|
const container = tp.getPanelPropContainer(panelPropTitle);
|
||||||
|
if (container === null) {
|
||||||
|
console.log("Record::uncloneInput",
|
||||||
|
`impossible! cannot find panelPropContainer for ${propTitle}`);
|
||||||
|
} else if (container.querySelector('input.recording') === null) {
|
||||||
|
console.log("Record::uncloneInput",
|
||||||
|
`already uncloned input for ${propTitle}`);
|
||||||
|
} else {
|
||||||
|
const input = container.querySelector('input:not(.recording)');
|
||||||
|
const input_clone = container.querySelector('input.recording');
|
||||||
|
if (input === null ) {
|
||||||
|
console.log("Record::uncloneInput",
|
||||||
|
`uuh.. seems there is no input for ${propTitle}`);
|
||||||
|
} else if (input_clone === null ) {
|
||||||
|
console.log("Record::uncloneInput",
|
||||||
|
`uuh.. seems there is no input_clone for ${propTitle}`);
|
||||||
|
} else {
|
||||||
|
input_clone.remove();
|
||||||
|
input.removeAttribute('data-previousDisplay');
|
||||||
|
const previousInputDisplay = input.getAttribute('data-previousDisplay');
|
||||||
|
input.style.display = previousInputDisplay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const injectPanel = (layer) => {
|
||||||
|
const props = Object.keys(layer.theatreObject.value);
|
||||||
|
props.forEach((propTitle) => {
|
||||||
|
if (config.record.ignoreProps.indexOf(propTitle) < 0) {
|
||||||
|
addRecordButton(layer, propTitle);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const startRecording = () => {
|
||||||
|
tp.sheet.sequence.pause();
|
||||||
|
const layerKeys = Object.keys(hot);
|
||||||
|
layerKeys.forEach((layerID) => {
|
||||||
|
const layer = getLayer(layerID);
|
||||||
|
layer.updateValuesViaTheatre(false);
|
||||||
|
const propTitles = Object.keys(hot[layerID]);
|
||||||
|
propTitles.forEach((propTitle) => {
|
||||||
|
// NOTE: layerID is not actually used atm
|
||||||
|
// and should be the layer anyways
|
||||||
|
const input_clone = cloneInput(layerID, propTitle);
|
||||||
|
if (input_clone !== null) {
|
||||||
|
input_clone.addEventListener('change', (e) => {
|
||||||
|
hot[layerID][propTitle].recording.push({
|
||||||
|
position: tp.sheet.sequence.position,
|
||||||
|
value: parseFloat(input_clone.value),
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.log('whoops input_clone is null');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
tp.sheet.sequence.position = 0;
|
||||||
|
tp.sheet.sequence.play();
|
||||||
|
});
|
||||||
|
isRecording = true;
|
||||||
|
};
|
||||||
|
const stopRecording = () => {
|
||||||
|
console.log('stoprecording');
|
||||||
|
const layerKeys = Object.keys(hot);
|
||||||
|
console.log({layerKeys});
|
||||||
|
layerKeys.forEach((layerID) => {
|
||||||
|
console.log(layerID);
|
||||||
|
const layer = getLayer(layerID);
|
||||||
|
layer.updateValuesViaTheatre(true);
|
||||||
|
const propTitles = Object.keys(hot[layerID]);
|
||||||
|
const keyframes = [];
|
||||||
|
propTitles.forEach((propTitle) => {
|
||||||
|
console.log(propTitle);
|
||||||
|
// NOTE: layerID is not actually used atm
|
||||||
|
// and should be the layer anyways
|
||||||
|
uncloneInput(layerID, propTitle);
|
||||||
|
console.log('should have uncloned input for ' + propTitle);
|
||||||
|
keyframes.push({
|
||||||
|
path: [propTitle],
|
||||||
|
keyframes: hot[layerID][propTitle].recording,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log('adding the keyframes now because we wnat it to happen right now please');
|
||||||
|
tp.addKeyframes(layer, keyframes);
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
isRecording = false;
|
||||||
|
};
|
||||||
|
|
||||||
// public
|
// public
|
||||||
this.addRecordButton = addRecordButton;
|
this.addRecordButton = addRecordButton;
|
||||||
|
this.getHot = () => {
|
||||||
|
return hot;
|
||||||
|
};
|
||||||
|
this.isRecording = () => {
|
||||||
|
return isRecording;
|
||||||
|
};
|
||||||
|
this.injectPanel = injectPanel;
|
||||||
|
this.startRecording = startRecording;
|
||||||
|
this.stopRecording = stopRecording;
|
||||||
};
|
};
|
||||||
|
|
||||||
export {
|
export {
|
||||||
|
|
|
@ -571,10 +571,18 @@ const TheatrePlay = function(autoInit = false) {
|
||||||
}
|
}
|
||||||
.audioButton{
|
.audioButton{
|
||||||
width: 20px;
|
width: 20px;
|
||||||
|
margin: 2px;
|
||||||
}
|
}
|
||||||
.audioButton.active{
|
.audioButton.active{
|
||||||
background: green;
|
background: green;
|
||||||
}
|
}
|
||||||
|
.recordButton{
|
||||||
|
width: 20px;
|
||||||
|
margin: 2px;
|
||||||
|
}
|
||||||
|
.recordButton.active{
|
||||||
|
background: green;
|
||||||
|
}
|
||||||
`;
|
`;
|
||||||
this.shadowRoot.appendChild(style);
|
this.shadowRoot.appendChild(style);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue