feat: add phase audio test
This commit is contained in:
parent
9ae4b740e1
commit
1510c9661d
3 changed files with 111 additions and 0 deletions
|
@ -38,6 +38,23 @@ button, .button {
|
||||||
|
|
||||||
background: black;
|
background: black;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="number"] {
|
||||||
|
background: transparent;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid white;
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 0.2em;
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.7;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
select {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import StereoTest from './(channels)/stereo-test.svelte';
|
import StereoTest from './(channels)/stereo-test.svelte';
|
||||||
|
import PhaseTest from './phase.svelte';
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<article>
|
<article>
|
||||||
|
@ -15,6 +16,8 @@
|
||||||
<li><a class="button" href="channels-7.1">7.1 Surround</a></li>
|
<li><a class="button" href="channels-7.1">7.1 Surround</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
<h3>Phase test</h3>
|
||||||
|
<PhaseTest />
|
||||||
</article>
|
</article>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
91
src/routes/audio/phase.svelte
Normal file
91
src/routes/audio/phase.svelte
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onMount } from 'svelte';
|
||||||
|
|
||||||
|
let frequency = 60;
|
||||||
|
let playing = false;
|
||||||
|
|
||||||
|
let audioCtx: AudioContext | undefined;
|
||||||
|
let oscillatorL: OscillatorNode | undefined;
|
||||||
|
let oscillatorR: OscillatorNode | undefined;
|
||||||
|
|
||||||
|
onMount(() => {
|
||||||
|
audioCtx = new window.AudioContext();
|
||||||
|
});
|
||||||
|
|
||||||
|
function start(mode: 'inPhase' | 'outOfPhase') {
|
||||||
|
if (!audioCtx) return;
|
||||||
|
oscillatorL?.stop();
|
||||||
|
oscillatorR?.stop();
|
||||||
|
|
||||||
|
oscillatorL = audioCtx.createOscillator();
|
||||||
|
oscillatorR = audioCtx.createOscillator();
|
||||||
|
const gainNode = audioCtx.createGain();
|
||||||
|
|
||||||
|
const stereoPannerL = audioCtx.createStereoPanner();
|
||||||
|
const stereoPannerR = audioCtx.createStereoPanner();
|
||||||
|
|
||||||
|
oscillatorL.frequency.setValueAtTime(frequency, audioCtx.currentTime);
|
||||||
|
oscillatorR.frequency.setValueAtTime(frequency, audioCtx.currentTime);
|
||||||
|
|
||||||
|
stereoPannerL.pan.setValueAtTime(-1, audioCtx.currentTime);
|
||||||
|
stereoPannerR.pan.setValueAtTime(1, audioCtx.currentTime);
|
||||||
|
|
||||||
|
oscillatorL.connect(stereoPannerL).connect(audioCtx.destination);
|
||||||
|
oscillatorR.connect(gainNode).connect(stereoPannerR).connect(audioCtx.destination);
|
||||||
|
|
||||||
|
if (mode === 'inPhase') {
|
||||||
|
gainNode?.gain.setValueAtTime(1, audioCtx.currentTime); // Normal phase
|
||||||
|
} else {
|
||||||
|
gainNode?.gain.setValueAtTime(-1, audioCtx.currentTime); // Invert phase
|
||||||
|
}
|
||||||
|
|
||||||
|
oscillatorL?.start();
|
||||||
|
oscillatorR?.start();
|
||||||
|
playing = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function stop() {
|
||||||
|
oscillatorL?.stop();
|
||||||
|
oscillatorR?.stop();
|
||||||
|
playing = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="test">
|
||||||
|
<label>
|
||||||
|
Frequency <input
|
||||||
|
type="number"
|
||||||
|
bind:value={frequency}
|
||||||
|
min="20"
|
||||||
|
max="20000"
|
||||||
|
disabled={playing}
|
||||||
|
/>Hz
|
||||||
|
</label>
|
||||||
|
<div class="controls">
|
||||||
|
<button on:click={() => start('inPhase')}>In Phase</button>
|
||||||
|
<button on:click={() => start('outOfPhase')}>Out of Phase</button>
|
||||||
|
<button class="stop" on:click={stop} disabled={!playing}>Stop</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.test {
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
margin-top: 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.stop {
|
||||||
|
margin-left: 1em;
|
||||||
|
|
||||||
|
&:not(:disabled) {
|
||||||
|
background: darkred;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 5em;
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in a new issue