Add Ethan

This commit is contained in:
Shav Kinderlehrer 2024-03-25 02:28:31 -04:00
parent 3de767b0cd
commit 78822334d9
27 changed files with 219 additions and 0 deletions

27
flake.lock Normal file
View File

@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1711163522,
"narHash": "sha256-YN/Ciidm+A0fmJPWlHBGvVkcarYWSC+s3NTPk/P+q3c=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "44d0940ea560dee511026a53f0e2e2cde489b4d4",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

27
flake.nix Normal file
View File

@ -0,0 +1,27 @@
{
description = "Cool people homepage";
inputs = {
nixpkgs.url = "github:nixos/nixpkgs?ref=nixos-unstable";
};
outputs = { self, nixpkgs }:
let
system = "aarch64-darwin";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default =
pkgs.mkShell {
buildInputs = with pkgs; [
yarn
nodePackages.svelte-language-server
nodePackages.typescript-language-server
nodePackages.vscode-css-languageserver-bin
tree
];
shellHook = ''
exec zsh
'';
};
};
}

View File

@ -20,6 +20,7 @@
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"metaphone-ts": "^1.0.1",
"pokedex-api": "^1.1.2" "pokedex-api": "^1.1.2"
} }
} }

View File

@ -6,6 +6,7 @@
"liv", "liv",
"nis", "nis",
"gremlin", "gremlin",
"ethan"
]; ];
</script> </script>

View File

@ -0,0 +1,158 @@
<script lang="ts">
import CountDownTimer from "$lib/elem/CountDownTimer.svelte";
import { metaphone } from "metaphone-ts";
let sounds = [
"B",
"X",
"S",
"K",
"J",
"T",
"F",
"H",
"L",
"M",
"N",
"P",
"R",
"0",
"W",
"Y",
];
let custom_message = "";
let message =
"Happy birthday Ethan! You are easily one of the closest friends I've ever had, and it's not even close. I've never met someone who's so willing to be goofy and crazy with me, but also has the capacity to be so serious when needed. I appreciate you as a friend as also just as a human on this planet. You make a difference in my life, so I'm sure you do for other people as well.";
let played_words: string[] = [];
let playing = false;
let playing_message = "";
let stop = false;
async function playAudio(message: string) {
playing_message = message;
playing = true;
played_words = [];
let words = message.split(" ");
for (const word of words) {
played_words.push(word);
played_words = played_words;
let phonemes = metaphone(word);
for (const phoneme of phonemes) {
let audio = document.querySelector(`#audio-${phoneme}`);
if (audio) {
audio.play();
await new Promise((r) => setTimeout(r, audio.duration * 1000 - 100));
}
if (stop) {
playing = false;
stop = false;
return;
}
}
await new Promise((r) => setTimeout(r, Math.min(word.length * 50, 300)));
}
playing = false;
}
</script>
<main>
<div id="content">
<div id="audio">
{#each sounds as sound}
<audio id="audio-{sound}" src="/ethan/{sound}.mp3"></audio>
{/each}
</div>
<div id="message">
<h1>Hi Ethan!</h1>
<p>
Do you remember that one time I was working on a procedural voices
algorithm for a game project? Well, the game isn't finished and neither
is the voice algorithm but ¯\_(ツ)_/¯.
</p>
<p>
Anyways, you helped me create a voice using your samples, so I thought
it would be fun to steal those and make you read your birthday message
to yourself!
</p>
</div>
<div id="automessage">
<button disabled={playing} on:click={() => playAudio(message)}
>Play</button
>
<button
disabled={!playing}
on:click={() => {
stop = true;
}}>Stop</button
>
<p>
{#each message.split(" ") as word, i}
{#if played_words.length >= i + 1 && playing_message == message}
<span class="played">
{word + " "}
</span>
{:else}
{word + " "}
{/if}
{/each}
</p>
</div>
<h2>Write your own message if you want!</h2>
<div id="custommessage">
<form
on:submit|preventDefault={() => {
playAudio(custom_message);
}}
>
<input placeholder="custom mesage.." bind:value={custom_message} />
<button disabled={playing}>Play</button>
<button
type="button"
disabled={!playing}
on:click={() => {
stop = true;
}}>Stop</button
>
</form>
<p>
{#each custom_message.split(" ") as word, i}
{#if played_words.length >= i + 1 && playing_message == custom_message}
<span class="played">
{word + " "}
</span>
{:else}
{word + " "}
{/if}
{/each}
</p>
</div>
<CountDownTimer birthday={"Mar 25"} />
</div>
</main>
<style>
@import url("https://fonts.googleapis.com/css2?family=Fira+Sans:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
main {
font-family: "Fira Sans", sans-serif;
font-weight: 400;
font-style: normal;
display: flex;
justify-content: center;
}
#content {
max-width: 40em;
}
.played {
color: cyan;
}
</style>

BIN
static/ethan/0.mp3 Normal file

Binary file not shown.

BIN
static/ethan/A.mp3 Normal file

Binary file not shown.

BIN
static/ethan/B.mp3 Normal file

Binary file not shown.

BIN
static/ethan/E.mp3 Normal file

Binary file not shown.

BIN
static/ethan/F.mp3 Normal file

Binary file not shown.

BIN
static/ethan/H.mp3 Normal file

Binary file not shown.

BIN
static/ethan/I.mp3 Normal file

Binary file not shown.

BIN
static/ethan/J.mp3 Normal file

Binary file not shown.

BIN
static/ethan/K.mp3 Normal file

Binary file not shown.

BIN
static/ethan/L.mp3 Normal file

Binary file not shown.

BIN
static/ethan/M.mp3 Normal file

Binary file not shown.

BIN
static/ethan/N.mp3 Normal file

Binary file not shown.

BIN
static/ethan/O.mp3 Normal file

Binary file not shown.

BIN
static/ethan/P.mp3 Normal file

Binary file not shown.

BIN
static/ethan/R.mp3 Normal file

Binary file not shown.

BIN
static/ethan/S.mp3 Normal file

Binary file not shown.

BIN
static/ethan/T.mp3 Normal file

Binary file not shown.

BIN
static/ethan/U.mp3 Normal file

Binary file not shown.

BIN
static/ethan/W.mp3 Normal file

Binary file not shown.

BIN
static/ethan/X.mp3 Normal file

Binary file not shown.

BIN
static/ethan/Y.mp3 Normal file

Binary file not shown.

View File

@ -639,6 +639,11 @@ merge2@^1.3.0:
resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae"
integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==
metaphone-ts@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/metaphone-ts/-/metaphone-ts-1.0.1.tgz#d3a9abbbbdb363bf82dcc755de7467352a8889f2"
integrity sha512-98u3uoBxvsvRdxo4jE50evb0w4qDDU56pQHJnx8pT6UMwQdYlsekTUtbcJTppk38Nbe+I53eQsELIEbV9VRgXg==
micromatch@^4.0.4: micromatch@^4.0.4:
version "4.0.5" version "4.0.5"
resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6"