Spaces:
Running
on
CPU Upgrade
Running
on
CPU Upgrade
class Editor { | |
constructor () { | |
this.isCreated = false | |
this.hasChanged = false | |
this.autoInferTimer = null | |
this.adjustedLetters = new Set() | |
this.LEFT_RIGHT_SEQ_PADDING = 20 | |
this.EDITOR_HEIGHT = 150 | |
this.LETTERS_Y_OFFSET = 40 | |
this.SLIDER_GRABBER_H = 15 | |
this.MIN_LETTER_LENGTH = 20 | |
this.MAX_LETTER_LENGTH = 100 | |
this.SPACE_BETWEEN_LETTERS = 5 | |
this.default_pitchSliderRange = 4 | |
this.pitchSliderRange = 4 | |
this.duration_visual_size_multiplier = 1 | |
this.default_MIN_ENERGY = 3.45 | |
this.MIN_ENERGY = 3.45 | |
this.default_MAX_ENERGY = 4.35 | |
this.MAX_ENERGY = 4.35 | |
this.ENERGY_GRABBER_RADIUS = 8 | |
this.EMOTION_STYLE_GRABBER_RADIUS = 8 | |
this.MIN_EMOTIONS = 0 | |
this.MAX_EMOTIONS = 1.06 | |
this.MIN_STYLES = 0 | |
this.MAX_STYLES = 1.06 | |
this.clear() // And thus init | |
this.registeredStyleKeys = [] | |
this.historyState = [] // TODO, add support for undo/redo across all editor functions | |
} | |
clear () { | |
this.sliderBoxes = [] | |
this.grabbers = [] // Pitch (original single grabber) | |
this.energyGrabbers = [] | |
this.emAngryGrabbers = [] | |
this.emHappyGrabbers = [] | |
this.emSadGrabbers = [] | |
this.emSurpriseGrabbers = [] | |
this.styleGrabbers = {} | |
this.styleValuesNew = {} | |
this.styleValuesReset = {} | |
this.multiLetterStyleDelta = {} | |
this.multiLetterStartStyleVals = {} | |
this.letters = [] | |
this.pitchNew = [] | |
this.dursNew = [] | |
this.energyNew = [] | |
this.emAngryNew = [] | |
this.emHappyNew = [] | |
this.emSadNew = [] | |
this.emSurpriseNew = [] | |
this.pacing = 1 | |
this.ampFlatCounter = 0 | |
this.inputSequence = undefined | |
this.currentVoice = undefined | |
this.letterFocus = [] | |
this.lastSelected = 0 | |
this.letterClasses = [] | |
this.resetDurs = [] | |
this.resetPitch = [] | |
this.resetEnergy = [] | |
this.resetEmAngry = [] | |
this.resetEmHappy = [] | |
this.resetEmSad = [] | |
this.resetEmSurprise = [] | |
this.multiLetterPitchDelta = undefined | |
this.multiLetterStartPitchVals = [] | |
this.multiLetterStartDursVals = [] | |
this.multiLetterEnergyDelta = undefined | |
this.multiLetterStartEnergyVals = [] | |
this.multiLetterEmotionDelta = undefined | |
this.multiLetterStartEmotionVals = [] | |
this.multiLetterLengthDelta = undefined | |
this.multiLetterStartLengthVals = [] | |
} | |
loadStylesData (editorStyles) { | |
this.registeredStyleKeys = [] | |
Object.keys(window.appState.currentModelEmbeddings).forEach(styleKey => { | |
if (styleKey=="default") return | |
this.registeredStyleKeys.push(styleKey) | |
this.styleGrabbers[styleKey] = [] | |
this.styleValuesReset[styleKey] = this.resetPitch.map(v=>0) | |
this.styleValuesNew[styleKey] = (editorStyles&&editorStyles[styleKey]&&editorStyles[styleKey].sliders) ? editorStyles[styleKey].sliders : this.resetPitch.map(v=>0) | |
this.multiLetterStyleDelta[styleKey] = undefined | |
this.multiLetterStartStyleVals[styleKey] = [] | |
}) | |
} | |
init () { | |
// Clear away old instance | |
if (this.isCreated) { | |
editorContainer.innerHTML = "" | |
delete this.canvas | |
delete this.context | |
} | |
let canvasWidth = 0 | |
if (this.sliderBoxes.length) { | |
canvasWidth = this.sliderBoxes.at(-1).getX() + this.SPACE_BETWEEN_LETTERS * 2 + 100 | |
} else { | |
canvasWidth = this.LEFT_RIGHT_SEQ_PADDING*2 // Padding | |
this.dursNew.forEach((dur,di) => { | |
if (di) { | |
canvasWidth += this.SPACE_BETWEEN_LETTERS | |
} | |
let value = dur | |
value = value * this.pacing | |
value = Math.max(0.1, value) | |
value = Math.min(value, 20) | |
const percentAcross = value/20 | |
const width = percentAcross * (this.MAX_LETTER_LENGTH-this.MIN_LETTER_LENGTH) + this.MIN_LETTER_LENGTH | |
canvasWidth += width | |
}) | |
} | |
this.canvas = document.createElement("canvas") | |
this.context = this.canvas.getContext("2d") | |
this.context.textAlign = "center" | |
this.canvas.width = canvasWidth | |
this.canvas.height = 200 | |
editorContainer.appendChild(this.canvas) | |
// Mouse cursor | |
this.canvas.addEventListener("mousemove", event => { | |
const mouseX = parseInt(event.offsetX) | |
const mouseY = parseInt(event.offsetY) | |
this.canvas.style.cursor = "default" | |
// Check energy grabber hover | |
const isOnEGrabber = seq_edit_view_select.value.includes("energy") && this.energyGrabbers.find((eGrabber, egi) => { | |
if (!this.enabled_disabled_items[egi]) return | |
const grabberX = eGrabber.getXLeft()+eGrabber.sliderBox.width/2-this.ENERGY_GRABBER_RADIUS | |
return (mouseX>grabberX && mouseX<grabberX+this.ENERGY_GRABBER_RADIUS*2+4) && (mouseY>eGrabber.topLeftY-this.ENERGY_GRABBER_RADIUS-2 && mouseY<eGrabber.topLeftY+this.ENERGY_GRABBER_RADIUS+2) | |
}) | |
if (isOnEGrabber && isOnEGrabber!=undefined) { | |
this.canvas.style.cursor = "row-resize" | |
return | |
} | |
// One grabber type | |
if (seq_edit_view_select.value !== "pitch_energy") { | |
this.sliderBoxes.forEach((sbox, sboxi) => { | |
if (!this.enabled_disabled_items[sboxi]) return; | |
// is outside slider box => return | |
if (!( | |
mouseX>sbox.getXLeft() | |
&& mouseX<sbox.getXLeft() + sbox.width | |
)) { | |
return; | |
} | |
this.canvas.style.cursor = "row-resize" | |
}) | |
} | |
// Check emotion grabber hover | |
const isHoveringOverEmotionGrabber = emotionGrabbers => { | |
return emotionGrabbers.find((eGrabber, egi) => { | |
if (!this.enabled_disabled_items[egi]) return | |
const grabberX = eGrabber.getXLeft()+eGrabber.sliderBox.width/2-this.EMOTION_STYLE_GRABBER_RADIUS | |
return (mouseX>grabberX && mouseX<grabberX+this.EMOTION_STYLE_GRABBER_RADIUS*2+4) && (mouseY>eGrabber.topLeftY-this.EMOTION_STYLE_GRABBER_RADIUS-2 && mouseY<eGrabber.topLeftY+this.EMOTION_STYLE_GRABBER_RADIUS+2) | |
}) | |
} | |
if (window.currentModel.modelType=="xVAPitch") { | |
const isOnEmGrabber = seq_edit_view_select.value.startsWith("em") && (isHoveringOverEmotionGrabber(this.emAngryGrabbers) || isHoveringOverEmotionGrabber(this.emHappyGrabbers) || isHoveringOverEmotionGrabber(this.emSadGrabbers) || isHoveringOverEmotionGrabber(this.emSurpriseGrabbers)) | |
if (isOnEmGrabber && isOnEmGrabber!=undefined) { | |
this.canvas.style.cursor = "row-resize" | |
return | |
} | |
} | |
// Check pitch grabber hover | |
const isOnGrabber = seq_edit_view_select.value.includes("pitch") && this.grabbers.find((grabber, gi) => { | |
if (!this.enabled_disabled_items[gi]) return | |
const grabberX = grabber.getXLeft() | |
return (mouseX>grabberX && mouseX<grabberX+grabber.width) && (mouseY>grabber.topLeftY && mouseY<grabber.topLeftY+grabber.height) | |
}) | |
if (isOnGrabber && isOnGrabber!=undefined) { | |
this.canvas.style.cursor = "n-resize" | |
return | |
} | |
// Check styles grabbers | |
if (this.registeredStyleKeys && this.registeredStyleKeys.length) { | |
let isOnStyleGrabber | |
this.registeredStyleKeys.forEach(styleKey => { | |
if (isOnStyleGrabber) return // Skip unnecessary work if already found | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
isOnStyleGrabber = this.styleGrabbers[styleKey].find((grabber, gi) => { | |
if (!this.enabled_disabled_items[gi]) return | |
const grabberX = grabber.getXLeft() | |
return (mouseX>grabberX && mouseX<grabberX+grabber.width) && (mouseY>grabber.topLeftY && mouseY<grabber.topLeftY+grabber.height) | |
}) | |
if (isOnStyleGrabber) { | |
this.canvas.style.cursor = "row-resize" | |
return | |
} | |
} | |
}) | |
} | |
// Check letter hover | |
const isOnLetter = this.letterClasses.find((letter, l) => { | |
if (!this.enabled_disabled_items[l]) return | |
return (mouseY<this.LETTERS_Y_OFFSET) && (mouseX>this.sliderBoxes[l].getXLeft() && mouseX<this.sliderBoxes[l].getXLeft()+this.sliderBoxes[l].width) | |
}) | |
if (isOnLetter!=undefined) { | |
this.canvas.style.cursor = "pointer" | |
return | |
} | |
// Check box length dragger | |
const isBetweenBoxes = this.sliderBoxes.find((box, bi) => { | |
if (!this.enabled_disabled_items[bi]) return | |
const boxX = box.getXLeft() | |
return (mouseY>box.topY && mouseY<box.topY+box.height) && (mouseX>(boxX+box.width-10) && mouseX<(boxX+box.width+10)+5) | |
}) | |
if (isBetweenBoxes!=undefined) { | |
this.canvas.style.cursor = "w-resize" | |
return | |
} | |
}) | |
let elemDragged = undefined | |
let mouseDownStart = {x: undefined, y: undefined} | |
this.canvas.addEventListener("mousedown", event => { | |
const mouseX = parseInt(event.offsetX) | |
const mouseY = parseInt(event.offsetY) | |
mouseDownStart.x = mouseX | |
mouseDownStart.y = mouseY | |
// Check up-down pitch dragging box first | |
const isOnGrabber = seq_edit_view_select.value.includes("pitch") && this.grabbers.find((grabber, gi) => { | |
if (!this.enabled_disabled_items[gi]) return | |
const grabberX = grabber.getXLeft() | |
return (mouseX>grabberX && mouseX<grabberX+grabber.width) && (mouseY>grabber.topLeftY && mouseY<grabber.topLeftY+grabber.height) | |
}) | |
if (isOnGrabber) { | |
const slider = isOnGrabber | |
if (this.letterFocus.length <= 1 || (!this.letterFocus.includes(slider.index))) { | |
this.setLetterFocus(this.grabbers.indexOf(slider), event.ctrlKey, event.shiftKey, event.altKey) | |
} | |
this.multiLetterPitchDelta = slider.topLeftY | |
this.multiLetterStartPitchVals = this.grabbers.map(slider => slider.topLeftY) | |
elemDragged = isOnGrabber | |
return | |
} | |
// Check sideways dragging | |
const isBetweenBoxes = this.sliderBoxes.find((box, bi) => { | |
if (!this.enabled_disabled_items[bi]) return | |
const boxX = box.getXLeft() | |
return (mouseY>box.topY && mouseY<box.topY+box.height) && (mouseX>(boxX+box.width-10) && mouseX<(boxX+box.width+10)+5) | |
}) | |
if (isBetweenBoxes) { | |
this.multiLetterStartDursVals = this.sliderBoxes.map(box => box.width) | |
isBetweenBoxes.dragStart.width = isBetweenBoxes.width | |
elemDragged = isBetweenBoxes | |
return | |
} | |
// Check up-down emotion dragging | |
const findGrabber = emotionGrabbers => { | |
return emotionGrabbers.find((eGrabber, egi) => { | |
if (!this.enabled_disabled_items[egi]) return | |
const boxX = eGrabber.sliderBox.getXLeft() | |
return ( | |
(mouseX > boxX) | |
&& (mouseX < (boxX + eGrabber.sliderBox.width)) | |
) | |
}) | |
} | |
const handleEmGrabber = (emGrabber, grabbersList) => { | |
if (this.letterFocus.length <= 1 || (!this.letterFocus.includes(emGrabber.index))) { | |
this.setLetterFocus(grabbersList.indexOf(emGrabber), event.ctrlKey, event.shiftKey, event.altKey) | |
} | |
this.multiLetterEmotionDelta = emGrabber.topLeftY | |
this.multiLetterStartEmotionVals = grabbersList.map(emGrabber => emGrabber.topLeftY) | |
return emGrabber | |
} | |
const handleStyleGrabber = (styleGrabber, grabbersList, styleKey) => { | |
if (this.letterFocus.length <= 1 || (!this.letterFocus.includes(styleGrabber.index))) { | |
this.setLetterFocus(grabbersList.indexOf(styleGrabber), event.ctrlKey, event.shiftKey, event.altKey) | |
} | |
this.multiLetterStyleDelta[styleKey] = styleGrabber.topLeftY | |
this.multiLetterStartStyleVals[styleKey] = grabbersList.map(styleGrabber => styleGrabber.topLeftY) | |
return styleGrabber | |
} | |
// Check up-down energy dragging | |
const isOnEGrabber = seq_edit_view_select.value.includes("energy") && this.energyGrabbers.find((eGrabber, egi) => { | |
if (!this.enabled_disabled_items[egi]) return | |
const grabberX = eGrabber.getXLeft()+eGrabber.sliderBox.width/2-this.ENERGY_GRABBER_RADIUS | |
return (mouseX>grabberX && mouseX<grabberX+this.ENERGY_GRABBER_RADIUS*2+4) && (mouseY>eGrabber.topLeftY-this.ENERGY_GRABBER_RADIUS-2 && mouseY<eGrabber.topLeftY+this.ENERGY_GRABBER_RADIUS+2) | |
}) | |
if (isOnEGrabber) { | |
const eGrabber = isOnEGrabber | |
if (this.letterFocus.length <= 1 || (!this.letterFocus.includes(eGrabber.index))) { | |
this.setLetterFocus(this.energyGrabbers.indexOf(eGrabber), event.ctrlKey, event.shiftKey, event.altKey) | |
} | |
this.multiLetterEnergyDelta = eGrabber.topLeftY | |
this.multiLetterStartEnergyVals = this.energyGrabbers.map(eGrabber => eGrabber.topLeftY) | |
elemDragged = isOnEGrabber | |
return | |
} | |
// Check clicking on the top letters | |
const isOnLetter = this.letterClasses.find((letter, l) => { | |
if (!this.enabled_disabled_items[l]) return | |
return (mouseY<this.LETTERS_Y_OFFSET) && (mouseX>this.sliderBoxes[l].getXLeft() && mouseX<this.sliderBoxes[l].getXLeft()+this.sliderBoxes[l].width) | |
}) | |
if (isOnLetter) { | |
this.setLetterFocus(this.letterClasses.indexOf(isOnLetter), event.ctrlKey, event.shiftKey, event.altKey) | |
return; | |
} | |
// Not on letter | |
// Drag grabber when only single type of grabber | |
if (seq_edit_view_select.value === "pitch_energy") | |
{ | |
return; | |
} | |
// Fetch any grabber within letter column | |
const isOnGrabberCol = seq_edit_view_select.value=="pitch" && findGrabber(this.grabbers) | |
if (isOnGrabberCol) { | |
const slider = isOnGrabberCol | |
this.multiLetterPitchDelta = slider.topLeftY | |
this.multiLetterStartPitchVals = this.grabbers.map(slider => slider.topLeftY) | |
elemDragged = isOnGrabberCol | |
return | |
} | |
const isOnEGrabberCol = seq_edit_view_select.value=="energy" && findGrabber(this.energyGrabbers) | |
if (isOnEGrabberCol) { | |
this.multiLetterEnergyDelta = isOnEGrabberCol.topLeftY | |
this.multiLetterStartEnergyVals = this.energyGrabbers.map(isOnEGrabberCol => isOnEGrabberCol.topLeftY) | |
elemDragged = isOnEGrabberCol | |
return | |
} | |
if (window.currentModel.modelType !== "xVAPitch") { | |
return | |
} | |
// v3 model | |
if (seq_edit_view_select.value.startsWith("style_") && this.registeredStyleKeys.length) { | |
this.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.includes(styleKey)) { | |
const isOnStyleGrabber = findGrabber(this.styleGrabbers[styleKey]) | |
if (isOnStyleGrabber) { | |
elemDragged = handleStyleGrabber(isOnStyleGrabber, this.styleGrabbers[styleKey], styleKey) | |
return | |
} | |
} | |
}) | |
} | |
const isOnEmAngryGrabber = seq_edit_view_select.value=="emAngry" && findGrabber(this.emAngryGrabbers) | |
if (isOnEmAngryGrabber) { | |
elemDragged = handleEmGrabber(isOnEmAngryGrabber, this.emAngryGrabbers) | |
return | |
} | |
const isOnEmHappyGrabber = seq_edit_view_select.value=="emHappy" && findGrabber(this.emHappyGrabbers) | |
if (isOnEmHappyGrabber) { | |
elemDragged = handleEmGrabber(isOnEmHappyGrabber, this.emHappyGrabbers) | |
return | |
} | |
const isOnEmSadGrabber = seq_edit_view_select.value=="emSad" && findGrabber(this.emSadGrabbers) | |
if (isOnEmSadGrabber) { | |
elemDragged = handleEmGrabber(isOnEmSadGrabber, this.emSadGrabbers) | |
return | |
} | |
const isOnEmSurpriseGrabber = seq_edit_view_select.value=="emSurprise" && findGrabber(this.emSurpriseGrabbers) | |
if (isOnEmSurpriseGrabber) { | |
elemDragged = handleEmGrabber(isOnEmSurpriseGrabber, this.emSurpriseGrabbers) | |
return | |
} | |
}) | |
this.canvas.addEventListener("mouseup", event => { | |
mouseDownStart = {x: undefined, y: undefined} | |
if (autoplay_ckbx.checked && this.hasChanged) { | |
generateVoiceButton.click() | |
} | |
this.init() | |
}) | |
this.canvas.addEventListener("mousemove", event => { | |
if (mouseDownStart.x && mouseDownStart.y) { | |
if (elemDragged && (parseInt(event.offsetX)-mouseDownStart.x || parseInt(event.offsetY)-mouseDownStart.y)) { | |
this.hasChanged = true | |
this.letterFocus.forEach(index => this.adjustedLetters.add(index)) | |
} | |
if (elemDragged) { | |
if (elemDragged.type=="slider") { // Pitch sliders, specifically | |
elemDragged.setValueFromCoords(parseInt(event.offsetY)-elemDragged.height/2) | |
// If there's a multi-selection, update all of their values, otherwise update the numerical input | |
if (this.letterFocus.length>1) { | |
this.letterFocus.forEach(li => { | |
if (li!=elemDragged.index) { | |
this.grabbers[li].setValueFromCoords(this.multiLetterStartPitchVals[li]+(elemDragged.topLeftY-this.multiLetterPitchDelta)) | |
} | |
}) | |
} else { | |
letterPitchNumb.value = parseInt(this.pitchNew[elemDragged.index]*100)/100 | |
} | |
} else if (elemDragged.type=="box") { // Durations being dragged sideways | |
// If there's a multi-selection, update all of their values, otherwise update the numerical input | |
if (this.letterFocus.length>1) { | |
this.letterFocus.forEach(li => { | |
let newWidth = this.multiLetterStartDursVals[li] + parseInt(elemDragged.width - elemDragged.dragStart.width) | |
newWidth = Math.max(20, newWidth) | |
newWidth = Math.min(newWidth, this.MAX_LETTER_LENGTH) | |
this.sliderBoxes[li].width = newWidth | |
this.sliderBoxes[li].percentAcross = (this.sliderBoxes[li].width-20) / (this.MAX_LETTER_LENGTH-20) | |
this.dursNew[this.sliderBoxes[li].index] = Math.max(0.1, this.sliderBoxes[li].percentAcross*20) | |
this.sliderBoxes[li].grabber.width = this.sliderBoxes[li].width-2 | |
this.sliderBoxes[li].letter.centerX = this.sliderBoxes[li].leftX + this.sliderBoxes[li].width/2 | |
}) | |
} else { | |
letterLengthNumb.value = parseInt(this.dursNew[elemDragged.index]*100)/100 | |
} | |
let newWidth = elemDragged.dragStart.width + parseInt(event.offsetX)-mouseDownStart.x | |
newWidth = Math.max(20, newWidth) | |
newWidth = Math.min(newWidth, this.MAX_LETTER_LENGTH) | |
elemDragged.width = newWidth | |
elemDragged.percentAcross = (elemDragged.width-20) / (this.MAX_LETTER_LENGTH-20) | |
this.dursNew[elemDragged.index] = Math.max(0.1, elemDragged.percentAcross*20) | |
elemDragged.grabber.width = elemDragged.width-2 | |
elemDragged.letter.centerX = elemDragged.leftX + elemDragged.width/2 | |
} else if (elemDragged.type=="energy_slider") { // Energy sliders | |
elemDragged.setValueFromCoords(parseInt(event.offsetY)-elemDragged.height/2) | |
// If there's a multi-selection, update all of their values, otherwise update the numerical input | |
if (this.letterFocus.length>1) { | |
this.letterFocus.forEach(li => { | |
if (li!=elemDragged.index) { | |
this.energyGrabbers[li].setValueFromCoords(this.multiLetterStartEnergyVals[li]+(elemDragged.topLeftY-this.multiLetterEnergyDelta)) | |
} | |
}) | |
} else { | |
letterEnergyNumb.value = parseInt(this.energyNew[elemDragged.index]*100)/100 | |
} | |
} else if (elemDragged.type=="emotion_slider") { // Emotion sliders | |
elemDragged.setValueFromCoords(parseInt(event.offsetY)-elemDragged.height/2) | |
// If there's a multi-selection, update all of their values, otherwise update the numerical input | |
if (this.letterFocus.length>1) { | |
this.letterFocus.forEach(li => { | |
if (li!=elemDragged.index) { | |
if (seq_edit_view_select.value=="emAngry") { | |
this.emAngryGrabbers[li].setValueFromCoords(this.multiLetterStartEmotionVals[li]+(elemDragged.topLeftY-this.multiLetterEmotionDelta)) | |
} else if (seq_edit_view_select.value=="emHappy") { | |
this.emHappyGrabbers[li].setValueFromCoords(this.multiLetterStartEmotionVals[li]+(elemDragged.topLeftY-this.multiLetterEmotionDelta)) | |
} else if (seq_edit_view_select.value=="emSad") { | |
this.emSadGrabbers[li].setValueFromCoords(this.multiLetterStartEmotionVals[li]+(elemDragged.topLeftY-this.multiLetterEmotionDelta)) | |
} else if (seq_edit_view_select.value=="emSurprise") { | |
this.emSurpriseGrabbers[li].setValueFromCoords(this.multiLetterStartEmotionVals[li]+(elemDragged.topLeftY-this.multiLetterEmotionDelta)) | |
} | |
} | |
}) | |
} else { | |
if (seq_edit_view_select.value=="emAngry") { | |
letterEmotionNumb.value = parseFloat(this.emAngryNew[elemDragged.index]*100)/100 | |
} else if (seq_edit_view_select.value=="emHappy") { | |
letterEmotionNumb.value = parseFloat(this.emHappyNew[elemDragged.index]*100)/100 | |
} else if (seq_edit_view_select.value=="emSad") { | |
letterEmotionNumb.value = parseFloat(this.emSadNew[elemDragged.index]*100)/100 | |
} else if (seq_edit_view_select.value=="emSurprise") { | |
letterEmotionNumb.value = parseFloat(this.emSurpriseNew[elemDragged.index]*100)/100 | |
} | |
} | |
} else if (elemDragged.type=="style_slider") { // Style sliders | |
elemDragged.setValueFromCoords(parseInt(event.offsetY)-elemDragged.height/2) | |
if (this.registeredStyleKeys.length) { | |
this.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
// If there's a multi-selection, update all of their values, otherwise update the numerical input | |
if (this.letterFocus.length>1) { | |
this.letterFocus.forEach(li => { | |
if (li!=elemDragged.index) { | |
this.styleGrabbers[styleKey][li].setValueFromCoords(this.multiLetterStartStyleVals[styleKey][li]+(elemDragged.topLeftY-this.multiLetterStyleDelta[styleKey])) | |
} | |
}) | |
} else { | |
letterStyleNumb.value = parseInt(this.styleValuesNew[styleKey][elemDragged.index]*100)/100 | |
} | |
} | |
}) | |
} | |
} | |
} | |
} | |
}) | |
if (!this.isCreated) { | |
this.render() | |
} | |
this.isCreated = true | |
} | |
render () { | |
if (this.context!=undefined) { | |
this.context.clearRect(0, 0, this.canvas.width, this.canvas.height) | |
this.letterClasses.forEach((letter, li) => { | |
if (this.letters[li]=="<PAD>") return | |
letter.context = this.context | |
letter.render() | |
}) | |
this.sliderBoxes.forEach((sliderBox, sbi) => { | |
if (this.letters[sbi]=="<PAD>") return | |
sliderBox.context = this.context | |
sliderBox.render() | |
}) | |
if (seq_edit_view_select.value=="pitch_energy" || seq_edit_view_select.value=="pitch") { | |
this.grabbers.forEach((grabber,gi) => { | |
if (this.letters[gi]=="<PAD>") return | |
grabber.context = this.context | |
grabber.render() | |
}) | |
} | |
if (seq_edit_view_select.value=="pitch_energy" || seq_edit_view_select.value=="energy") { | |
this.energyGrabbers.forEach((eGrabber, egi) => { | |
if (this.letters[egi]=="<PAD>") return | |
eGrabber.context = this.context | |
eGrabber.render() | |
}) | |
} | |
if (window.currentModel.modelType=="xVAPitch") { | |
if (seq_edit_view_select.value=="emAngry") { | |
this.emAngryGrabbers.forEach((eGrabber, egi) => { | |
if (this.letters[egi]=="<PAD>") return | |
eGrabber.context = this.context | |
eGrabber.render() | |
}) | |
} | |
if (seq_edit_view_select.value=="emHappy") { | |
this.emHappyGrabbers.forEach((eGrabber, egi) => { | |
if (this.letters[egi]=="<PAD>") return | |
eGrabber.context = this.context | |
eGrabber.render() | |
}) | |
} | |
if (seq_edit_view_select.value=="emSad") { | |
this.emSadGrabbers.forEach((eGrabber, egi) => { | |
if (this.letters[egi]=="<PAD>") return | |
eGrabber.context = this.context | |
eGrabber.render() | |
}) | |
} | |
if (seq_edit_view_select.value=="emSurprise") { | |
this.emSurpriseGrabbers.forEach((eGrabber, egi) => { | |
if (this.letters[egi]=="<PAD>") return | |
eGrabber.context = this.context | |
eGrabber.render() | |
}) | |
} | |
if (this.registeredStyleKeys && this.registeredStyleKeys.length) { | |
this.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
this.styleGrabbers[styleKey].forEach((styleGrabber, sgi) => { | |
if (this.letters[sgi]=="<PAD>") return | |
styleGrabber.context = this.context | |
styleGrabber.render() | |
}) | |
} | |
}) | |
} | |
} | |
} | |
requestAnimationFrame(() => {this.render()}) | |
} | |
update (modelType=undefined, sliderRange=undefined) { | |
self.modelType = modelType | |
// Make model-specific adjustments | |
if (modelType=="xVAPitch") { | |
this.default_pitchSliderRange = 6 | |
this.pitchSliderRange = sliderRange || 6 | |
this.duration_visual_size_multiplier = 1 | |
this.MAX_LETTER_LENGTH = 200 | |
this.default_MIN_ENERGY = 0 | |
this.MIN_ENERGY = 0 | |
this.default_MAX_ENERGY = 1.07 | |
this.MAX_ENERGY = 1.07 | |
this.styleGrabbers = {} | |
this.registeredStyleKeys.forEach(styleKey => { | |
this.styleGrabbers[styleKey] = [] | |
}) | |
} else { | |
this.default_pitchSliderRange = 4 | |
this.pitchSliderRange = sliderRange || 4 | |
this.duration_visual_size_multiplier = 1 | |
this.MAX_LETTER_LENGTH = 100 | |
} | |
this.letterClasses = [] | |
this.sliderBoxes = [] | |
this.grabbers = [] | |
this.energyGrabbers = [] | |
this.emAngryGrabbers = [] | |
this.emHappyGrabbers = [] | |
this.emSadGrabbers = [] | |
this.emSurpriseGrabbers = [] | |
this.enabled_disabled_items = [] | |
let xCounter = 0 | |
let lastBox = undefined | |
let letter_counter = 0 | |
this.letters.forEach((letter, li) => { | |
if (letter=="<PAD>") { | |
this.enabled_disabled_items.push(false) | |
letter_counter += 1 | |
} else { | |
this.enabled_disabled_items.push(true) | |
} | |
letter_counter += 1 | |
const dur = this.dursNew[li] | |
const width = Math.max(25, dur*10) | |
// Slider box | |
const sliderBox = new SliderBox(this.context, li, lastBox, this.LETTERS_Y_OFFSET, this.EDITOR_HEIGHT, this.MIN_LETTER_LENGTH, this.MAX_LETTER_LENGTH, letter_counter%2==0) | |
sliderBox.render() | |
if (lastBox) { | |
lastBox.rightBox = sliderBox | |
} | |
lastBox = sliderBox | |
this.sliderBoxes.push(sliderBox) | |
// Letter text | |
const letterClass = new Letter(this.context, li, letter, sliderBox, 20, 20+xCounter, width) | |
if (this.letterFocus.includes(li)) { | |
letterClass.colour = "red" | |
} | |
letterClass.render() | |
this.letterClasses.push(letterClass) | |
// Slider grabber thing | |
const pitchPercent = 1-(this.pitchNew[li]+this.pitchSliderRange)/(this.pitchSliderRange*2) | |
const grabber = new SliderGrabber(this.context, li, sliderBox, (this.LETTERS_Y_OFFSET+1)+(this.SLIDER_GRABBER_H/2)+((this.EDITOR_HEIGHT-2)-this.SLIDER_GRABBER_H)*pitchPercent-this.SLIDER_GRABBER_H/2, width-2, this.SLIDER_GRABBER_H, this.pitchSliderRange) | |
grabber.render() | |
this.grabbers.push(grabber) | |
if (this.energyNew && this.energyNew.length) { | |
// Energy round grabber | |
let energyPercent | |
if (modelType=="xVAPitch") { | |
energyPercent = ( (this.energyNew[li]-this.MIN_ENERGY) / (this.MAX_ENERGY-this.MIN_ENERGY) ) | |
} else { | |
energyPercent = 1 - ( (this.energyNew[li]-this.MIN_ENERGY) / (this.MAX_ENERGY-this.MIN_ENERGY) ) | |
} | |
energyPercent = Math.max(0, energyPercent) | |
energyPercent = Math.min(energyPercent, 1) | |
let topLeftY = (1 - energyPercent) * (this.EDITOR_HEIGHT-2-this.ENERGY_GRABBER_RADIUS) + (this.LETTERS_Y_OFFSET) | |
const energyGrabber = new EnergyEmotionGrabber(this.context, li, sliderBox, topLeftY, width-2, this.ENERGY_GRABBER_RADIUS, undefined, modelType, this.ENERGY_GRABBER_RADIUS, "energy") | |
energyGrabber.render() | |
this.energyGrabbers.push(energyGrabber) | |
} | |
if (modelType=="xVAPitch") { | |
if (this.emAngryNew && this.emAngryNew.length) { | |
let emotionPercent = ( (this.emAngryNew[li]-this.MIN_EMOTIONS) / (this.MAX_EMOTIONS-this.MIN_EMOTIONS) ) | |
emotionPercent = Math.max(0, emotionPercent) | |
emotionPercent = Math.min(emotionPercent, 1) | |
let topLeftY = (1 - emotionPercent) * (this.EDITOR_HEIGHT-2-this.EMOTION_STYLE_GRABBER_RADIUS) + (this.LETTERS_Y_OFFSET) | |
const emAngryGrabber = new EnergyEmotionGrabber(this.context, li, sliderBox, topLeftY, width-2, this.EMOTION_STYLE_GRABBER_RADIUS, undefined, modelType, this.EMOTION_STYLE_GRABBER_RADIUS, "emotion") | |
emAngryGrabber.render() | |
this.emAngryGrabbers.push(emAngryGrabber) | |
} | |
if (this.emHappyNew && this.emHappyNew.length) { | |
let emotionPercent = ( (this.emHappyNew[li]-this.MIN_EMOTIONS) / (this.MAX_EMOTIONS-this.MIN_EMOTIONS) ) | |
emotionPercent = Math.max(0, emotionPercent) | |
emotionPercent = Math.min(emotionPercent, 1) | |
let topLeftY = (1 - emotionPercent) * (this.EDITOR_HEIGHT-2-this.EMOTION_STYLE_GRABBER_RADIUS) + (this.LETTERS_Y_OFFSET) | |
const emHappyGrabber = new EnergyEmotionGrabber(this.context, li, sliderBox, topLeftY, width-2, this.EMOTION_STYLE_GRABBER_RADIUS, undefined, modelType, this.EMOTION_STYLE_GRABBER_RADIUS, "emotion") | |
emHappyGrabber.render() | |
this.emHappyGrabbers.push(emHappyGrabber) | |
} | |
if (this.emSadNew && this.emSadNew.length) { | |
let emotionPercent = ( (this.emSadNew[li]-this.MIN_EMOTIONS) / (this.MAX_EMOTIONS-this.MIN_EMOTIONS) ) | |
emotionPercent = Math.max(0, emotionPercent) | |
emotionPercent = Math.min(emotionPercent, 1) | |
let topLeftY = (1 - emotionPercent) * (this.EDITOR_HEIGHT-2-this.EMOTION_STYLE_GRABBER_RADIUS) + (this.LETTERS_Y_OFFSET) | |
const emSadGrabber = new EnergyEmotionGrabber(this.context, li, sliderBox, topLeftY, width-2, this.EMOTION_STYLE_GRABBER_RADIUS, undefined, modelType, this.EMOTION_STYLE_GRABBER_RADIUS, "emotion") | |
emSadGrabber.render() | |
this.emSadGrabbers.push(emSadGrabber) | |
} | |
if (this.emSurpriseNew && this.emSurpriseNew.length) { | |
let emotionPercent = ( (this.emSurpriseNew[li]-this.MIN_EMOTIONS) / (this.MAX_EMOTIONS-this.MIN_EMOTIONS) ) | |
emotionPercent = Math.max(0, emotionPercent) | |
emotionPercent = Math.min(emotionPercent, 1) | |
let topLeftY = (1 - emotionPercent) * (this.EDITOR_HEIGHT-2-this.EMOTION_STYLE_GRABBER_RADIUS) + (this.LETTERS_Y_OFFSET) | |
const emSurpriseGrabber = new EnergyEmotionGrabber(this.context, li, sliderBox, topLeftY, width-2, this.EMOTION_STYLE_GRABBER_RADIUS, undefined, modelType, this.EMOTION_STYLE_GRABBER_RADIUS, "emotion") | |
emSurpriseGrabber.render() | |
this.emSurpriseGrabbers.push(emSurpriseGrabber) | |
} | |
// Initialize grabbers dynamically for every style | |
this.registeredStyleKeys.forEach(styleKey => { | |
let stylePercent = ( (this.styleValuesNew[styleKey][li]-this.MIN_STYLES) / (this.MAX_STYLES-this.MIN_STYLES) ) | |
stylePercent = Math.max(0, stylePercent) | |
stylePercent = Math.min(stylePercent, 1) | |
let topLeftY = (1 - stylePercent) * (this.EDITOR_HEIGHT-2-this.EMOTION_STYLE_GRABBER_RADIUS) + (this.LETTERS_Y_OFFSET) | |
const styleGrabber = new EnergyEmotionGrabber(this.context, li, sliderBox, topLeftY, width-2, this.EMOTION_STYLE_GRABBER_RADIUS, undefined, modelType, this.EMOTION_STYLE_GRABBER_RADIUS, "style") | |
styleGrabber.render() | |
this.styleGrabbers[styleKey].push(styleGrabber) | |
}) | |
} | |
sliderBox.letter = letterClass | |
sliderBox.grabber = grabber | |
sliderBox.setValueFromValue(dur) | |
xCounter += width + 5 | |
}) | |
this.canvas.width = this.sliderBoxes.at(-1).getX() + this.SPACE_BETWEEN_LETTERS * 2 + 100 | |
} | |
setLetterFocus (l, ctrlKey, shiftKey, altKey) { | |
// NONE = Clear selection, add l to selection | |
// Ctrl = Add l to existing selection | |
// Shift = Add all letters from the last selected letter up to and including l to existing selection | |
// Ctrl + Shift = (See Shift) | |
// Alt = Clear selection and select word surrounding l (space delimited) | |
// Ctrl + Alt = Add word surrounding l to existing selection | |
// Shift + Alt = Same as shift, then afterwards add word (space delimited) around l to selection | |
// Ctrl + Shift + Alt = (See Shift + Alt) | |
// If nothing is selected and we hold shift, we assume we start from the first letter: at position 0 | |
// If we don't press shift or ctrl, we can clear our current selection. | |
if (!(ctrlKey || shiftKey) && this.letterFocus.length){ | |
this.letterFocus.forEach(li => { | |
this.letterClasses[li].colour = "black" | |
}) | |
this.letterFocus = [] | |
this.lastSelected = 0 | |
} | |
if (shiftKey){ | |
if (l>this.lastSelected) { | |
for (let i=this.lastSelected; i<=l; i++) { | |
this.letterFocus.push(i) | |
} | |
} else { | |
for (let i=l; i<=this.lastSelected; i++) { | |
this.letterFocus.push(i) | |
} | |
} | |
} | |
this.letterFocus.push(l) // Push l | |
this.lastSelected = l | |
if (altKey){ | |
let l2 = l | |
// Looking backwards | |
while (l2>=0) { | |
let prevLetter = this.letters[l2] | |
if (prevLetter!="_") { | |
this.letterFocus.push(l2) | |
} else { | |
break | |
} | |
l2-- | |
} | |
l2 = l | |
// Looking forward | |
while (l2<this.letters.length) { | |
let nextLetter = this.letters[l2] | |
if (nextLetter!="_") { | |
this.letterFocus.push(l2) | |
} else { | |
break | |
} | |
l2++ | |
} | |
} | |
this.letterFocus = Array.from(new Set(this.letterFocus.sort())) | |
this.letterFocus.forEach(li => { | |
this.letterClasses[li].colour = "red" | |
}) | |
letterStyleNumb.value = "" | |
letterStyleNumb.disabled = true | |
if (this.letterFocus.length==1) { | |
if (this.energyNew.length) { | |
letterEnergyNumb.value = parseFloat(this.energyNew[this.letterFocus[0]]) | |
letterEnergyNumb.disabled = false | |
} | |
if (this.emAngryNew && this.emAngryNew.length) { | |
letterEmotionNumb.value = parseFloat(this.emAngryNew[this.letterFocus[0]]) | |
letterEmotionNumb.disabled = false | |
} | |
if (this.emHappyNew && this.emHappyNew.length) { | |
letterEmotionNumb.value = parseFloat(this.emHappyNew[this.letterFocus[0]]) | |
letterEmotionNumb.disabled = false | |
} | |
if (this.emSadNew && this.emSadNew.length) { | |
letterEmotionNumb.value = parseFloat(this.emSadNew[this.letterFocus[0]]) | |
letterEmotionNumb.disabled = false | |
} | |
if (this.emSurpriseNew && this.emSurpriseNew.length) { | |
letterEmotionNumb.value = parseFloat(this.emSurpriseNew[this.letterFocus[0]]) | |
letterEmotionNumb.disabled = false | |
} | |
if (this.registeredStyleKeys) { | |
this.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
letterStyleNumb.value = parseFloat(this.styleValuesNew[styleKey][this.letterFocus[0]]) | |
letterStyleNumb.disabled = false | |
} | |
}) | |
} | |
letterPitchNumb.value = parseInt(this.pitchNew[this.letterFocus[0]]*100)/100 | |
letterLengthNumb.value = parseInt(parseFloat(this.dursNew[this.letterFocus[0]])*100)/100 | |
letterPitchNumb.disabled = false | |
letterLengthNumb.disabled = false | |
} else { | |
letterEnergyNumb.disabled = true | |
letterEnergyNumb.value = "" | |
letterEmotionNumb.disabled = true | |
letterEmotionNumb.value = "" | |
letterPitchNumb.disabled = true | |
letterPitchNumb.value = "" | |
letterLengthNumb.disabled = true | |
letterLengthNumb.value = "" | |
} | |
} | |
getChangedTimeStamps (startI, endI, audioSDuration) { | |
const adjustedLetters = Array.from(this.adjustedLetters) | |
// Skip this if start/end indexes are not found (new sample) | |
if ((startI==-1 || endI==-1) && !adjustedLetters.length) { | |
return undefined | |
} | |
startI = startI==-1 ? this.letters.length : parseInt(startI) | |
endI = endI==-1 ? 0 : parseInt(endI) | |
// Check OUTSIDE of the given changed indexes for TEXT, to see if there were other changes, to eg pitch/duration | |
if (adjustedLetters.length) { | |
startI = Math.min(startI, Math.min(adjustedLetters)) | |
endI = Math.max(endI, Math.max(adjustedLetters)) | |
} | |
const newStartI = startI | |
const newEndI = endI | |
// Then, look through the duration values of the audio, and get a percent into the audio where those new start/end points are | |
const totalDuration = this.dursNew.reduce((p,c)=>p+c,0) | |
const durAtStart = this.dursNew.filter((v,vi) => vi<=newStartI).reduce((p,c)=>p+c,0) | |
const durAtEnd = this.dursNew.filter((v,vi) => vi<=newEndI).reduce((p,c)=>p+c,0) | |
const startPercent = durAtStart/totalDuration | |
const endPercent = durAtEnd/totalDuration | |
// Then, multiply this by the seconds duration of the generated audio, and pad with ~500ms, to get the final start/end of the section of the audio to play | |
const startSeconds = Math.max(0, startPercent*audioSDuration-0.5) | |
const endSeconds = Math.min(audioSDuration, endPercent*audioSDuration+0.5) | |
return [startSeconds, endSeconds] | |
} | |
} | |
class Letter { | |
constructor (context, index, letter, sliderBox, centerY, left, width) { | |
this.type = "letter" | |
this.context = context | |
this.letter = letter | |
this.sliderBox = sliderBox | |
this.centerY = centerY | |
this.index = index | |
this.left = left | |
this.width = width | |
this.colour = "black" | |
} | |
render () { | |
this.context.fillStyle = this.colour | |
this.context.font = "20pt Arial" | |
this.context.textAlign = "center" | |
this.context.textBaseline = "middle" | |
this.context.fillText(this.letter, this.sliderBox.getXLeft()+this.sliderBox.width/2, this.centerY) | |
} | |
} | |
class SliderGrabber { | |
constructor (context, index, sliderBox, topLeftY, width, height, sliderRange) { | |
this.type = "slider" | |
this.context = context | |
this.sliderBox = sliderBox | |
this.topLeftY = topLeftY | |
this.width = width | |
this.height = height | |
this.index = index | |
this.sliderRange = sliderRange | |
this.isBeingDragged = false | |
this.dragStart = {x: undefined, y: undefined} | |
this.fillStyle = `#${window.currentGame.themeColourPrimary}` | |
} | |
render () { | |
this.context.beginPath() | |
this.context.rect(this.sliderBox.getXLeft()+1, this.topLeftY, this.width, this.height) | |
this.context.stroke() | |
this.context.fillStyle = this.fillStyle | |
this.context.fillRect(this.sliderBox.getXLeft()+1, this.topLeftY, this.width, this.height) | |
} | |
getXLeft () { | |
return this.sliderBox.getXLeft() | |
} | |
setValueFromCoords (topLeftY) { | |
this.topLeftY = topLeftY | |
this.topLeftY = Math.max(window.sequenceEditor.LETTERS_Y_OFFSET+1, this.topLeftY) | |
this.topLeftY = Math.min(this.topLeftY, window.sequenceEditor.LETTERS_Y_OFFSET+window.sequenceEditor.EDITOR_HEIGHT-this.height-1) | |
this.percentUp = (this.topLeftY-window.sequenceEditor.LETTERS_Y_OFFSET) / (window.sequenceEditor.EDITOR_HEIGHT-this.height) | |
window.sequenceEditor.pitchNew[this.index] = (1-this.percentUp)*(this.sliderRange*2)-this.sliderRange | |
} | |
setValueFromValue (value) { | |
value = Math.max(-this.sliderRange, value) | |
value = Math.min(value, this.sliderRange) | |
this.percentUp = (value+this.sliderRange)/(this.sliderRange*2) | |
this.topLeftY = (1-this.percentUp) * (window.sequenceEditor.EDITOR_HEIGHT-this.height) + window.sequenceEditor.LETTERS_Y_OFFSET | |
} | |
} | |
class EnergyEmotionGrabber extends SliderGrabber { | |
constructor (context, index, sliderBox, topLeftY, width, height, sliderRange, modelType, radius, sliderType) { | |
super(context, index, sliderBox, topLeftY, width, height, sliderRange) | |
this.type = `${sliderType}_slider` | |
this.modelType = modelType | |
this.radius = radius | |
} | |
render () { | |
this.context.fillStyle = this.fillStyle | |
this.context.beginPath() | |
this.context.lineWidth = 1 | |
let x = this.sliderBox.getXLeft()+1 + this.sliderBox.width/2 // Centered | |
let y = this.topLeftY | |
this.context.arc(x, y, this.radius, 0, 2 * Math.PI) | |
this.context.fill() | |
this.context.stroke() | |
this.context.lineWidth = 1 | |
} | |
setValueFromCoords (topLeftY) { | |
this.topLeftY = topLeftY | |
this.topLeftY = Math.max(window.sequenceEditor.LETTERS_Y_OFFSET+this.radius, this.topLeftY) | |
this.topLeftY = Math.min(this.topLeftY, window.sequenceEditor.LETTERS_Y_OFFSET+(window.sequenceEditor.EDITOR_HEIGHT-2-this.radius/2)) | |
if (this.type=="energy_slider") { | |
if (this.modelType=="xVAPitch") { | |
this.percentUp = (this.topLeftY-window.sequenceEditor.LETTERS_Y_OFFSET)/(window.sequenceEditor.EDITOR_HEIGHT-this.radius) | |
} else { | |
this.percentUp = 1-(this.topLeftY-window.sequenceEditor.LETTERS_Y_OFFSET)/(window.sequenceEditor.EDITOR_HEIGHT-this.radius) | |
} | |
window.sequenceEditor.energyNew[this.index] = window.sequenceEditor.MAX_ENERGY - (window.sequenceEditor.MAX_ENERGY-window.sequenceEditor.MIN_ENERGY)*this.percentUp | |
} else if (this.type=="style_slider") { | |
this.percentUp = (this.topLeftY-window.sequenceEditor.LETTERS_Y_OFFSET)/(window.sequenceEditor.EDITOR_HEIGHT-this.radius) | |
window.sequenceEditor.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
window.sequenceEditor.styleValuesNew[styleKey][this.index] = window.sequenceEditor.MAX_STYLES - (window.sequenceEditor.MAX_STYLES-window.sequenceEditor.MIN_STYLES)*this.percentUp | |
} | |
}) | |
} else { | |
this.percentUp = (this.topLeftY-window.sequenceEditor.LETTERS_Y_OFFSET)/(window.sequenceEditor.EDITOR_HEIGHT-this.radius) | |
if (seq_edit_view_select.value=="emAngry") { | |
window.sequenceEditor.emAngryNew[this.index] = window.sequenceEditor.MAX_EMOTIONS - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_ENERGY)*this.percentUp | |
} else if (seq_edit_view_select.value=="emHappy") { | |
window.sequenceEditor.emHappyNew[this.index] = window.sequenceEditor.MAX_EMOTIONS - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_ENERGY)*this.percentUp | |
} else if (seq_edit_view_select.value=="emSad") { | |
window.sequenceEditor.emSadNew[this.index] = window.sequenceEditor.MAX_EMOTIONS - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_ENERGY)*this.percentUp | |
} else if (seq_edit_view_select.value=="emSurprise") { | |
window.sequenceEditor.emSurpriseNew[this.index] = window.sequenceEditor.MAX_EMOTIONS - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_ENERGY)*this.percentUp | |
} | |
} | |
} | |
setValueFromValue (value) { | |
if (this.type=="energy_slider") { | |
value = Math.max(window.sequenceEditor.MIN_ENERGY, value) | |
value = Math.min(value, window.sequenceEditor.MAX_ENERGY) | |
if (this.modelType=="xVAPitch") { | |
this.percentUp = ( (value-window.sequenceEditor.MIN_ENERGY) / (window.sequenceEditor.MAX_ENERGY-window.sequenceEditor.MIN_ENERGY) ) | |
} else { | |
this.percentUp = 1 - ( (value-window.sequenceEditor.MIN_ENERGY) / (window.sequenceEditor.MAX_ENERGY-window.sequenceEditor.MIN_ENERGY) ) | |
} | |
} else if (this.type=="style_slider") { | |
value = Math.max(window.sequenceEditor.MIN_STYLES, value) | |
value = Math.min(value, window.sequenceEditor.MAX_STYLES) | |
this.percentUp = ( (value-window.sequenceEditor.MIN_STYLES) / (window.sequenceEditor.MAX_STYLES-window.sequenceEditor.MIN_STYLES) ) | |
} else { | |
value = Math.max(window.sequenceEditor.MIN_EMOTIONS, value) | |
value = Math.min(value, window.sequenceEditor.MAX_EMOTIONS) | |
this.percentUp = ( (value-window.sequenceEditor.MIN_EMOTIONS) / (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_EMOTIONS) ) | |
} | |
this.topLeftY = (1 - this.percentUp) * (window.sequenceEditor.EDITOR_HEIGHT-2-this.radius*2) + (window.sequenceEditor.LETTERS_Y_OFFSET+1) | |
} | |
} | |
class SliderBox { | |
constructor (context, index, leftBox, topY, height, minLetterLength, maxLetterLength, alternateColour=false) { | |
this.type = "box" | |
this.context = context | |
this.leftBox = leftBox | |
this.topY = topY | |
this.height = height | |
this.index = index | |
this.alternateColour = alternateColour | |
this.LEFT_RIGHT_SEQ_PADDING = 20 | |
this.MIN_LETTER_LENGTH = minLetterLength | |
this.MAX_LETTER_LENGTH = maxLetterLength | |
this.isBeingDragged = false | |
this.dragStart = {width: undefined, y: undefined} | |
} | |
render () { | |
this.context.globalAlpha = 0.3 | |
this.context.fillStyle = this.alternateColour ? "white" : "black" | |
this.context.fillRect(this.LEFT_RIGHT_SEQ_PADDING+ (this.getLeftBox()?this.getLeftBox().getX():0), this.topY, this.width, this.height) | |
this.context.beginPath() | |
this.context.rect(this.LEFT_RIGHT_SEQ_PADDING+ (this.getLeftBox()?this.getLeftBox().getX():0), this.topY, this.width, this.height) | |
this.context.stroke() | |
this.context.globalAlpha = 1 | |
} | |
setValueFromValue (value) { | |
value = value * window.sequenceEditor.pacing | |
value = Math.max(0.1, value) | |
value = Math.min(value, 20) | |
this.percentAcross = value/20 | |
this.width = this.percentAcross * (this.MAX_LETTER_LENGTH-this.MIN_LETTER_LENGTH) + this.MIN_LETTER_LENGTH | |
this.grabber.width = this.width-2 | |
this.letter.centerX = this.leftX + this.width/2 | |
} | |
getLeftBox () { | |
if (this.leftBox) { | |
if (window.sequenceEditor.enabled_disabled_items[this.leftBox.index]) { | |
return this.leftBox | |
} else { | |
return this.leftBox.leftBox | |
} | |
} | |
} | |
getX () { | |
if (this.leftBox) { | |
return this.getLeftBox().getX() + this.width + 5 | |
} | |
return 0 + this.width + 5 | |
} | |
getXLeft () { | |
if (this.leftBox) { | |
return this.LEFT_RIGHT_SEQ_PADDING+this.getLeftBox().getX() | |
} | |
return this.LEFT_RIGHT_SEQ_PADDING | |
} | |
} | |
const infer = () => { | |
window.sequenceEditor.hasChanged = false | |
if (!isGenerating) { | |
generateVoiceButton.click() | |
} | |
} | |
const kickOffAutoInferTimer = () => { | |
if (window.sequenceEditor.autoInferTimer != null) { | |
clearTimeout(window.sequenceEditor.autoInferTimer) | |
window.sequenceEditor.autoInferTimer = null | |
} | |
if (autoplay_ckbx.checked) { | |
window.sequenceEditor.autoInferTimer = setTimeout(infer, 500) | |
} | |
} | |
// Un-select letters when clicking anywhere else | |
right.addEventListener("click", event => { | |
if (event.target.nodeName=="BUTTON" || event.target.nodeName=="INPUT" || event.target.nodeName=="SVG" || event.target.nodeName=="IMG" || event.target.nodeName=="path" || event.target == window.sequenceEditor.canvas || event.target.id=="dialogueInput" || (event.target.classList && event.target.classList.contains("autocomplete_option"))) { | |
return | |
} | |
window.sequenceEditor.letterFocus.forEach(li => { | |
window.sequenceEditor.letterClasses[li].colour = "black" | |
}) | |
window.sequenceEditor.letterFocus = [] | |
letterEnergyNumb.disabled = true | |
letterEnergyNumb.value = "" | |
letterPitchNumb.disabled = true | |
letterPitchNumb.value = "" | |
letterLengthNumb.disabled = true | |
letterLengthNumb.value = "" | |
letterEmotionNumb.disabled = true | |
letterEmotionNumb.value = "" | |
letterStyleNumb.disabled = true | |
letterStyleNumb.value = "" | |
}) | |
letterEnergyNumb.addEventListener("click", () => { | |
const lpnValue = parseFloat(letterEnergyNumb.value) || 0 | |
if (window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
}) | |
letterEnergyNumb.addEventListener("input", () => { | |
const lpnValue = parseFloat(letterEnergyNumb.value) || 0 | |
if (window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]] = lpnValue | |
window.sequenceEditor.energyGrabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(lpnValue) | |
kickOffAutoInferTimer() | |
}) | |
letterEnergyNumb.addEventListener("change", () => { | |
const lpnValue = parseFloat(letterEnergyNumb.value) || 0 | |
if (window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]] = lpnValue | |
window.sequenceEditor.energyGrabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(lpnValue) | |
kickOffAutoInferTimer() | |
}) | |
letterEmotionNumb.addEventListener("click", () => { | |
const lpnValue = parseFloat(letterEmotionNumb.value) || 0 | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
if (data[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
}) | |
letterEmotionNumb.addEventListener("input", () => { | |
const lpnValue = parseFloat(letterEmotionNumb.value) || 0 | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
if (window.sequenceEditor.data[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.data[window.sequenceEditor.letterFocus[0]] = lpnValue | |
grabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(lpnValue) | |
kickOffAutoInferTimer() | |
}) | |
letterEmotionNumb.addEventListener("change", () => { | |
const lpnValue = parseFloat(letterEmotionNumb.value) || 0 | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
if (data[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
data[window.sequenceEditor.letterFocus[0]] = lpnValue | |
grabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(lpnValue) | |
kickOffAutoInferTimer() | |
}) | |
const getSelectedStyleDataAndGrabbers = () => { | |
let data, grabbers | |
window.sequenceEditor.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
data = window.sequenceEditor.styleValuesNew[styleKey] | |
grabbers = window.sequenceEditor.styleGrabbers[styleKey] | |
} | |
}) | |
return [data, grabbers] | |
} | |
letterStyleNumb.addEventListener("click", () => { | |
const lpnValue = parseFloat(letterStyleNumb.value) || 0 | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
if (data && data[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
}) | |
letterStyleNumb.addEventListener("input", () => { | |
const lpnValue = parseFloat(letterStyleNumb.value) || 0 | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
if (data[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
data[window.sequenceEditor.letterFocus[0]] = lpnValue | |
grabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(lpnValue) | |
setNewDataToSelectedStyle(data) | |
kickOffAutoInferTimer() | |
}) | |
letterStyleNumb.addEventListener("change", () => { | |
const lpnValue = parseFloat(letterStyleNumb.value) || 0 | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
if (data[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
data[window.sequenceEditor.letterFocus[0]] = lpnValue | |
grabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(lpnValue) | |
setNewDataToSelectedStyle(data) | |
kickOffAutoInferTimer() | |
}) | |
letterPitchNumb.addEventListener("click", () => { | |
const lpnValue = parseFloat(letterPitchNumb.value) || 0 | |
if (window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
}) | |
letterPitchNumb.addEventListener("input", () => { | |
const lpnValue = parseFloat(letterPitchNumb.value) || 0 | |
if (window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]] = lpnValue | |
window.sequenceEditor.grabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(letterPitchNumb.value) | |
kickOffAutoInferTimer() | |
}) | |
letterPitchNumb.addEventListener("change", () => { | |
const lpnValue = parseFloat(letterPitchNumb.value) || 0 | |
if (window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]!=lpnValue) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]] = lpnValue | |
window.sequenceEditor.grabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(letterPitchNumb.value) | |
kickOffAutoInferTimer() | |
}) | |
resetLetter_btn.addEventListener("click", () => { | |
if (window.sequenceEditor.letterFocus.length==0) { | |
return | |
} | |
window.sequenceEditor.letterFocus.forEach(l => { | |
if (window.sequenceEditor.dursNew[l] != window.sequenceEditor.resetDurs[l]) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.dursNew[l] = window.sequenceEditor.resetDurs[l] | |
window.sequenceEditor.pitchNew[l] = window.sequenceEditor.resetPitch[l] | |
window.sequenceEditor.grabbers[l].setValueFromValue(window.sequenceEditor.resetPitch[l]) | |
window.sequenceEditor.sliderBoxes[l].setValueFromValue(window.sequenceEditor.resetDurs[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterLengthNumb.value = parseFloat(window.sequenceEditor.dursNew[window.sequenceEditor.letterFocus[0]]) | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]) | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
window.sequenceEditor.emAngryNew[window.sequenceEditor.letterFocus[0]] = window.sequenceEditor.resetEmAngry[window.sequenceEditor.letterFocus[0]] | |
window.sequenceEditor.emAngryGrabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(window.sequenceEditor.emAngryNew[window.sequenceEditor.letterFocus[0]]) | |
window.sequenceEditor.emHappyNew[window.sequenceEditor.letterFocus[0]] = window.sequenceEditor.resetEmHappy[window.sequenceEditor.letterFocus[0]] | |
window.sequenceEditor.emHappyGrabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(window.sequenceEditor.emHappyNew[window.sequenceEditor.letterFocus[0]]) | |
window.sequenceEditor.emSadNew[window.sequenceEditor.letterFocus[0]] = window.sequenceEditor.resetEmSad[window.sequenceEditor.letterFocus[0]] | |
window.sequenceEditor.emSadGrabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(window.sequenceEditor.emSadNew[window.sequenceEditor.letterFocus[0]]) | |
window.sequenceEditor.emSurpriseNew[window.sequenceEditor.letterFocus[0]] = window.sequenceEditor.resetEmSurprise[window.sequenceEditor.letterFocus[0]] | |
window.sequenceEditor.emSurpriseGrabbers[window.sequenceEditor.letterFocus[0]].setValueFromValue(window.sequenceEditor.emSurpriseNew[window.sequenceEditor.letterFocus[0]]) | |
if (data) { | |
letterEmotionNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]) | |
} | |
window.sequenceEditor.registeredStyleKeys.forEach(styleKey => { | |
window.sequenceEditor.styleValuesNew[styleKey][window.sequenceEditor.letterFocus[0]] = window.sequenceEditor.styleValuesReset[styleKey][window.sequenceEditor.letterFocus[0]] | |
window.sequenceEditor.styleGrabbers[styleKey][window.sequenceEditor.letterFocus[0]].setValueFromValue(window.sequenceEditor.styleValuesNew[styleKey][window.sequenceEditor.letterFocus[0]]) | |
}) | |
let [styleData, styleGrabbers] = getSelectedStyleDataAndGrabbers() | |
if (styleData) { | |
letterStyleNumb.value = parseInt(styleData[window.sequenceEditor.letterFocus[0]]) | |
} | |
} | |
}) | |
const updateLetterLengthFromInput = () => { | |
if (window.sequenceEditor.dursNew[window.sequenceEditor.letterFocus[0]] != letterLengthNumb.value) { | |
window.sequenceEditor.hasChanged = true | |
} | |
window.sequenceEditor.dursNew[window.sequenceEditor.letterFocus[0]] = parseFloat(letterLengthNumb.value) | |
window.sequenceEditor.letterFocus.forEach(l => { | |
window.sequenceEditor.sliderBoxes[l].setValueFromValue(window.sequenceEditor.dursNew[l]) | |
}) | |
kickOffAutoInferTimer() | |
} | |
letterLengthNumb.addEventListener("input", () => { | |
updateLetterLengthFromInput() | |
}) | |
letterLengthNumb.addEventListener("change", () => { | |
updateLetterLengthFromInput() | |
}) | |
// Reset button | |
window.resetEnergy = () => { | |
window.sequenceEditor.energyNew = window.sequenceEditor.resetEnergy.map(v => v) | |
window.sequenceEditor.energyGrabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.energyNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]) | |
} | |
} | |
window.resetStyle = () => { | |
window.sequenceEditor.registeredStyleKeys.forEach(styleKey => { | |
window.sequenceEditor.styleValuesNew[styleKey] = window.sequenceEditor.styleValuesReset[styleKey].map(v => v) | |
window.sequenceEditor.styleGrabbers[styleKey].forEach((slider, l) => slider.setValueFromValue(window.sequenceEditor.styleValuesNew[styleKey][l])) | |
}) | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
if (data) { | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]) | |
} | |
} | |
} | |
window.resetEmotion = () => { | |
window.sequenceEditor.emAngryNew = window.sequenceEditor.resetEmAngry.map(v => v) | |
window.sequenceEditor.emHappyNew = window.sequenceEditor.resetEmHappy.map(v => v) | |
window.sequenceEditor.emSadNew = window.sequenceEditor.resetEmSad.map(v => v) | |
window.sequenceEditor.emSurpriseNew = window.sequenceEditor.resetEmSurprise.map(v => v) | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
window.sequenceEditor.emAngryGrabbers.forEach((slider, l) => slider.setValueFromValue(window.sequenceEditor.emAngryNew[l])) | |
window.sequenceEditor.emHappyGrabbers.forEach((slider, l) => slider.setValueFromValue(window.sequenceEditor.emHappyNew[l])) | |
window.sequenceEditor.emSadGrabbers.forEach((slider, l) => slider.setValueFromValue(window.sequenceEditor.emSadNew[l])) | |
window.sequenceEditor.emSurpriseGrabbers.forEach((slider, l) => slider.setValueFromValue(window.sequenceEditor.emSurpriseNew[l])) | |
if (data && window.sequenceEditor.letterFocus.length==1) { | |
letterEmotionNumb.value = parseFloat(data[window.sequenceEditor.letterFocus[0]]) | |
} | |
} | |
window.resetPitch = () => { | |
window.sequenceEditor.pitchNew = window.sequenceEditor.resetPitch.map(p=>p) | |
// Update the editor pitch values | |
window.sequenceEditor.grabbers.forEach((slider, i) => { | |
slider.setValueFromValue(window.sequenceEditor.pitchNew[i]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} | |
window.resetDursPace = () => { | |
pace_slid.value = 1 | |
paceNumbInput.value = 1 | |
window.sequenceEditor.pacing = parseFloat(pace_slid.value) | |
window.sequenceEditor.dursNew = window.sequenceEditor.resetDurs.map(v => v) | |
// Update the editor lengths | |
window.sequenceEditor.sliderBoxes.forEach((box,i) => { | |
box.setValueFromValue(window.sequenceEditor.dursNew[i]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterLengthNumb.value = parseFloat(window.sequenceEditor.dursNew[window.sequenceEditor.letterFocus[0]]) | |
} | |
} | |
reset_btn.addEventListener("click", () => { | |
if (window.shiftKeyIsPressed) { | |
if (seq_edit_edit_select.value=="energy") { | |
resetEnergy() | |
resetDursPace() | |
} else if (seq_edit_edit_select.value=="pitch") { | |
resetPitch() | |
resetDursPace() | |
} else if (seq_edit_edit_select.value=="emotion") { | |
resetEmotion() | |
resetDursPace() | |
} else if (seq_edit_edit_select.value=="style") { | |
resetStyle() | |
resetDursPace() | |
} | |
window.sequenceEditor.init() | |
} else { | |
reset_what_open_btn.click() | |
} | |
}) | |
reset_what_confirm_btn.addEventListener("click", () => { | |
resetContainer.click() | |
if (reset_what_pitch.checked) { | |
resetPitch() | |
} | |
if (reset_what_energy.checked) { | |
resetEnergy() | |
} | |
if (reset_what_duration.checked) { | |
resetDursPace() | |
} | |
if (reset_what_emotion.checked) { | |
resetEmotion() | |
} | |
if (reset_what_style.checked) { | |
resetStyle() | |
} | |
window.sequenceEditor.init() | |
}) | |
const getSelectedEmotionDataAndGrabbers = () => { | |
let data, grabbers | |
if (seq_edit_view_select.value=="emAngry") { | |
data = window.sequenceEditor.emAngryNew | |
grabbers = window.sequenceEditor.emAngryGrabbers | |
} else if (seq_edit_view_select.value=="emHappy") { | |
data = window.sequenceEditor.emHappyNew | |
grabbers = window.sequenceEditor.emHappyGrabbers | |
} else if (seq_edit_view_select.value=="emSad") { | |
data = window.sequenceEditor.emSadNew | |
grabbers = window.sequenceEditor.emSadGrabbers | |
} else if (seq_edit_view_select.value=="emSurprise") { | |
data = window.sequenceEditor.emSurpriseNew | |
grabbers = window.sequenceEditor.emSurpriseGrabbers | |
} | |
return [data, grabbers] | |
} | |
const setNewDataToSelectedEmotion = (data) => { | |
if (seq_edit_view_select.value=="emAngry") { | |
window.sequenceEditor.emAngryNew = data | |
} else if (seq_edit_view_select.value=="emHappy") { | |
window.sequenceEditor.emHappyNew = data | |
} else if (seq_edit_view_select.value=="emSad") { | |
window.sequenceEditor.emSadNew = data | |
} else if (seq_edit_view_select.value=="emSurprise") { | |
window.sequenceEditor.emSurpriseNew = data | |
} | |
} | |
const setNewDataToSelectedStyle = (data) => { | |
window.sequenceEditor.registeredStyleKeys.forEach(styleKey => { | |
if (seq_edit_view_select.value.startsWith("style_") && seq_edit_view_select.value.includes(styleKey)) { | |
window.sequenceEditor.styleValuesNew[styleKey] = data | |
} | |
}) | |
} | |
amplify_btn.addEventListener("click", () => { | |
if (seq_edit_edit_select.value=="pitch") { | |
window.sequenceEditor.pitchNew = window.sequenceEditor.pitchNew.map((p, pi) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(pi)==-1) { | |
return p | |
} | |
const newVal = p*1.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.pitchSliderRange, newVal) : Math.max(-window.sequenceEditor.pitchSliderRange, newVal) | |
}) | |
window.sequenceEditor.grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.pitchNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_edit_select.value=="energy") { | |
window.sequenceEditor.energyNew = window.sequenceEditor.energyNew.map((e, ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_ENERGY) - (window.sequenceEditor.MAX_ENERGY-window.sequenceEditor.MIN_ENERGY)/2 | |
const newVal = e + distFromMiddle*0.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_ENERGY, newVal) : Math.max(window.sequenceEditor.MIN_ENERGY, newVal) | |
}) | |
window.sequenceEditor.energyGrabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.energyNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_view_select.value.startsWith("style_")) { | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
data = data.map((e, ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_STYLES) - (window.sequenceEditor.MAX_STYLES-window.sequenceEditor.MIN_STYLES)/2 | |
const newVal = e + distFromMiddle*0.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_STYLES, newVal) : Math.max(window.sequenceEditor.MIN_STYLES, newVal) | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedStyle(data) | |
} else if (seq_edit_edit_select.value=="emotion") { | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
data = data.map((e, ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_EMOTIONS) - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_EMOTIONS)/2 | |
const newVal = e + distFromMiddle*0.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_EMOTIONS, newVal) : Math.max(window.sequenceEditor.MIN_EMOTIONS, newVal) | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEmotionNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedEmotion(data) | |
} | |
kickOffAutoInferTimer() | |
}) | |
flatten_btn.addEventListener("click", () => { | |
if (seq_edit_edit_select.value=="pitch") { | |
window.sequenceEditor.pitchNew = window.sequenceEditor.pitchNew.map((p,pi) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(pi)==-1) { | |
return p | |
} | |
return p*(1-0.025) | |
}) | |
window.sequenceEditor.grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.pitchNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_edit_select.value=="energy") { | |
window.sequenceEditor.energyNew = window.sequenceEditor.energyNew.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_ENERGY) - (window.sequenceEditor.MAX_ENERGY-window.sequenceEditor.MIN_ENERGY)/2 | |
const newVal = e + distFromMiddle*-0.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_ENERGY, newVal) : Math.max(window.sequenceEditor.MIN_ENERGY, newVal) | |
}) | |
window.sequenceEditor.energyGrabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.energyNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_view_select.value.startsWith("style_")) { | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
data = data.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_STYLES) - (window.sequenceEditor.MAX_STYLES-window.sequenceEditor.MIN_STYLES)/2 | |
const newVal = e + distFromMiddle*-0.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_STYLES, newVal) : Math.max(window.sequenceEditor.MIN_STYLES, newVal) | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedStyle(data) | |
} else if (seq_edit_edit_select.value=="emotion") { | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
data = data.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_EMOTIONS) - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_EMOTIONS)/2 | |
const newVal = e + distFromMiddle*-0.025 | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_EMOTIONS, newVal) : Math.max(window.sequenceEditor.MIN_EMOTIONS, newVal) | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEmotionNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedEmotion(data) | |
} | |
kickOffAutoInferTimer() | |
}) | |
jitter_btn.addEventListener("click", () => { | |
if (seq_edit_edit_select.value=="pitch") { | |
window.sequenceEditor.pitchNew = window.sequenceEditor.pitchNew.map((p, pi) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(pi)==-1) { | |
return p | |
} | |
let newVal | |
if (p==0) { | |
newVal = 1*(1+ (Math.random()*0.4+0.05) * ((Math.random()-0.5)>0 ? 1 : -1) ) | |
newVal -= 1 | |
} else { | |
newVal = p*(1+ (Math.random()*0.2+0.05) * ((Math.random()-0.5)>0 ? 1 : -1) ) | |
} | |
return newVal>0 ? Math.min(window.sequenceEditor.pitchSliderRange, newVal) : Math.max(-window.sequenceEditor.pitchSliderRange, newVal) | |
}) | |
window.sequenceEditor.grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.pitchNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_edit_select.value=="energy") { | |
window.sequenceEditor.energyNew = window.sequenceEditor.energyNew.map((e, ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_ENERGY) - (window.sequenceEditor.MAX_ENERGY-window.sequenceEditor.MIN_ENERGY)/2 | |
const newVal = e + distFromMiddle*(Math.random()*0.1+0.05) * ((Math.random()-0.5)>0 ? 1 : -1) | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_ENERGY, newVal) : Math.max(window.sequenceEditor.MIN_ENERGY, newVal) | |
}) | |
window.sequenceEditor.energyGrabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.energyNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_view_select.value.startsWith("style_")) { | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
data = data.map((e, ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_STYLES) - (window.sequenceEditor.MAX_STYLES-window.sequenceEditor.MIN_STYLES)/2 | |
const newVal = e + distFromMiddle*(Math.random()*0.1+0.05) * ((Math.random()-0.5)>0 ? 1 : -1) | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_STYLES, newVal) : Math.max(window.sequenceEditor.MIN_STYLES, newVal) | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedStyle(data) | |
} else if (seq_edit_edit_select.value=="emotion") { | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
data = data.map((e, ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
const distFromMiddle = (e-window.sequenceEditor.MIN_EMOTIONS) - (window.sequenceEditor.MAX_EMOTIONS-window.sequenceEditor.MIN_EMOTIONS)/2 | |
const newVal = e + distFromMiddle*(Math.random()*0.1+0.05) * ((Math.random()-0.5)>0 ? 1 : -1) | |
return newVal>0 ? Math.min(window.sequenceEditor.MAX_EMOTIONS, newVal) : Math.max(window.sequenceEditor.MIN_EMOTIONS, newVal) | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEmotionNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedEmotion(data) | |
} | |
kickOffAutoInferTimer() | |
}) | |
increase_btn.addEventListener("click", () => { | |
if (seq_edit_edit_select.value=="pitch") { | |
window.sequenceEditor.pitchNew = window.sequenceEditor.pitchNew.map((p,pi) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(pi)==-1) { | |
return p | |
} | |
return p+0.1 | |
}) | |
window.sequenceEditor.grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.pitchNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_edit_select.value=="energy") { | |
window.sequenceEditor.energyNew = window.sequenceEditor.energyNew.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
return window.currentModel.modelType=="xVAPitch" ? e+0.04 : e-0.04 | |
}) | |
window.sequenceEditor.energyGrabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.energyNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_view_select.value.startsWith("style_")) { | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
data = data.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
return e+0.04 | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedStyle(data) | |
} else if (seq_edit_edit_select.value=="emotion") { | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
data = data.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
return e+0.04 | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEmotionNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedEmotion(data) | |
} | |
kickOffAutoInferTimer() | |
}) | |
decrease_btn.addEventListener("click", () => { | |
if (seq_edit_edit_select.value=="pitch") { | |
window.sequenceEditor.pitchNew = window.sequenceEditor.pitchNew.map((p,pi) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(pi)==-1) { | |
return p | |
} | |
return p-0.1 | |
}) | |
window.sequenceEditor.grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.pitchNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterPitchNumb.value = parseInt(window.sequenceEditor.pitchNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_edit_select.value=="energy") { | |
window.sequenceEditor.energyNew = window.sequenceEditor.energyNew.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
return window.currentModel.modelType=="xVAPitch" ? e-0.04 : e+0.04 | |
}) | |
window.sequenceEditor.energyGrabbers.forEach((slider, l) => { | |
slider.setValueFromValue(window.sequenceEditor.energyNew[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEnergyNumb.value = parseInt(window.sequenceEditor.energyNew[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
} else if (seq_edit_view_select.value.startsWith("style_")) { | |
let [data, grabbers] = getSelectedStyleDataAndGrabbers() | |
data = data.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
return e-0.04 | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterStyleNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedStyle(data) | |
} else if (seq_edit_edit_select.value=="emotion") { | |
let [data, grabbers] = getSelectedEmotionDataAndGrabbers() | |
data = data.map((e,ei) => { | |
if (window.sequenceEditor.letterFocus.length>1 && window.sequenceEditor.letterFocus.indexOf(ei)==-1) { | |
return e | |
} | |
return e-0.04 | |
}) | |
grabbers.forEach((slider, l) => { | |
slider.setValueFromValue(data[l]) | |
}) | |
if (window.sequenceEditor.letterFocus.length==1) { | |
letterEmotionNumb.value = parseInt(data[window.sequenceEditor.letterFocus[0]]*100)/100 | |
} | |
setNewDataToSelectedEmotion(data) | |
} | |
kickOffAutoInferTimer() | |
}) | |
pace_slid.addEventListener("input", () => { | |
paceNumbInput.value = pace_slid.value | |
}) | |
pace_slid.addEventListener("change", () => { | |
editorTooltip.style.display = "none" | |
if (autoplay_ckbx.checked) { | |
generateVoiceButton.click() | |
} | |
paceNumbInput.value = pace_slid.value | |
window.sequenceEditor.pacing = parseFloat(pace_slid.value) | |
window.sequenceEditor.init() | |
}) | |
pace_slid.addEventListener("input", () => { | |
window.sequenceEditor.pacing = parseFloat(pace_slid.value) | |
window.sequenceEditor.sliderBoxes.forEach((box, i) => { | |
box.setValueFromValue(window.sequenceEditor.dursNew[i]) | |
}) | |
}) | |
paceNumbInput.addEventListener("change", () => { | |
pace_slid.value = paceNumbInput.value | |
if (autoplay_ckbx.checked) { | |
generateVoiceButton.click() | |
} | |
window.sequenceEditor.sliderBoxes.forEach((box, i) => {box.setValueFromValue(window.sequenceEditor.dursNew[i])}) | |
window.sequenceEditor.pacing = parseFloat(pace_slid.value) | |
window.sequenceEditor.init() | |
}) | |
paceNumbInput.addEventListener("keyup", () => { | |
pace_slid.value = paceNumbInput.value | |
window.sequenceEditor.sliderBoxes.forEach((box, i) => {box.setValueFromValue(window.sequenceEditor.dursNew[i])}) | |
window.sequenceEditor.pacing = parseFloat(pace_slid.value) | |
window.sequenceEditor.init() | |
}) | |
autoplay_ckbx.addEventListener("change", () => { | |
window.userSettings.autoplay = autoplay_ckbx.checked | |
saveUserSettings() | |
}) | |
// Populate the languages dropdown | |
window.supportedLanguages = { | |
// "am": "Amharic", | |
"ar": "Arabic", | |
"da": "Danish", | |
"de": "German", | |
"el": "Greek", | |
"en": "English", | |
"es": "Spanish", | |
"fi": "Finnish", | |
"fr": "French", | |
"ha": "Hausa", | |
"hi": "Hindi", | |
"hu": "Hungarian", | |
"it": "Italian", | |
"jp": "Japanese", | |
"ko": "Korean", | |
"la": "Latin", | |
"nl": "Dutch", | |
"pl": "Polish", | |
"pt": "Portuguese", | |
"ro": "Romanian", | |
"ru": "Russian", | |
"sv": "Swedish", | |
"sw": "Swahili", | |
// "th": "Thai", | |
"tr": "Turkish", | |
"uk": "Ukrainian", | |
"vi": "Vietnamese", | |
"wo": "Wolof", | |
"yo": "Yoruba", | |
"zh": "Chinese" | |
} | |
window.populateLanguagesDropdownsFromModel = (dropdown, modelJson=undefined) => { | |
dropdown.innerHTML = "" | |
Object.keys(window.supportedLanguages).sort((a,b)=>window.supportedLanguages[a]<window.supportedLanguages[b]?-1:1).forEach(key => { | |
if (!modelJson || !modelJson.lang_capabilities || modelJson.lang_capabilities.includes(key)) { | |
const opt = createElem("option", window.supportedLanguages[key]) | |
opt.value = key | |
dropdown.appendChild(opt) | |
} | |
}) | |
} | |
window.populateLanguagesDropdownsFromModel(base_lang_select) | |
window.populateLanguagesDropdownsFromModel(voiceWorkbenchLanguageDropdown) | |
base_lang_select.value = "en" | |
voiceWorkbenchLanguageDropdown.value = "en" | |
// For copying the generated ARPAbet sequence to the clipboard | |
editorContainer.addEventListener("contextmenu", event => { | |
event.preventDefault() | |
ipcRenderer.send('show-context-menu-editor') | |
}) | |
ipcRenderer.on('context-menu-command', (e, command) => { | |
if (command=="context-copy-editor") { | |
if (window.sequenceEditor && window.sequenceEditor.sequence && window.sequenceEditor.sequence.length && window.currentModel && window.currentModel.modelType=="xVAPitch") { | |
let seqARPAbet = window.sequenceEditor.sequence | |
if (seqARPAbet[0]=="_") { | |
seqARPAbet = seqARPAbet.slice(1, seqARPAbet.length) | |
} | |
if (seqARPAbet[seqARPAbet.length-1]=="_") { | |
seqARPAbet = seqARPAbet.slice(0, seqARPAbet.length-1) | |
} | |
seqARPAbet = seqARPAbet.filter(val => val!="<PAD>") | |
seqARPAbet = seqARPAbet.map(v => { | |
if (v=="_") { | |
return "} {" | |
} | |
return v | |
}) | |
clipboard.writeText("{"+seqARPAbet.join(" ")+"}") | |
} | |
} | |
}) | |
// Audio player | |
window.initWaveSurfer = (src) => { | |
if (window.wavesurfer) { | |
window.wavesurfer.stop() | |
wavesurferContainer.innerHTML = "" | |
} else { | |
window.wavesurfer = WaveSurfer.create({ | |
container: '#wavesurferContainer', | |
backend: 'MediaElement', | |
waveColor: `#${window.currentGame.themeColourPrimary}`, | |
height: 100, | |
progressColor: 'white', | |
responsive: true, | |
}) | |
} | |
try { | |
window.wavesurfer.setSinkId(window.userSettings.base_speaker) | |
} catch (e) { | |
console.log("Can't set sinkId") | |
} | |
if (src) { | |
window.wavesurfer.load(src) | |
} | |
window.wavesurfer.on("finish", () => { | |
samplePlayPause.innerHTML = window.i18n.PLAY | |
}) | |
window.wavesurfer.on("seek", event => { | |
if (event!=0) { | |
window.wavesurfer.play() | |
samplePlayPause.innerHTML = window.i18n.PAUSE | |
} | |
}) | |
} | |
window.samplePlayPauseHandler = event => { | |
if (window.wavesurfer) { | |
if (event.ctrlKey) { | |
if (window.wavesurfer.sink_id!=window.userSettings.alt_speaker) { | |
window.wavesurfer.setSinkId(window.userSettings.alt_speaker) | |
} | |
} else { | |
if (window.wavesurfer.sink_id!=window.userSettings.base_speaker) { | |
window.wavesurfer.setSinkId(window.userSettings.base_speaker) | |
} | |
} | |
if (window.wavesurfer.isPlaying()) { | |
samplePlayPause.innerHTML = window.i18n.PLAY | |
window.wavesurfer.playPause() | |
} else { | |
samplePlayPause.innerHTML = window.i18n.PAUSE | |
window.wavesurfer.playPause() | |
} | |
} | |
} | |
samplePlayPause.addEventListener("click", window.samplePlayPauseHandler) | |
exports.Editor = Editor | |