Compare commits
4 commits
fd25154725
...
a75d3b0175
Author | SHA1 | Date | |
---|---|---|---|
a75d3b0175 | |||
40270c7f32 | |||
cfe22d204b | |||
7e29468247 |
14 changed files with 217 additions and 123 deletions
|
@ -21,7 +21,7 @@ a {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
h1, h2, h3 {
|
h1, h2, h3, h4 {
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
$: onlyCard = $page.url.pathname === '/card';
|
$: onlyCard = $page.data.card;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<TestCard full={onlyCard} on:focus={() => goto('/card')} />
|
<TestCard full={onlyCard} on:focus={() => goto('/card')} />
|
||||||
<main class:content={!onlyCard} class:sub={$page.url.pathname !== '/' && !onlyCard}>
|
<main class:content={!onlyCard} class:sub={!$page.data.root && !onlyCard}>
|
||||||
<a href=".." class="button button-back"><i class="ti ti-arrow-back" />Back</a>
|
<a href=".." class="button button-back"><i class="ti ti-arrow-back" />Back</a>
|
||||||
<slot />
|
<slot />
|
||||||
</main>
|
</main>
|
||||||
|
|
7
src/routes/+page.ts
Normal file
7
src/routes/+page.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type { PageLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageLoad = () => {
|
||||||
|
return {
|
||||||
|
root: true
|
||||||
|
}
|
||||||
|
}
|
51
src/routes/audio/(channels)/+layout.svelte
Normal file
51
src/routes/audio/(channels)/+layout.svelte
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import CycleButton from './cycle-button.svelte';
|
||||||
|
|
||||||
|
let channelsEl: HTMLDivElement;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="channels" bind:this={channelsEl}>
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
<div class="controls">
|
||||||
|
<CycleButton element={channelsEl} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.channels {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
justify-content: space-evenly;
|
||||||
|
font-size: 2rem;
|
||||||
|
flex-grow: 1;
|
||||||
|
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.channels .row) {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.controls {
|
||||||
|
text-align: center;
|
||||||
|
margin: 2rem 0;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.channels .center) {
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
:global(.channels .label) {
|
||||||
|
opacity: 0.2;
|
||||||
|
font-size: 6rem;
|
||||||
|
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
</style>
|
53
src/routes/audio/(channels)/cycle-button.svelte
Normal file
53
src/routes/audio/(channels)/cycle-button.svelte
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import { onDestroy } from 'svelte';
|
||||||
|
|
||||||
|
export let element: HTMLElement;
|
||||||
|
|
||||||
|
let cycling = false;
|
||||||
|
let currentChannel: HTMLAudioElement | undefined;
|
||||||
|
async function cycleChannels() {
|
||||||
|
cycling = true;
|
||||||
|
const buttons = element.querySelectorAll('button');
|
||||||
|
buttons.forEach((button) => (button.disabled = true));
|
||||||
|
const channels = element.querySelectorAll('audio');
|
||||||
|
while (cycling) {
|
||||||
|
for (const channel of channels) {
|
||||||
|
currentChannel = channel;
|
||||||
|
await channel.play();
|
||||||
|
await new Promise((resolve) => {
|
||||||
|
channel.onended = resolve;
|
||||||
|
});
|
||||||
|
if (!cycling) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buttons.forEach((button) => (button.disabled = false));
|
||||||
|
}
|
||||||
|
|
||||||
|
function onClick() {
|
||||||
|
cycling = !cycling;
|
||||||
|
if (cycling) {
|
||||||
|
cycleChannels();
|
||||||
|
} else {
|
||||||
|
if (currentChannel) {
|
||||||
|
currentChannel.pause();
|
||||||
|
currentChannel.currentTime = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
cycling = false;
|
||||||
|
currentChannel?.pause();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button on:click={onClick}>
|
||||||
|
<i class="ti ti-refresh"></i>
|
||||||
|
{#if cycling}
|
||||||
|
Stop Cycling
|
||||||
|
{:else}
|
||||||
|
Cycle through
|
||||||
|
{/if}
|
||||||
|
</button>
|
|
@ -1,12 +1,10 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { createEventDispatcher, onMount } from 'svelte';
|
|
||||||
const dispatch = createEventDispatcher<{ end: void }>();
|
|
||||||
|
|
||||||
export let src: string;
|
export let src: string;
|
||||||
export let left = false;
|
export let left = false;
|
||||||
export let center = false;
|
export let center = false;
|
||||||
export let right = false;
|
export let right = false;
|
||||||
export let lfe = false;
|
export let lfe = false;
|
||||||
|
export let inline = false;
|
||||||
|
|
||||||
let currentTime = 0;
|
let currentTime = 0;
|
||||||
let paused = true;
|
let paused = true;
|
||||||
|
@ -22,6 +20,7 @@
|
||||||
class:right
|
class:right
|
||||||
class:center
|
class:center
|
||||||
class:lfe
|
class:lfe
|
||||||
|
class:inline
|
||||||
class:playing={!paused}
|
class:playing={!paused}
|
||||||
on:click={play}
|
on:click={play}
|
||||||
>
|
>
|
||||||
|
@ -30,7 +29,7 @@
|
||||||
{:else}
|
{:else}
|
||||||
<i class="ti ti-wave-sine"></i>
|
<i class="ti ti-wave-sine"></i>
|
||||||
{/if}
|
{/if}
|
||||||
<label><slot /></label>
|
<span><slot /></span>
|
||||||
<audio bind:currentTime bind:paused {src}></audio>
|
<audio bind:currentTime bind:paused {src}></audio>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
@ -43,6 +42,8 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
|
||||||
|
opacity: 0.8;
|
||||||
|
|
||||||
& .ti {
|
& .ti {
|
||||||
font-size: 3em;
|
font-size: 3em;
|
||||||
}
|
}
|
||||||
|
@ -58,11 +59,39 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
opacity: 0.33;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.playing {
|
&.playing {
|
||||||
opacity: 0.66;
|
transform: scale(1.1);
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
transition:
|
||||||
|
transform 0.2s ease,
|
||||||
|
opacity 0.2s ease;
|
||||||
|
|
||||||
|
&.inline {
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
background: black;
|
||||||
|
border: 1px solid white;
|
||||||
|
|
||||||
|
opacity: 1;
|
||||||
|
|
||||||
|
& .ti {
|
||||||
|
font-size: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.playing {
|
||||||
|
transform: scale(1);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:active {
|
||||||
|
transform: scale(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
34
src/routes/audio/(channels)/stereo-test.svelte
Normal file
34
src/routes/audio/(channels)/stereo-test.svelte
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import leftUrl from '@assets/audio/stereo/Left.mp3';
|
||||||
|
import centerUrl from '@assets/audio/stereo/Center.mp3';
|
||||||
|
import rightUrl from '@assets/audio/stereo/Right.mp3';
|
||||||
|
import Speaker from './speaker.svelte';
|
||||||
|
import CycleButton from './cycle-button.svelte';
|
||||||
|
|
||||||
|
let speakersEl: HTMLElement;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="test">
|
||||||
|
<div class="speakers" bind:this={speakersEl}>
|
||||||
|
<Speaker src={leftUrl} left inline>Left</Speaker>
|
||||||
|
<Speaker src={centerUrl} center inline>Center</Speaker>
|
||||||
|
<Speaker src={rightUrl} right inline>Right</Speaker>
|
||||||
|
</div>
|
||||||
|
<CycleButton element={speakersEl} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.test {
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
align-items: center;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.speakers {
|
||||||
|
display: flex;
|
||||||
|
gap: 1em;
|
||||||
|
font-size: 1.25em;
|
||||||
|
margin-right: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -1,20 +1,37 @@
|
||||||
|
<script lang="ts">
|
||||||
|
import StereoTest from './(channels)/stereo-test.svelte';
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<article>
|
||||||
<h3>Channel tests</h3>
|
<h3>Channel tests</h3>
|
||||||
|
<h4>Stereo</h4>
|
||||||
|
<section>
|
||||||
|
<StereoTest />
|
||||||
|
</section>
|
||||||
|
<h4>Surround audio</h4>
|
||||||
|
<section>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="channels/stereo">Stereo</a></li>
|
<li><a class="button" href="channels-5.1">5.1 Surround</a></li>
|
||||||
<li><a href="channels/5.1">5.1 Surround</a></li>
|
<li><a class="button" href="channels-7.1">7.1 Surround</a></li>
|
||||||
<li><a href="channels/7.1">7.1 Surround</a></li>
|
|
||||||
</ul>
|
</ul>
|
||||||
|
</section>
|
||||||
|
</article>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
h4 {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
ul {
|
ul {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
|
||||||
display: flex;
|
display: inline-flex;
|
||||||
gap: 1rem;
|
gap: 1em;
|
||||||
}
|
}
|
||||||
li {
|
|
||||||
margin-bottom: 10px;
|
section {
|
||||||
|
margin: 1em 0;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -1,82 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { onDestroy } from 'svelte';
|
|
||||||
|
|
||||||
let channelsEl: HTMLDivElement;
|
|
||||||
|
|
||||||
let cycling = false;
|
|
||||||
async function cycleChannels() {
|
|
||||||
cycling = true;
|
|
||||||
const buttons = channelsEl.querySelectorAll('button');
|
|
||||||
buttons.forEach((button) => (button.disabled = true));
|
|
||||||
const channels = channelsEl.querySelectorAll('audio');
|
|
||||||
while (cycling) {
|
|
||||||
for (const channel of channels) {
|
|
||||||
await channel.play();
|
|
||||||
await new Promise((resolve) => {
|
|
||||||
channel.onended = resolve;
|
|
||||||
});
|
|
||||||
if (!cycling) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buttons.forEach((button) => (button.disabled = false));
|
|
||||||
}
|
|
||||||
|
|
||||||
function startCycle() {
|
|
||||||
cycling = !cycling;
|
|
||||||
if (cycling) {
|
|
||||||
cycleChannels();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onDestroy(() => {
|
|
||||||
cycling = false;
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="channels" bind:this={channelsEl}>
|
|
||||||
<slot />
|
|
||||||
</div>
|
|
||||||
<div class="controls">
|
|
||||||
<button on:click={startCycle}>Cycle all</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style>
|
|
||||||
.channels {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: space-evenly;
|
|
||||||
font-size: 2rem;
|
|
||||||
flex-grow: 1;
|
|
||||||
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.channels .row) {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.controls {
|
|
||||||
text-align: center;
|
|
||||||
margin: 2rem 0;
|
|
||||||
font-size: 1.5rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.channels .center) {
|
|
||||||
font-size: 0.9em;
|
|
||||||
}
|
|
||||||
|
|
||||||
:global(.channels .label) {
|
|
||||||
opacity: 0.2;
|
|
||||||
font-size: 6rem;
|
|
||||||
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
|
|
||||||
pointer-events: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
|
@ -1,8 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import { onMount } from 'svelte';
|
|
||||||
import { goto } from '$app/navigation';
|
|
||||||
|
|
||||||
onMount(() => {
|
|
||||||
goto('..');
|
|
||||||
});
|
|
||||||
</script>
|
|
|
@ -1,14 +0,0 @@
|
||||||
<script lang="ts">
|
|
||||||
import Speaker from '../speaker.svelte';
|
|
||||||
import leftUrl from '@assets/audio/stereo/Left.mp3';
|
|
||||||
import centerUrl from '@assets/audio/stereo/Center.mp3';
|
|
||||||
import rightUrl from '@assets/audio/stereo/Right.mp3';
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="row">
|
|
||||||
<Speaker src={leftUrl} left>Left</Speaker>
|
|
||||||
<div class="center">
|
|
||||||
<Speaker src={centerUrl} center>Center</Speaker>
|
|
||||||
</div>
|
|
||||||
<Speaker src={rightUrl} right>Right</Speaker>
|
|
||||||
</div>
|
|
7
src/routes/card/+page.ts
Normal file
7
src/routes/card/+page.ts
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
import type { PageLoad } from './$types';
|
||||||
|
|
||||||
|
export const load: PageLoad = () => {
|
||||||
|
return {
|
||||||
|
card: true
|
||||||
|
};
|
||||||
|
};
|
Loading…
Reference in a new issue