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 | |