Implement record function

This commit is contained in:
Kevin Thomas
2022-04-28 23:56:51 -07:00
parent 232163064e
commit e13a056706
2 changed files with 146 additions and 66 deletions

View File

@@ -95,13 +95,11 @@
<v-card-text> <v-card-text>
<v-container> <v-container>
<v-row> <v-row>
<v-col cols="12"> <v-text-field
<v-text-field v-model="profileName"
v-model="profileName" label="Profile Name"
label="Profile Name" :rules="[rules.required()]"
:rules="[rules.required()]" />
/>
</v-col>
</v-row> </v-row>
</v-container> </v-container>
</v-card-text> </v-card-text>
@@ -169,7 +167,7 @@
</v-list-item-title> </v-list-item-title>
</v-list-item> </v-list-item>
<v-list-item <v-list-item
@click="startRecordingDialog = true" @click="openStartRecordingDialog"
> >
<v-list-item-icon> <v-list-item-icon>
<v-icon>mdi-record</v-icon> <v-icon>mdi-record</v-icon>
@@ -262,7 +260,6 @@
:items="profileItems" :items="profileItems"
return-object return-object
label="Profiles" label="Profiles"
class="mx-3 mb-5"
/> />
</v-row> </v-row>
</v-container> </v-container>
@@ -289,29 +286,54 @@
v-model="startRecordingDialog" v-model="startRecordingDialog"
max-width="600px" max-width="600px"
> >
<v-card> <v-form
<v-card-title> ref="startRecordingForm"
<span class="text-h5">Start Recording</span> v-model="isRecordingValid"
</v-card-title> >
<v-card-text> <v-card>
Start recording the currently playing audio? This is only supported on Chrome and Firefox. <v-card-title>
</v-card-text> <span class="text-h5">Start Recording</span>
<v-card-actions> </v-card-title>
<v-spacer /> <v-card-text>
<v-btn <v-container>
text <v-row>
@click="startRecordingDialog = false" <p>Select profile to record audio for. This is only supported on Chrome and Firefox.</p>
> </v-row>
Close <v-row>
</v-btn> <v-select
<v-btn v-model="recordedProfile"
text :items="profileItems"
@click="startRecording" return-object
> label="Profiles"
Record />
</v-btn> </v-row>
</v-card-actions> <v-row>
</v-card> <v-text-field
v-model="recordingFileName"
label="File Name"
:rules="[rules.required()]"
/>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer />
<v-btn
text
@click="startRecordingDialog = false"
>
Close
</v-btn>
<v-btn
text
:disabled="!isRecordingValid"
@click="startRecording"
>
Record
</v-btn>
</v-card-actions>
</v-card>
</v-form>
</v-dialog> </v-dialog>
<v-dialog <v-dialog
@@ -323,7 +345,7 @@
<span class="text-h5">Recording</span> <span class="text-h5">Recording</span>
</v-card-title> </v-card-title>
<v-card-text> <v-card-text>
Time Elapsed: {{ recordingTimeElapsed }} Time Elapsed: {{ recordingTimeElapsed }} Seconds
</v-card-text> </v-card-text>
<v-card-actions> <v-card-actions>
<v-spacer /> <v-spacer />
@@ -708,9 +730,7 @@
<v-card-text> <v-card-text>
<v-container> <v-container>
<v-row> <v-row>
<v-col cols="12"> <p><strong>WARNING:</strong> Uploaded samples are publicly accessible.</p>
<strong>WARNING:</strong> Uploaded samples are publicly accessible.
</v-col>
</v-row> </v-row>
<v-row> <v-row>
<v-file-input <v-file-input
@@ -721,13 +741,11 @@
/> />
</v-row> </v-row>
<v-row> <v-row>
<v-col cols="12"> <v-text-field
<v-text-field v-model="sampleName"
v-model="sampleName" label="Sample Name"
label="Sample Name" :rules="[rules.required()]"
:rules="[rules.required()]" />
/>
</v-col>
</v-row> </v-row>
</v-container> </v-container>
</v-card-text> </v-card-text>
@@ -784,7 +802,6 @@
item-text="name" item-text="name"
return-object return-object
label="Samples" label="Samples"
class="mx-3"
@change="loadPreviewSample" @change="loadPreviewSample"
/> />
</v-row> </v-row>
@@ -798,7 +815,6 @@
v-model="previewSampleLoopPointsEnabled" v-model="previewSampleLoopPointsEnabled"
:disabled="previewSamplePlaying" :disabled="previewSamplePlaying"
label="Use Loop Points" label="Use Loop Points"
class="mx-3"
/> />
</v-row> </v-row>
@@ -807,7 +823,7 @@
v-model="previewSampleLoopStart" v-model="previewSampleLoopStart"
type="number" type="number"
label="Loop Start Time" label="Loop Start Time"
class="mx-3" class="mr-3"
:disabled="!previewSampleLoopPointsEnabled || previewSamplePlaying" :disabled="!previewSampleLoopPointsEnabled || previewSamplePlaying"
:rules="[rules.gt(-1)]" :rules="[rules.gt(-1)]"
@change="updatePreviewSamplePlayerLoopPoints" @change="updatePreviewSamplePlayerLoopPoints"
@@ -817,7 +833,7 @@
v-model="previewSampleLoopEnd" v-model="previewSampleLoopEnd"
type="number" type="number"
label="Loop End Time" label="Loop End Time"
class="mx-3" class="ml-3"
:disabled="!previewSampleLoopPointsEnabled || previewSamplePlaying" :disabled="!previewSampleLoopPointsEnabled || previewSamplePlaying"
:rules="[rules.gt(-1), rules.lt(previewSampleLength)]" :rules="[rules.gt(-1), rules.lt(previewSampleLength)]"
@change="updatePreviewSamplePlayerLoopPoints" @change="updatePreviewSamplePlayerLoopPoints"
@@ -829,7 +845,6 @@
v-model="previewSampleFadeIn" v-model="previewSampleFadeIn"
type="number" type="number"
label="Fade In Time" label="Fade In Time"
class="mx-3"
:disabled="previewSamplePlaying" :disabled="previewSamplePlaying"
:rules="[rules.gt(-1)]" :rules="[rules.gt(-1)]"
@change="updatePreviewSamplePlayerFadeIn" @change="updatePreviewSamplePlayerFadeIn"

View File

@@ -67,6 +67,9 @@ export default {
startRecordingDialog: false, startRecordingDialog: false,
recordingDialog: false, recordingDialog: false,
recordingTimeElapsed: 0, recordingTimeElapsed: 0,
recordedProfile: {},
recordingFileName: '',
isRecordingValid: false,
errorSnackbar: false, errorSnackbar: false,
errorSnackbarText: '', errorSnackbarText: '',
rules: { rules: {
@@ -253,6 +256,7 @@ export default {
this.selectedProfile = this.profileItems.find(p => p.id === profileId) this.selectedProfile = this.profileItems.find(p => p.id === profileId)
} }
this.exportedProfile = this.profileItems[0] this.exportedProfile = this.profileItems[0]
this.recordedProfile = this.profileItems[0]
this.loadProfile() this.loadProfile()
} }
} }
@@ -487,7 +491,7 @@ export default {
} }
}) })
.catch(() => { .catch(() => {
this.errorSnackbarText = 'Error Saving Profile' this.errorSnackbarText = 'Error Importing Profile'
this.errorSnackbar = true this.errorSnackbar = true
}) })
@@ -540,7 +544,7 @@ export default {
} }
}) })
.catch(() => { .catch(() => {
this.errorSnackbarText = 'Error Loading Profile' this.errorSnackbarText = 'Error Exporting Profile'
this.errorSnackbar = true this.errorSnackbar = true
}) })
@@ -636,43 +640,104 @@ export default {
this.samplePreviewPlayer.setLoopPoints(this.previewSampleLoopStart, this.previewSampleLoopEnd) this.samplePreviewPlayer.setLoopPoints(this.previewSampleLoopStart, this.previewSampleLoopEnd)
} }
}, },
async startRecording () { openStartRecordingDialog () {
this.startRecordingDialog = false this.startRecordingDialog = true
this.recordingDialog = true this.profileMoreDialog = false
this.recordingTimeElapsed = 0 },
startRecording () {
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) { if (!this.isFilterEnabled && !this.isTremoloEnabled) {
this.noise.connect(this.recorder) this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.recorder).toDestination()
} else if (!this.isFilterEnabled && this.isTremoloEnabled) { } else if (!this.isFilterEnabled && this.isTremoloEnabled) {
this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder) this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder).toDestination().start()
} else if (this.isFilterEnabled && !this.isLFOFilterCutoffEnabled && !this.isTremoloEnabled) { this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.tremolo)
this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.recorder) } else if (this.isFilterEnabled && !this.isTremoloEnabled) {
} else if (this.isFilterEnabled && this.isLFOFilterCutoffEnabled && !this.isTremoloEnabled) { this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.recorder).toDestination()
this.filter = new Tone.Filter(this.filterCutoff, this.filterType).connect(this.recorder) this.noise = new Tone.Noise({ volume: this.volume, type: this.noiseColor }).connect(this.filter)
} else if (this.isFilterEnabled && this.isLFOFilterCutoffEnabled && this.isTremoloEnabled) { } else if (this.isFilterEnabled && this.isTremoloEnabled) {
this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder) 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 { } else {
this.tremolo = new Tone.Tremolo({ frequency: this.tremoloFrequency, depth: this.tremoloDepth }).connect(this.recorder) 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.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)
}
this.players.player(s.id).volume.value = s.volume
this.players.player(s.id).connect(this.recorder) this.players.player(s.id).connect(this.recorder)
this.players.player(s.id).unsync().sync().start(0)
}) })
await this.recorder.start() this.noise.sync().start(0)
this.recordingInterval = setInterval(() => this.recordingTimeElapsed++, 1000)
Tone.Transport.start()
}, },
async stopRecording () { async stopRecording () {
const recording = await this.recorder.stop() const recording = await this.recorder.stop()
this.loadProfile()
const url = URL.createObjectURL(recording) const url = URL.createObjectURL(recording)
const anchor = document.createElement('a') const anchor = document.createElement('a')
anchor.download = this.selectedProfile.text + '.webm' anchor.download = this.recordingFileName + '.webm'
anchor.href = url anchor.href = url
anchor.click() anchor.click()
clearInterval(this.recordingInterval) clearInterval(this.recordingInterval)
this.recordingDialog = false this.recordingDialog = false
this.stop()
} }
} }
} }