Initial commit
This commit is contained in:
169
components/experiments/GainController.vue
Normal file
169
components/experiments/GainController.vue
Normal file
@@ -0,0 +1,169 @@
|
||||
<template>
|
||||
<div>
|
||||
<div v-if="error" class="error-message">
|
||||
{{ error }}
|
||||
</div>
|
||||
<AudioFileSelector @file-selected="onFileSelected" />
|
||||
<!-- Ramp Time Control -->
|
||||
<div class="ramp-time-control">
|
||||
<label for="rampTime">Ramp Time (ms):</label>
|
||||
<input
|
||||
id="rampTime"
|
||||
v-model="rampTime"
|
||||
type="range"
|
||||
min="100"
|
||||
max="50000"
|
||||
step="100"
|
||||
>
|
||||
<span>{{ rampTime }}ms</span>
|
||||
</div>
|
||||
<div class="gain-controller">
|
||||
<div v-for="frequency in frequencies" :key="frequency" class="frequency-control">
|
||||
<RNBOControlValue
|
||||
:center-frequency="frequency"
|
||||
@control-value-change="(value) => handleValueChange(value.frequency, value.value)"
|
||||
/>
|
||||
<AudioTagWebAudio
|
||||
:ref="el => { if (el) audioElements[frequency] = el }"
|
||||
:src="audioSrc"
|
||||
:volume="currentVolumes[frequency]"
|
||||
/>
|
||||
<div>
|
||||
Frequency: {{ frequency }}Hz
|
||||
<br>Gain Value (dB): {{ gainValuesDB[frequency] }}
|
||||
<br>Normalized: {{ normalizedVolumes[frequency] }}
|
||||
<br>Volume: {{ currentVolumes[frequency] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, ref, onUnmounted, reactive } from 'vue'
|
||||
import AudioFileSelector from '../AudioFileSelector.vue'
|
||||
import AudioTagWebAudio from './AudioTagWebAudio.vue'
|
||||
import RNBOControlValue from './tests/ControlValues/RNBOControlValue.vue'
|
||||
import { useAudioStore } from '~/stores/audio'
|
||||
|
||||
export default defineComponent({
|
||||
name: 'GainController',
|
||||
components: {
|
||||
RNBOControlValue,
|
||||
AudioTagWebAudio,
|
||||
AudioFileSelector
|
||||
},
|
||||
setup () {
|
||||
const logger = useNuxtApp().$logger
|
||||
logger.info('GainController setup')
|
||||
const audioStore = useAudioStore()
|
||||
logger.info('Got audioStore', audioStore)
|
||||
const audioSrc = ref(window.location.origin + '/sounds/lagoon.ogg')
|
||||
const rampTime = ref(25000)
|
||||
logger.info('Set rampTime', 25000)
|
||||
const frequencies = ref([63, 125, 250, 500, 1000, 2000, 4000, 8000, 16000])
|
||||
logger.info('Set frequencies', { frequencies })
|
||||
const error = ref<string | null>(null)
|
||||
|
||||
const gainValuesDB = reactive<Record<number, number>>({})
|
||||
const currentVolumes = reactive<Record<number, number>>({})
|
||||
const normalizedVolumes = reactive<Record<number, number>>({})
|
||||
const audioElements = reactive<Record<number, InstanceType<typeof AudioTagWebAudio>>>({})
|
||||
|
||||
const rampIntervals: Record<number, ReturnType<typeof setInterval> | null> = {}
|
||||
|
||||
const onFileSelected = (file: string) => {
|
||||
const fullPath = new URL(file, window.location.origin).toString()
|
||||
audioSrc.value = fullPath
|
||||
logger.info('User hat ein File ausgewählt ' + file)
|
||||
useNuxtApp().$logger.log({ audioElements })
|
||||
setTimeout(() => {
|
||||
audioStore.setPlaying(true)
|
||||
}, 250)
|
||||
}
|
||||
|
||||
const calculateNormalizedVolume = (db: number): number => {
|
||||
const minDB = -12
|
||||
const maxDB = 2
|
||||
return (db - minDB) / (maxDB - minDB)
|
||||
}
|
||||
|
||||
const rampVolume = (frequency: number, targetVolume: number, duration: number) => {
|
||||
const startVolume = currentVolumes[frequency] || 1
|
||||
const startTime = Date.now()
|
||||
const endTime = startTime + duration
|
||||
|
||||
if (rampIntervals[frequency]) {
|
||||
clearInterval(rampIntervals[frequency]!)
|
||||
}
|
||||
|
||||
rampIntervals[frequency] = setInterval(() => {
|
||||
const now = Date.now()
|
||||
if (now >= endTime) {
|
||||
currentVolumes[frequency] = targetVolume
|
||||
clearInterval(rampIntervals[frequency]!)
|
||||
rampIntervals[frequency] = null
|
||||
return
|
||||
}
|
||||
|
||||
const progress = (now - startTime) / duration
|
||||
currentVolumes[frequency] = startVolume + (targetVolume - startVolume) * progress
|
||||
}, 50)
|
||||
}
|
||||
|
||||
const handleValueChange = (frequency: number, value: number) => {
|
||||
logger.info('Change for ' + frequency + ' to ' + value)
|
||||
if (!isNaN(value)) {
|
||||
gainValuesDB[frequency] = value
|
||||
normalizedVolumes[frequency] = calculateNormalizedVolume(value)
|
||||
rampVolume(frequency, normalizedVolumes[frequency], rampTime.value)
|
||||
} else {
|
||||
useNuxtApp().$logger.log('value is not NaN', { value })
|
||||
}
|
||||
}
|
||||
|
||||
onUnmounted(() => {
|
||||
Object.values(rampIntervals).forEach((interval) => {
|
||||
if (interval) { clearInterval(interval) }
|
||||
})
|
||||
})
|
||||
|
||||
return {
|
||||
frequencies,
|
||||
gainValuesDB,
|
||||
currentVolumes,
|
||||
normalizedVolumes,
|
||||
audioElements,
|
||||
handleValueChange,
|
||||
error,
|
||||
onFileSelected,
|
||||
audioSrc,
|
||||
rampTime
|
||||
}
|
||||
}
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.error-message {
|
||||
color: red;
|
||||
font-weight: bold;
|
||||
padding: 10px;
|
||||
border: 1px solid red;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.ramp-time-control {
|
||||
margin-top: 20px;
|
||||
}
|
||||
.ramp-time-control input {
|
||||
width: 300px;
|
||||
margin: 0 10px;
|
||||
}
|
||||
.frequency-control {
|
||||
margin-bottom: 20px;
|
||||
padding: 10px;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
Reference in New Issue
Block a user