Spaces:
Runtime error
Runtime error
| const BlockType = require('../../extension-support/block-type'); | |
| const ArgumentType = require('../../extension-support/argument-type'); | |
| const Cast = require('../../util/cast'); | |
| const HelperTool = require('./helper'); | |
| const Helper = new HelperTool.Helper(); | |
| /** | |
| * Class for AudioGroups & AudioSources | |
| * @constructor | |
| */ | |
| class AudioExtension { | |
| constructor(runtime) { | |
| /** | |
| * The runtime instantiating this block package. | |
| * @type {runtime} | |
| */ | |
| this.runtime = runtime; | |
| this.helper = Helper; | |
| this.helper.runtime = this.runtime; | |
| this.runtime.on('PROJECT_STOP_ALL', () => { | |
| for (const audioGroupName in Helper.audioGroups) { | |
| const audioGroup = Helper.GetAudioGroup(audioGroupName); | |
| for (const sourceName in audioGroup.sources) { | |
| audioGroup.sources[sourceName].stop(); | |
| } | |
| } | |
| }); | |
| this.runtime.registerExtensionAudioContext("jgExtendedAudio", this.helper.audioContext, this.helper.audioGlobalVolumeNode); | |
| } | |
| deserialize(data) { | |
| for (const audioGroup in Helper.audioGroups) { | |
| Helper.DeleteAudioGroup(audioGroup); | |
| } | |
| Helper.audioGroups = {}; | |
| for (const audioGroup of data) { | |
| Helper.AddAudioGroup(audioGroup.id, audioGroup); | |
| } | |
| } | |
| serialize() { | |
| return Helper.GetAllAudioGroups().map(audioGroup => ({ | |
| id: audioGroup.id, | |
| sources: {}, | |
| globalVolume: audioGroup.globalVolume, | |
| globalSpeed: audioGroup.globalSpeed, | |
| globalPitch: audioGroup.globalPitch, | |
| globalPan: audioGroup.globalPan | |
| })); | |
| } | |
| orderCategoryBlocks(blocks) { | |
| const buttons = { | |
| create: blocks[0], | |
| delete: blocks[1] | |
| }; | |
| const varBlock = blocks[2]; | |
| blocks.splice(0, 3); | |
| // create the variable block xml's | |
| const varBlocks = Helper.GetAllAudioGroups().map(audioGroup => varBlock.replace('{audioGroupId}', audioGroup.id)); | |
| if (!varBlocks.length) { | |
| return [buttons.create]; | |
| } | |
| // push the button to the top of the var list | |
| varBlocks.reverse(); | |
| varBlocks.push(buttons.delete); | |
| varBlocks.push(buttons.create); | |
| // merge the category blocks and variable blocks into one block list | |
| blocks = varBlocks | |
| .reverse() | |
| .concat(blocks); | |
| return blocks; | |
| } | |
| /** | |
| * @returns {object} metadata for this extension and its blocks. | |
| */ | |
| getInfo() { | |
| return { | |
| id: 'jgExtendedAudio', | |
| name: 'Sound Systems', | |
| color1: '#E256A1', | |
| color2: '#D33388', | |
| isDynamic: true, | |
| orderBlocks: this.orderCategoryBlocks, | |
| blocks: [ | |
| { opcode: 'createAudioGroup', text: 'New Audio Group', blockType: BlockType.BUTTON, }, | |
| { opcode: 'deleteAudioGroup', text: 'Remove an Audio Group', blockType: BlockType.BUTTON, }, | |
| { | |
| opcode: 'audioGroupGet', text: '[AUDIOGROUP]', blockType: BlockType.REPORTER, | |
| arguments: { | |
| AUDIOGROUP: { menu: 'audioGroup', defaultValue: '{audioGroupId}', type: ArgumentType.STRING, } | |
| }, | |
| }, | |
| { text: "Operations", blockType: BlockType.LABEL, }, | |
| { | |
| opcode: 'audioGroupSetVolumeSpeedPitchPan', text: 'set [AUDIOGROUP] [VSPP] to [VALUE]%', blockType: BlockType.COMMAND, | |
| arguments: { | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| VSPP: { type: ArgumentType.STRING, menu: 'vspp', defaultValue: "" }, | |
| VALUE: { type: ArgumentType.NUMBER, defaultValue: 100 }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioGroupGetModifications', text: '[AUDIOGROUP] [OPTION]', blockType: BlockType.REPORTER, disableMonitor: true, | |
| arguments: { | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| OPTION: { type: ArgumentType.STRING, menu: 'audioGroupOptions', defaultValue: "" }, | |
| }, | |
| }, | |
| "---", | |
| { | |
| opcode: 'audioSourceCreate', text: '[CREATEOPTION] audio source named [NAME] in [AUDIOGROUP]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| CREATEOPTION: { type: ArgumentType.STRING, menu: 'createOptions', defaultValue: "" }, | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceDuplicate', text: 'duplicate audio source from [NAME] to [COPY] in [AUDIOGROUP]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| COPY: { type: ArgumentType.STRING, defaultValue: "AudioSource2" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceReverse', text: 'reverse audio source used in [NAME] in [AUDIOGROUP]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| COPY: { type: ArgumentType.STRING, defaultValue: "AudioSource2" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceDeleteAll', text: '[DELETEOPTION] all audio sources in [AUDIOGROUP]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| DELETEOPTION: { type: ArgumentType.STRING, menu: 'deleteOptions', defaultValue: "" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| "---", | |
| { | |
| opcode: 'audioSourceSetScratch', text: 'set audio source [NAME] in [AUDIOGROUP] to use [SOUND]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| SOUND: { type: ArgumentType.STRING, menu: 'sounds', defaultValue: "" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceSetUrl', text: 'set audio source [NAME] in [AUDIOGROUP] to use [URL]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| URL: { type: ArgumentType.STRING, defaultValue: "https://extensions.turbowarp.org/meow.mp3" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourcePlayerOption', text: '[PLAYEROPTION] audio source [NAME] in [AUDIOGROUP]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| PLAYEROPTION: { type: ArgumentType.STRING, menu: 'playerOptions', defaultValue: "" }, | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| "---", | |
| { | |
| opcode: 'audioSourceSetLoop', text: 'set audio source [NAME] in [AUDIOGROUP] to [LOOP]', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| LOOP: { type: ArgumentType.STRING, menu: 'loop', defaultValue: "loop" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceSetTime2', text: 'set audio source [NAME] [TIMEPOS] position in [AUDIOGROUP] to [TIME] seconds', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| TIMEPOS: { type: ArgumentType.STRING, menu: 'timePosition' }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| TIME: { type: ArgumentType.NUMBER, defaultValue: 0.3 }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceSetVolumeSpeedPitchPan', text: 'set audio source [NAME] [VSPP] in [AUDIOGROUP] to [VALUE]%', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| VSPP: { type: ArgumentType.STRING, menu: 'vspp', defaultValue: "" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| VALUE: { type: ArgumentType.NUMBER, defaultValue: 100 }, | |
| }, | |
| }, | |
| "---", | |
| { | |
| opcode: 'audioSourceGetModificationsBoolean', text: 'audio source [NAME] [OPTION] in [AUDIOGROUP]', blockType: BlockType.BOOLEAN, disableMonitor: true, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| OPTION: { type: ArgumentType.STRING, menu: 'audioSourceOptionsBooleans', defaultValue: "" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| { | |
| opcode: 'audioSourceGetModificationsNormal', text: 'audio source [NAME] [OPTION] in [AUDIOGROUP]', blockType: BlockType.REPORTER, disableMonitor: true, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| OPTION: { type: ArgumentType.STRING, menu: 'audioSourceOptions', defaultValue: "" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| }, | |
| }, | |
| // deleted blocks | |
| { | |
| opcode: 'audioSourceSetTime', text: 'set audio source [NAME] start position in [AUDIOGROUP] to [TIME] seconds', blockType: BlockType.COMMAND, | |
| arguments: { | |
| NAME: { type: ArgumentType.STRING, defaultValue: "AudioSource1" }, | |
| AUDIOGROUP: { type: ArgumentType.STRING, menu: 'audioGroup', defaultValue: "" }, | |
| TIME: { type: ArgumentType.NUMBER, defaultValue: 0.3 }, | |
| }, | |
| hideFromPalette: true, | |
| }, | |
| ], | |
| menus: { | |
| audioGroup: 'fetchAudioGroupMenu', | |
| sounds: 'fetchScratchSoundMenu', | |
| // specific menus | |
| vspp: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "volume", value: "volume" }, | |
| { text: "speed", value: "speed" }, | |
| { text: "detune", value: "pitch" }, | |
| { text: "pan", value: "pan" }, | |
| ] | |
| }, | |
| playerOptions: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "play", value: "play" }, | |
| { text: "pause", value: "pause" }, | |
| { text: "stop", value: "stop" }, | |
| ] | |
| }, | |
| loop: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "loop", value: "loop" }, | |
| { text: "not loop", value: "not loop" }, | |
| ] | |
| }, | |
| timePosition: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "time", value: "time" }, | |
| { text: "start", value: "start" }, | |
| { text: "end", value: "end" }, | |
| { text: "start loop", value: "start loop" }, | |
| { text: "end loop", value: "end loop" }, | |
| ] | |
| }, | |
| deleteOptions: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "delete", value: "delete" }, | |
| { text: "play", value: "play" }, | |
| { text: "pause", value: "pause" }, | |
| { text: "stop", value: "stop" }, | |
| ] | |
| }, | |
| createOptions: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "create", value: "create" }, | |
| { text: "delete", value: "delete" }, | |
| ] | |
| }, | |
| // audio group stuff | |
| audioGroupOptions: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "volume", value: "volume" }, | |
| { text: "speed", value: "speed" }, | |
| { text: "detune", value: "pitch" }, | |
| { text: "pan", value: "pan" }, | |
| ] | |
| }, | |
| // audio source stuff | |
| audioSourceOptionsBooleans: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "playing", value: "playing" }, | |
| { text: "paused", value: "paused" }, | |
| { text: "looping", value: "looping" }, | |
| ] | |
| }, | |
| audioSourceOptions: { | |
| acceptReporters: true, | |
| items: [ | |
| { text: "volume", value: "volume" }, | |
| { text: "speed", value: "speed" }, | |
| { text: "detune", value: "pitch" }, | |
| { text: "pan", value: "pan" }, | |
| { text: "time position", value: "time position" }, | |
| { text: "output volume", value: "output volume" }, | |
| { text: "start position", value: "start position" }, | |
| { text: "end position", value: "end position" }, | |
| { text: "start loop position", value: "start loop position" }, | |
| { text: "end loop position", value: "end loop position" }, | |
| { text: "sound length", value: "sound length" }, | |
| { text: "origin sound", value: "origin sound" }, | |
| // see https://stackoverflow.com/a/54567527 as to why this is not a menu option | |
| // { text: "dominant frequency", value: "dominant frequency" }, | |
| ] | |
| } | |
| } | |
| }; | |
| } | |
| createAudioGroup() { | |
| const newGroup = prompt('Set a name for this Audio Group:', 'audio group ' + (Helper.GetAllAudioGroups().length + 1)); | |
| if (!newGroup) return alert('Canceled') | |
| if (Helper.GetAudioGroup(newGroup)) return alert(`"${newGroup}" is taken!`); | |
| Helper.AddAudioGroup(newGroup); | |
| vm.emitWorkspaceUpdate(); | |
| this.serialize(); | |
| } | |
| deleteAudioGroup() { | |
| const group = prompt('Which audio group would you like to delete?'); | |
| // helper deals with audio groups that dont exist, so we just call the function with no check | |
| Helper.DeleteAudioGroup(group); | |
| vm.emitWorkspaceUpdate(); | |
| this.serialize(); | |
| } | |
| fetchAudioGroupMenu() { | |
| const audioGroups = Helper.GetAllAudioGroups(); | |
| if (audioGroups.length <= 0) { | |
| return [ | |
| { | |
| text: '', | |
| value: '' | |
| } | |
| ]; | |
| } | |
| return audioGroups.map(audioGroup => ({ | |
| text: audioGroup.id, | |
| value: audioGroup.id | |
| })); | |
| } | |
| fetchScratchSoundMenu() { | |
| const sounds = vm.editingTarget.sprite.sounds; // this function only gets used in the editor so we are safe to use editingTarget | |
| if (sounds.length <= 0) return [{ text: '', value: '' }]; | |
| return sounds.map(sound => ({ | |
| text: sound.name, | |
| value: sound.name | |
| })); | |
| } | |
| audioGroupGet(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| return JSON.stringify(Object.getOwnPropertyNames(audioGroup.sources)); | |
| } | |
| audioGroupSetVolumeSpeedPitchPan(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| switch (args.VSPP) { | |
| case "volume": | |
| audioGroup.globalVolume = Helper.Clamp(Cast.toNumber(args.VALUE) / 100, 0, 1); | |
| break; | |
| case "speed": | |
| audioGroup.globalSpeed = Helper.Clamp(Cast.toNumber(args.VALUE) / 100, 0, Infinity); | |
| break; | |
| case "detune": | |
| case "pitch": | |
| audioGroup.globalPitch = Cast.toNumber(args.VALUE); | |
| break; | |
| case "pan": | |
| audioGroup.globalPan = Helper.Clamp(Cast.toNumber(args.VALUE), -100, 100) / 100; | |
| break; | |
| } | |
| Helper.UpdateAudioGroupSources(audioGroup); | |
| } | |
| audioSourceCreate(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| switch (args.CREATEOPTION) { | |
| case "create": | |
| Helper.RemoveAudioSource(audioGroup, args.NAME); | |
| Helper.AppendAudioSource(audioGroup, args.NAME); | |
| break; | |
| case "delete": | |
| Helper.RemoveAudioSource(audioGroup, args.NAME); | |
| break; | |
| } | |
| } | |
| audioSourceDuplicate(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| const origin = Cast.toString(args.NAME); | |
| const newName = Cast.toString(args.COPY); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, origin); | |
| if (!audioSource) return; | |
| Helper.RemoveAudioSource(audioGroup, newName); | |
| audioGroup.sources[newName] = audioSource.clone(); | |
| } | |
| audioSourceReverse(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| const target = Cast.toString(args.NAME); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, target); | |
| if (!audioSource) return; | |
| audioSource.reverse(); | |
| } | |
| audioSourceDeleteAll(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| for (const sourceName in audioGroup.sources) { | |
| switch (args.DELETEOPTION) { | |
| case "delete": | |
| Helper.RemoveAudioSource(audioGroup, sourceName); | |
| break; | |
| case "play": | |
| audioGroup.sources[sourceName].play(); | |
| break; | |
| case "pause": | |
| audioGroup.sources[sourceName].pause(); | |
| break; | |
| case "stop": | |
| audioGroup.sources[sourceName].stop(); | |
| break; | |
| } | |
| } | |
| } | |
| audioSourceSetScratch(args, util) { | |
| return new Promise((resolve, reject) => { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return resolve(); | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return resolve(); | |
| const sound = Helper.FindSoundByName(util.target.sprite.sounds, args.SOUND); | |
| if (!sound) return resolve(); | |
| let canUse = true; | |
| try { | |
| // eslint-disable-next-line no-unused-vars | |
| util.target.sprite.soundBank.getSoundPlayer(sound.soundId).buffer; | |
| } catch { | |
| canUse = false; | |
| } | |
| if (!canUse) return resolve(); | |
| const buffer = util.target.sprite.soundBank.getSoundPlayer(sound.soundId).buffer | |
| audioSource.duration = buffer.duration; | |
| audioSource.src = buffer; | |
| audioSource.originAudioName = `${args.SOUND}`; | |
| resolve(); | |
| }) | |
| } | |
| audioSourceSetUrl(args, util) { | |
| return new Promise((resolve, reject) => { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return resolve(); | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return resolve(); | |
| fetch(args.URL).then(response => response.arrayBuffer().then(arrayBuffer => { | |
| Helper.audioContext.decodeAudioData(arrayBuffer, buffer => { | |
| audioSource.duration = buffer.duration; | |
| audioSource.src = buffer; | |
| audioSource.originAudioName = `${args.URL}`; | |
| resolve(); | |
| }, resolve); | |
| }).catch(resolve)).catch(err => { | |
| // this is not a url, try some other stuff instead | |
| const sound = Helper.FindSoundByName(util.target.sprite.sounds, args.URL); | |
| if (sound) { | |
| // this is a scratch sound name | |
| let canUse = true; | |
| try { | |
| // eslint-disable-next-line no-unused-vars | |
| util.target.sprite.soundBank.getSoundPlayer(sound.soundId).buffer; | |
| } catch { | |
| canUse = false; | |
| } | |
| if (!canUse) return resolve(); | |
| const buffer = util.target.sprite.soundBank.getSoundPlayer(sound.soundId).buffer | |
| audioSource.duration = buffer.duration; | |
| audioSource.src = buffer; | |
| audioSource.originAudioName = `${args.URL}`; | |
| return resolve(); | |
| } | |
| console.warn(err); | |
| return resolve(); | |
| }); | |
| }) | |
| } | |
| audioSourcePlayerOption(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return; | |
| if (!["play", "pause", "stop"].includes(args.PLAYEROPTION)) return; | |
| audioSource[args.PLAYEROPTION](); | |
| } | |
| audioSourceSetLoop(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return; | |
| if (!["loop", "not loop"].includes(args.LOOP)) return; | |
| audioSource.looping = args.LOOP == "loop"; | |
| } | |
| audioSourceSetTime(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return; | |
| audioSource.startPosition = Cast.toNumber(args.TIME); | |
| } | |
| audioSourceSetTime2(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return; | |
| switch (args.TIMEPOS) { | |
| case "start": | |
| audioSource.startPosition = Cast.toNumber(args.TIME); | |
| break; | |
| case "end": | |
| audioSource.endPosition = Cast.toNumber(args.TIME); | |
| break; | |
| case "start loop": | |
| audioSource.loopStartPosition = Cast.toNumber(args.TIME); | |
| break; | |
| case "end loop": | |
| audioSource.loopEndPosition = Cast.toNumber(args.TIME); | |
| break; | |
| case "time": | |
| audioSource.setTimePosition(Cast.toNumber(args.TIME)); | |
| break; | |
| } | |
| } | |
| audioSourceSetVolumeSpeedPitchPan(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return; | |
| switch (args.VSPP) { | |
| case "volume": | |
| audioSource.volume = Helper.Clamp(Cast.toNumber(args.VALUE) / 100, 0, 1); | |
| break; | |
| case "speed": | |
| audioSource.speed = Helper.Clamp(Cast.toNumber(args.VALUE) / 100, 0, Infinity); | |
| break; | |
| case "detune": | |
| case "pitch": | |
| audioSource.pitch = Cast.toNumber(args.VALUE); | |
| break; | |
| case "pan": | |
| audioSource.pan = Helper.Clamp(Cast.toNumber(args.VALUE), -100, 100) / 100; | |
| break; | |
| } | |
| Helper.UpdateAudioGroupSources(audioGroup); | |
| } | |
| audioGroupGetModifications(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| switch (args.OPTION) { | |
| case "volume": | |
| return audioGroup.globalVolume * 100; | |
| case "speed": | |
| return audioGroup.globalSpeed * 100; | |
| case "detune": | |
| case "pitch": | |
| return audioGroup.globalPitch; | |
| case "pan": | |
| return audioGroup.globalPan * 100; | |
| default: | |
| return 0; | |
| } | |
| } | |
| audioSourceGetModificationsBoolean(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return false; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return false; | |
| switch (args.OPTION) { | |
| case "playing": | |
| return ((!audioSource.paused) && (!audioSource.notPlaying)); | |
| case "paused": | |
| return audioSource.paused; | |
| case "looping": | |
| return audioSource.looping; | |
| default: | |
| return false; | |
| } | |
| } | |
| audioSourceGetModificationsNormal(args) { | |
| const audioGroup = Helper.GetAudioGroup(args.AUDIOGROUP); | |
| if (!audioGroup) return ""; | |
| const audioSource = Helper.GrabAudioSource(audioGroup, args.NAME); | |
| if (!audioSource) return ""; | |
| switch (args.OPTION) { | |
| case "volume": | |
| return audioSource.volume * 100; | |
| case "speed": | |
| return audioSource.speed * 100; | |
| case "detune": | |
| case "pitch": | |
| return audioSource.pitch; | |
| case "pan": | |
| return audioSource.pan * 100; | |
| case "start position": | |
| return audioSource.startPosition; | |
| case "end position": | |
| return audioSource.endPosition; | |
| case "start loop position": | |
| return audioSource.loopStartPosition; | |
| case "end loop position": | |
| return audioSource.loopEndPosition; | |
| case "time position": | |
| return audioSource.getTimePosition(); | |
| case "sound length": | |
| return audioSource.duration; | |
| case "origin sound": | |
| return audioSource.originAudioName; | |
| case "output volume": | |
| return audioSource.getVolume() * 100; | |
| case "dominant frequency": | |
| return audioSource.getFrequency(); | |
| default: | |
| return ""; | |
| } | |
| } | |
| } | |
| module.exports = AudioExtension; | |