import * as Tone from 'tone' export default { name: 'Noise', data: () => ({ mainPlayLoading: true, isTimerValid: false, selectedProfile: {}, profileItems: [], profileDialog: false, profileName: '', isProfileValid: false, profileMoreDialog: false, importDialog: false, isImportValid: false, exportDialog: false, importedProfile: null, importedProfileName: '', exportedProfile: {}, infoSnackbar: false, infoSnackbarText: '', playDisabled: false, isTimerEnabled: false, hours: 0, minutes: 0, seconds: 30, duration: 30, timeRemaining: 0, noiseColor: 'pink', noiseColorItems: ['pink', 'white', 'brown'], volume: -10, isFilterEnabled: false, filterCutoff: 1000, filterType: 'lowpass', filterTypeItems: ['lowpass', 'highpass', 'bandpass', 'lowshelf', 'highshelf', 'notch', 'allpass', 'peaking'], isLFOFilterCutoffEnabled: false, lfoFilterCutoffFrequency: 0.5, lfoFilterCutoffMin: 0, lfoFilterCutoffMax: 5000, lfoFilterCutoffRange: [100, 5000], isTremoloEnabled: false, tremoloFrequency: 0.5, tremoloDepth: 0.5, isReverbEnabled: false, allSamples: [], loadedSamples: [], selectedSample: null, uploadSampleDialog: false, addSampleDialog: false, checkedSamples: [], sampleName: '', isSampleUploadValid: false, canUpload: false, editSampleDialog: false, previewSampleLoopPointsEnabled: false, previewSampleLoopStart: 0, previewSampleLoopEnd: 0, previewSampleFadeIn: 0, previewSamplePlaying: false, selectedPreviewSample: {}, previewSampleItems: [], isEditSampleValid: false, previewSampleButtonText: 'Preview Sample', previewSampleLoading: true, previewSampleLength: 0, startRecordingDialog: false, recordingDialog: false, recordingTimeElapsed: 0, recordedProfile: {}, recordingFileName: '', isRecordingValid: false, unsavedWork: false, saveProfileText: 'Save Profile', unwatch: null, confirmSwitchProfileDialog: false, activeProfile: {}, isSporadicValid: false, errorSnackbar: false, errorSnackbarText: '', rules: { lt (n) { return value => (!isNaN(parseInt(value, 10)) && value < n) || 'Must be less than ' + n }, gt (n) { return value => (!isNaN(parseInt(value, 10)) && value > n) || 'Must be greater than ' + n }, required () { return value => !!value || 'Required' } } }), computed: { unloadedSamples: function () { const samples = [] this.allSamples.forEach(s1 => { const result = this.loadedSamples.find(s2 => s2.id === s1.id) if (!result) { samples.push(s1) } }) return samples }, changeableSettings: function () { const settings = [ this.isTimerEnabled, this.hours, this.minutes, this.seconds, this.volume, this.noiseColor, this.isFilterEnabled, this.filterType, this.filterCutoff, this.isLFOFilterCutoffEnabled, this.lfoFilterCutoffFrequency, this.lfoFilterCutoffRange, this.isTremoloEnabled, this.tremoloDepth, this.tremoloFrequency, this.isTimerEnabled, this.loadedSamples ] this.loadedSamples.forEach(s => { settings.push(s.volume) settings.push(s.reverbEnabled) settings.push(s.reverbPreDelay) settings.push(s.reverbDecay) settings.push(s.reverbWet) settings.push(s.playbackMode) settings.push(s.sporadicMin) settings.push(s.sporadicMax) }) return settings } }, created () { this.noise = new Tone.Noise() this.filter = new Tone.Filter() this.tremolo = new Tone.Tremolo() this.lfo = new Tone.LFO() this.players = new Tone.Players() this.samplePreviewPlayer = new Tone.Player().toDestination() this.samplePreviewPlayer.loop = true this.recorder = new Tone.Recorder() this.populateProfileItems(0) this.populatePreviewSampleItems() this.getSamples() this.getCurrentUser() }, beforeDestroy () { this.stop() }, methods: { async play () { if (!this.players.loaded) { return } await Tone.start() this.playDisabled = true Tone.Transport.cancel() if (!this.isFilterEnabled && !this.isTremoloEnabled) { this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).toDestination() } else if (!this.isFilterEnabled && this.isTremoloEnabled) { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).toDestination().start() this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.tremolo) } else if (this.isFilterEnabled && !this.isTremoloEnabled) { this.filter = new Tone.Filter(this.filterCutoff, this.filterType).toDestination() this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter) } else if (this.isFilterEnabled && this.isTremoloEnabled) { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).toDestination().start() this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.tremolo) this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter) } else { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).toDestination().start() this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.tremolo) this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter) } if (this.isLFOFilterCutoffEnabled) { this.lfo = new Tone.LFO({ frequency: this.lfoFilterCutoffFrequency, min: this.lfoFilterCutoffRange[0], max: this.lfoFilterCutoffRange[1] }) this.lfo.connect(this.filter.frequency).start() } if (this.isTimerEnabled) { this.duration = parseInt((this.hours * 3600)) + parseInt((this.minutes * 60)) + parseInt(this.seconds) this.timeRemaining = this.duration this.transportInterval = setInterval(() => this.stop(), this.duration * 1000 + 100) this.timeRemainingInterval = setInterval(() => this.startTimer(), 1000) Tone.Transport.loopEnd = this.duration this.noise.sync().start(0).stop(this.duration) } else { this.noise.sync().start(0) } this.loadedSamples.forEach(s => { this.players.player(s.id).loop = true this.players.player(s.id).fadeIn = s.fadeIn if (s.loopPointsEnabled) { this.players.player(s.id).setLoopPoints(s.loopStart, s.loopEnd) } else { this.players.player(s.id).setLoopPoints(0, this.players.player(s.id).buffer.duration) } this.players.player(s.id).volume.value = s.volume this.players.player(s.id).disconnect() if (s.reverbEnabled) { const reverb = new Tone.Reverb(s.reverbDecay).toDestination() reverb.set({ preDelay: s.reverbPreDelay, wet: s.reverbWet }) this.players.player(s.id).connect(reverb) } else { this.players.player(s.id).toDestination() } if (s.playbackMode === 'sporadic') { this.players.player(s.id).loop = false const maxInt = parseInt(s.sporadicMax, 10) const minInt = parseInt(s.sporadicMin, 10) if (minInt <= maxInt) { const rand = Math.floor(Math.random() * (maxInt - minInt + 1) + minInt) s.initialSporadicPlayInterval = setInterval(() => this.playSporadicSample(s.id), rand * 1000) } } else { this.players.player(s.id).loop = true if (this.isTimerEnabled) { this.players.player(s.id).unsync().sync().start(0).stop(this.duration) } else { this.players.player(s.id).unsync().sync().start(0) } } }) Tone.Transport.start('+0.1') }, playSporadicSample (id) { const sample = this.loadedSamples.find(s => s.id === id) clearInterval(sample.initialSporadicPlayInterval) clearInterval(sample.sporadicInterval) this.players.player(id).unsync().sync().start() const maxInt = parseInt(sample.sporadicMax, 10) const minInt = parseInt(sample.sporadicMin, 10) sample.playNextTime = Math.floor(Math.random() * (maxInt - minInt + 1) + minInt) sample.sporadicInterval = setInterval(() => this.playSporadicSample(id), sample.playNextTime * 1000) }, stop () { clearInterval(this.transportInterval) Tone.Transport.stop() this.playDisabled = false clearInterval(this.timeRemainingInterval) this.timeRemaining = 0 this.duration = 0 this.loadedSamples.forEach(s => { if (s.playbackMode === 'sporadic') { clearInterval(s.initialSporadicPlayInterval) clearInterval(s.sporadicInterval) } }) }, startTimer () { this.timeRemaining -= 1 }, updateVolume () { this.noise.volume.value = this.volume }, updateNoiseColor () { this.noise.type = this.noiseColor }, updateFilterType () { this.filter.type = this.filterType }, updateFilterCutoff () { this.filter.set({ frequency: this.filterCutoff }) }, updateLFOFilterCutoffFrequency () { this.lfo.set({ frequency: this.lfoFilterCutoffFrequency }) }, updateLFOFilterCutoffRange () { this.lfo.set({ min: this.lfoFilterCutoffRange[0], max: this.lfoFilterCutoffRange[1] }) }, updateTremoloFrequency () { this.tremolo.set({ frequency: this.tremoloFrequency }) }, updateTremoloDepth () { this.tremolo.set({ depth: this.tremoloDepth }) }, updateAudioChain () { this.noise.disconnect() if (!this.isFilterEnabled && !this.isTremoloEnabled) { this.noise.toDestination() } else if (!this.isFilterEnabled && this.isTremoloEnabled) { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).toDestination().start() this.noise.connect(this.tremolo) } else if (this.isFilterEnabled && !this.isLFOFilterCutoffEnabled && !this.isTremoloEnabled) { this.filter = new Tone.Filter(this.filterCutoff, this.filterType).toDestination() this.noise.connect(this.filter) this.lfo.disconnect() this.lfo.stop() } else if (this.isFilterEnabled && this.isLFOFilterCutoffEnabled && !this.isTremoloEnabled) { this.filter = new Tone.Filter(this.filterCutoff, this.filterType).toDestination() this.noise.connect(this.filter) this.lfo = new Tone.LFO({ frequency: this.lfoFilterCutoffFrequency, min: this.lfoFilterCutoffRange[0], max: this.lfoFilterCutoffRange[1] }) this.lfo.connect(this.filter.frequency).start() } else if (this.isFilterEnabled && this.isLFOFilterCutoffEnabled && this.isTremoloEnabled) { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).toDestination().start() this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.tremolo) this.noise.connect(this.filter) this.lfo = new Tone.LFO({ frequency: this.lfoFilterCutoffFrequency, min: this.lfoFilterCutoffRange[0], max: this.lfoFilterCutoffRange[1] }) this.lfo.connect(this.filter.frequency).start() } else { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).toDestination().start() this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.tremolo) this.noise.connect(this.filter) } }, populateProfileItems (profileId) { this.$http.get('/profiles') .then(response => { if (response.status === 200) { if (response.data.profiles.length === 0) { this.addDefaultProfile() } else { this.profileItems = response.data.profiles if (profileId === 0) { this.selectedProfile = this.profileItems[0] } else { this.selectedProfile = this.profileItems.find(p => p.id === profileId) } this.exportedProfile = this.profileItems[0] this.recordedProfile = this.profileItems[0] this.loadProfile(true) } } }) }, addDefaultProfile () { this.$http.post('/profiles/default') .then(response => { if (response.status === 200) { const defaultProfile = { id: response.data.id, text: 'Default' } this.profileItems = [defaultProfile] this.selectedProfile = defaultProfile } }) }, saveProfile () { this.$http.post('/profiles', { name: this.profileName, isTimerEnabled: this.isTimerEnabled, duration: this.duration, volume: this.volume, noiseColor: this.noiseColor, isFilterEnabled: this.isFilterEnabled, filterType: this.filterType, filterCutoff: this.filterCutoff, isLFOFilterCutoffEnabled: this.isLFOFilterCutoffEnabled, lfoFilterCutoffFrequency: this.lfoFilterCutoffFrequency, lfoFilterCutoffLow: this.lfoFilterCutoffRange[0], lfoFilterCutoffHigh: this.lfoFilterCutoffRange[1], isTremoloEnabled: this.isTremoloEnabled, tremoloFrequency: this.tremoloFrequency, tremoloDepth: this.tremoloDepth, samples: this.loadedSamples }).then(response => { if (response.status === 200) { this.profileDialog = false this.populateProfileItems(response.data.id) this.unsavedWork = false this.infoSnackbarText = 'Profile Saved' this.infoSnackbar = true } }) .catch(() => { this.errorSnackbarText = 'Error Saving Profile' this.errorSnackbar = true }) }, updateProfile () { this.$http.put('/profiles/'.concat(this.selectedProfile.id), { isTimerEnabled: this.isTimerEnabled, duration: this.duration, volume: this.volume, noiseColor: this.noiseColor, isFilterEnabled: this.isFilterEnabled, filterType: this.filterType, filterCutoff: this.filterCutoff, isLFOFilterCutoffEnabled: this.isLFOFilterCutoffEnabled, lfoFilterCutoffFrequency: this.lfoFilterCutoffFrequency, lfoFilterCutoffLow: this.lfoFilterCutoffRange[0], lfoFilterCutoffHigh: this.lfoFilterCutoffRange[1], isTremoloEnabled: this.isTremoloEnabled, tremoloFrequency: this.tremoloFrequency, tremoloDepth: this.tremoloDepth, samples: this.loadedSamples }).then(response => { if (response.status === 200) { this.unsavedWork = false this.infoSnackbarText = 'Profile Saved' this.infoSnackbar = true } }) .catch(() => { this.errorSnackbarText = 'Error Saving Profile' this.errorSnackbar = true }) }, loadProfile (checkForUnsavedWork) { if (checkForUnsavedWork && this.unsavedWork) { this.confirmSwitchProfileDialog = true } else { this.$http.get('/profiles/'.concat(this.selectedProfile.id)) .then(response => { if (response.status === 200) { const profile = response.data.profile this.isTimerEnabled = profile.isTimerEnabled this.duration = profile.duration this.volume = profile.volume this.noiseColor = profile.noiseColor this.isFilterEnabled = profile.isFilterEnabled this.filterType = profile.filterType this.filterCutoff = profile.filterCutoff this.isLFOFilterCutoffEnabled = profile.isLFOFilterCutoffEnabled this.lfoFilterCutoffFrequency = profile.lfoFilterCutoffFrequency this.lfoFilterCutoffRange[0] = profile.lfoFilterCutoffLow this.lfoFilterCutoffRange[1] = profile.lfoFilterCutoffHigh this.isTremoloEnabled = profile.isTremoloEnabled this.tremoloFrequency = profile.tremoloFrequency this.tremoloDepth = profile.tremoloDepth this.loadedSamples = profile.samples this.activeProfile = profile if (this.unwatch) { this.unwatch() } this.unwatch = this.$watch('changeableSettings', function () { this.unsavedWork = true }) } }) .catch(() => { this.errorSnackbarText = 'Error Loading Profile' this.errorSnackbar = true }) } }, deleteProfile () { this.$http.delete('/profiles/'.concat(this.selectedProfile.id)) .then(response => { if (response.status === 200) { this.populateProfileItems(0) this.infoSnackbarText = 'Profile Deleted' this.infoSnackbar = true } }) .catch(() => { this.errorSnackbarText = 'Error Deleting Profile' this.errorSnackbar = true }) }, getSamples () { this.$http.get('/samples') .then(response => { if (response.status === 200) { this.allSamples = response.data.samples this.allSamples.forEach(s => { if (!this.players.has(s.id)) { this.players.add(s.id, '/samples/' + s.user + '_' + s.name).toDestination() } }) this.mainPlayLoading = false } }) }, uploadSample () { const formData = new FormData() formData.append('name', this.sampleName) formData.append('sample', this.selectedSample) this.$http.post('/samples', formData, { headers: { 'Content-Type': 'multipart/form-data' } }) .then(response => { if (response.status === 200) { this.getSamples() this.populatePreviewSampleItems() this.infoSnackbarText = 'Sample Uploaded' this.infoSnackbar = true } }) .catch((error) => { if (error.response.status === 409) { this.errorSnackbarText = 'Error Uploading Sample: Duplicate Sample Name' } else { this.errorSnackbarText = 'Error Uploading Sample' } this.errorSnackbar = true }) this.uploadSampleDialog = false }, addSample () { this.checkedSamples.forEach(i => { const load = this.allSamples.find(e => e.id === i) load.volume = -10 load.sporadicMin = 30 load.sporadicMax = 300 this.loadedSamples.push(load) }) this.addSampleDialog = false this.checkedSamples = [] }, updateSampleVolume (id, index) { this.players.player(id).volume.value = this.loadedSamples[index].volume this.$forceUpdate() }, removeSample (index) { this.loadedSamples.splice(index, 1) }, getCurrentUser () { this.$http.get('/users/current') .then(response => { if (response.status === 200) { this.canUpload = response.data.user.canUpload this.$vuetify.theme.dark = response.data.user.darkMode const preferences = response.data.user.preferences this.$vuetify.theme.themes.dark.primary = preferences.accentColor.hex this.$vuetify.theme.themes.light.primary = preferences.accentColor.hex } }) }, resetProfileForm () { if (this.$refs.profileForm) { this.$refs.profileForm.reset() } }, resetUploadSampleForm () { if (this.$refs.uploadSampleForm) { this.$refs.uploadSampleForm.reset() } }, openImportDialog () { this.profileMoreDialog = false this.importDialog = true }, openExportDialog () { this.profileMoreDialog = false this.exportDialog = true }, async importProfile () { const fileContents = await this.readFile(this.importedProfile) const profileJSON = JSON.parse(fileContents) this.$http.post('/profiles/import', { name: this.importedProfileName, isTimerEnabled: profileJSON.isTimerEnabled, duration: profileJSON.duration, volume: profileJSON.volume, noiseColor: profileJSON.noiseColor, isFilterEnabled: profileJSON.isFilterEnabled, filterType: profileJSON.filterType, filterCutoff: profileJSON.filterCutoff, isLFOFilterCutoffEnabled: profileJSON.isLFOFilterCutoffEnabled, lfoFilterCutoffFrequency: profileJSON.lfoFilterCutoffFrequency, lfoFilterCutoffLow: profileJSON.lfoFilterCutoffLow, lfoFilterCutoffHigh: profileJSON.lfoFilterCutoffHigh, isTremoloEnabled: profileJSON.isTremoloEnabled, tremoloFrequency: profileJSON.tremoloFrequency, tremoloDepth: profileJSON.tremoloDepth }).then(response => { if (response.status === 200) { this.importDialog = false this.populateProfileItems(response.data.id) this.infoSnackbarText = 'Profile Imported and Saved' this.infoSnackbar = true } }) .catch(() => { this.errorSnackbarText = 'Error Importing Profile' this.errorSnackbar = true }) if (this.$refs.importForm) { this.$refs.importForm.reset() } }, readFile (file) { return new Promise((resolve, reject) => { const reader = new FileReader() reader.onload = res => { resolve(res.target.result) } reader.onerror = err => reject(err) reader.readAsText(file) }) }, exportProfile () { this.$http.get('/profiles/'.concat(this.exportedProfile.id)) .then(response => { if (response.status === 200) { const profile = response.data.profile const profileJSON = {} profileJSON.name = this.exportedProfile.text profileJSON.isTimerEnabled = profile.isTimerEnabled profileJSON.duration = profile.duration profileJSON.volume = profile.volume profileJSON.noiseColor = profile.noiseColor profileJSON.isFilterEnabled = profile.isFilterEnabled profileJSON.filterType = profile.filterType profileJSON.filterCutoff = profile.filterCutoff profileJSON.isLFOFilterCutoffEnabled = profile.isLFOFilterCutoffEnabled profileJSON.lfoFilterCutoffFrequency = profile.lfoFilterCutoffFrequency profileJSON.lfoFilterCutoffLow = profile.lfoFilterCutoffLow profileJSON.lfoFilterCutoffHigh = profile.lfoFilterCutoffHigh profileJSON.isTremoloEnabled = profile.isTremoloEnabled profileJSON.tremoloFrequency = profile.tremoloFrequency profileJSON.tremoloDepth = profile.tremoloDepth const dataStr = 'data:text/json;charset=utf-8,' + encodeURIComponent(JSON.stringify(profileJSON)) const downloadAnchorNode = document.createElement('a') downloadAnchorNode.setAttribute('href', dataStr) downloadAnchorNode.setAttribute('download', profileJSON.name + '.json') document.body.appendChild(downloadAnchorNode) // required for firefox downloadAnchorNode.click() downloadAnchorNode.remove() } }) .catch(() => { this.errorSnackbarText = 'Error Exporting Profile' this.errorSnackbar = true }) this.exportDialog = false }, populatePreviewSampleItems () { this.$http.get('/samples') .then(response => { if (response.status === 200) { this.previewSampleItems = response.data.samples if (this.previewSampleItems.length > 0) { this.selectedPreviewSample = this.previewSampleItems[0] } } }) }, openEditSampleForm () { if (this.previewSampleItems.length > 0) { this.selectedPreviewSample = this.previewSampleItems[0] } this.loadPreviewSample() }, closeEditSampleForm () { this.editSampleDialog = false this.previewSampleLoading = true if (this.previewSamplePlaying) { this.previewSamplePlaying = false this.previewSampleButtonText = 'Preview Sample' this.samplePreviewPlayer.stop() } }, loadPreviewSample () { this.previewSampleLoading = true this.$http.get('/samples/'.concat(this.selectedPreviewSample.id)) .then(async response => { if (response.status === 200) { const sample = response.data.sample await this.samplePreviewPlayer.load('/samples/' + sample.user + '_' + sample.name) this.previewSampleFadeIn = sample.fadeIn this.previewSampleLoopPointsEnabled = sample.loopPointsEnabled if (sample.loopPointsEnabled) { this.previewSampleLoopStart = sample.loopStart this.previewSampleLoopEnd = sample.loopEnd this.samplePreviewPlayer.setLoopPoints(this.previewSampleLoopStart, this.previewSampleLoopEnd) } else { this.previewSampleLoopStart = 0 this.previewSampleLoopEnd = 0 } this.samplePreviewPlayer.fadeIn = this.previewSampleFadeIn this.previewSampleLength = this.samplePreviewPlayer.buffer.duration this.previewSampleLoading = false } }) }, updatePreviewSampleLoopPoints () { if (this.previewSampleLoopPointsEnabled) { this.samplePreviewPlayer.setLoopPoints(this.previewSampleLoopStart, this.previewSampleLoopEnd) } else { this.samplePreviewPlayer.setLoopPoints(0, this.samplePreviewPlayer.buffer.duration) } }, previewSample () { if (this.previewSamplePlaying) { this.previewSamplePlaying = false this.previewSampleButtonText = 'Preview Sample' this.samplePreviewPlayer.stop() } else { this.previewSamplePlaying = true this.previewSampleButtonText = 'Stop' this.samplePreviewPlayer.start() } }, editSample () { this.$http.put('/samples/'.concat(this.selectedPreviewSample.id), { fadeIn: this.previewSampleFadeIn, loopPointsEnabled: this.previewSampleLoopPointsEnabled, loopStart: this.previewSampleLoopStart, loopEnd: this.previewSampleLoopEnd }).then(response => { if (response.status === 200) { this.getSamples() // Update sample if it's already loaded in current profile const sample = this.loadedSamples.find(s => s.id === this.selectedPreviewSample.id) if (sample) { sample.fadeIn = this.previewSampleFadeIn sample.loopPointsEnabled = this.previewSampleLoopPointsEnabled sample.loopStart = this.previewSampleLoopStart sample.loopEnd = this.previewSampleLoopEnd } this.closeEditSampleForm() this.infoSnackbarText = 'Sample Saved' this.infoSnackbar = true } }) .catch(() => { this.errorSnackbarText = 'Error Saving Sample' this.errorSnackbar = true }) }, updatePreviewSamplePlayerFadeIn () { this.samplePreviewPlayer.fadeIn = this.previewSampleFadeIn }, updatePreviewSamplePlayerLoopPoints () { if (this.previewSampleLoopStart >= 0 && this.previewSampleLoopEnd <= this.previewSampleLength) { this.samplePreviewPlayer.setLoopPoints(this.previewSampleLoopStart, this.previewSampleLoopEnd) } }, openStartRecordingDialog () { this.startRecordingDialog = true this.profileMoreDialog = false }, startRecording () { // Save current profile before recording this.updateProfile() this.$http.get('/profiles/'.concat(this.recordedProfile.id)) .then(async response => { if (response.status === 200) { const profile = response.data.profile this.isTimerEnabled = profile.isTimerEnabled this.duration = profile.duration this.volume = profile.volume this.noiseColor = profile.noiseColor this.isFilterEnabled = profile.isFilterEnabled this.filterType = profile.filterType this.filterCutoff = profile.filterCutoff this.isLFOFilterCutoffEnabled = profile.isLFOFilterCutoffEnabled this.lfoFilterCutoffFrequency = profile.lfoFilterCutoffFrequency this.lfoFilterCutoffRange[0] = profile.lfoFilterCutoffLow this.lfoFilterCutoffRange[1] = profile.lfoFilterCutoffHigh this.isTremoloEnabled = profile.isTremoloEnabled this.tremoloFrequency = profile.tremoloFrequency this.tremoloDepth = profile.tremoloDepth this.loadedSamples = profile.samples this.startRecordingDialog = false this.recordingDialog = true this.recordingTimeElapsed = 0 await this.recorder.start() this.recordingInterval = setInterval(() => this.recordingTimeElapsed++, 1000) this.playProfileForRecording() } }) .catch(() => { this.errorSnackbarText = 'Error Recording Profile' this.errorSnackbar = true }) }, playProfileForRecording () { this.playDisabled = true Tone.Transport.cancel() if (!this.isFilterEnabled && !this.isTremoloEnabled) { this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.recorder).toDestination() } else if (!this.isFilterEnabled && this.isTremoloEnabled) { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder).toDestination().start() this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.tremolo) } else if (this.isFilterEnabled && !this.isTremoloEnabled) { this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.recorder).toDestination() this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter) } else if (this.isFilterEnabled && this.isTremoloEnabled) { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder).toDestination().start() this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.tremolo) this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter) } else { this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder).toDestination().start() this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.tremolo) this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter) } if (this.isLFOFilterCutoffEnabled) { this.lfo = new Tone.LFO({ frequency: this.lfoFilterCutoffFrequency, min: this.lfoFilterCutoffRange[0], max: this.lfoFilterCutoffRange[1] }) this.lfo.connect(this.filter.frequency).start() } this.loadedSamples.forEach(s => { this.players.player(s.id).loop = true this.players.player(s.id).fadeIn = s.fadeIn if (s.loopPointsEnabled) { this.players.player(s.id).setLoopPoints(s.loopStart, s.loopEnd) } else { this.players.player(s.id).setLoopPoints(0, this.players.player(s.id).buffer.duration) } this.players.player(s.id).volume.value = s.volume this.players.player(s.id).disconnect() if (s.reverbEnabled) { const reverb = new Tone.Reverb(s.reverbDecay).connect(this.recorder).toDestination() reverb.set({ preDelay: s.reverbPreDelay, wet: s.reverbWet }) this.players.player(s.id).connect(reverb) } else { this.players.player(s.id).connect(this.recorder).toDestination() } }) this.noise.sync().start(0) this.loadedSamples.forEach(s => { if (s.playbackMode === 'sporadic') { this.players.player(s.id).loop = false const maxInt = parseInt(s.sporadicMax, 10) const minInt = parseInt(s.sporadicMin, 10) const rand = Math.floor(Math.random() * (maxInt - minInt + 1) + minInt) s.initialSporadicPlayInterval = setInterval(() => this.playSporadicSample(s.id), rand * 1000) } else { this.players.player(s.id).loop = true this.players.player(s.id).unsync().sync().start(0) } }) Tone.Transport.start('+0.1') }, async stopRecording () { const recording = await this.recorder.stop() // Set active profile back to the selected one this.loadProfile(false) const url = URL.createObjectURL(recording) const anchor = document.createElement('a') anchor.download = this.recordingFileName + '.webm' anchor.href = url anchor.click() clearInterval(this.recordingInterval) this.loadedSamples.forEach(s => { if (s.playbackMode === 'sporadic') { clearInterval(s.initialSporadicPlayInterval) clearInterval(s.sporadicInterval) } }) this.recordingDialog = false this.stop() }, async cancelRecording () { await this.recorder.stop() // Set active profile back to the selected one this.loadProfile(false) clearInterval(this.recordingInterval) this.recordingDialog = false this.stop() }, discardChanges () { this.unsavedWork = false this.loadProfile(true) this.confirmSwitchProfileDialog = false }, saveChanges () { // Set active profile back to previously selected one before saving this.selectedProfile = this.profileItems.find(p => p.text === this.activeProfile.name) this.updateProfile() this.confirmSwitchProfileDialog = false } } }