push
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@ -22,3 +22,8 @@ dist-ssr
|
|||||||
*.njsproj
|
*.njsproj
|
||||||
*.sln
|
*.sln
|
||||||
*.sw?
|
*.sw?
|
||||||
|
|
||||||
|
# Claude artifacts
|
||||||
|
.claude/
|
||||||
|
.clinerules
|
||||||
|
CLAUDE.md
|
||||||
|
|||||||
@ -4,9 +4,9 @@
|
|||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
<meta name="description" content="Audio sample generator" />
|
<meta name="description" content="Poof: a sample generator" />
|
||||||
<meta name="theme-color" content="#000000" />
|
<meta name="theme-color" content="#000000" />
|
||||||
<title>Vending Machine</title>
|
<title>Poof</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"name": "vendingmachine",
|
"name": "poof",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.0.0",
|
"version": "0.0.0",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
|
|||||||
@ -1,4 +1,7 @@
|
|||||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
||||||
<rect width="32" height="32" fill="#000"/>
|
<rect width="32" height="32" fill="#000"/>
|
||||||
<text x="16" y="21" font-family="monospace" font-size="18" fill="#fff" text-anchor="middle" font-weight="bold">VM</text>
|
<circle cx="16" cy="16" r="8" fill="none" stroke="#fff" stroke-width="1.5"/>
|
||||||
|
<circle cx="16" cy="16" r="4" fill="none" stroke="#fff" stroke-width="1"/>
|
||||||
|
<path d="M16 4 L16 8 M28 16 L24 16 M16 28 L16 24 M4 16 L8 16" stroke="#fff" stroke-width="1.5" stroke-linecap="square"/>
|
||||||
|
<path d="M23 9 L20.5 11.5 M23 23 L20.5 20.5 M9 23 L11.5 20.5 M9 9 L11.5 11.5" stroke="#fff" stroke-width="1" stroke-linecap="square"/>
|
||||||
</svg>
|
</svg>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 236 B After Width: | Height: | Size: 529 B |
@ -908,7 +908,7 @@ export class Benjolin implements SynthEngine<BenjolinParams> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Correlate cross-mod amounts
|
// Correlate cross-mod amounts
|
||||||
const crossModDelta = (Math.random() - 0.5) * mutationAmount;
|
const crossModDelta = (Math.random() - 0.5) * mutAmount;
|
||||||
mutated.crossMod1to2 = Math.max(0, Math.min(1, mutated.crossMod1to2 + crossModDelta));
|
mutated.crossMod1to2 = Math.max(0, Math.min(1, mutated.crossMod1to2 + crossModDelta));
|
||||||
mutated.crossMod2to1 = Math.max(0, Math.min(1, mutated.crossMod2to1 + crossModDelta * 0.7));
|
mutated.crossMod2to1 = Math.max(0, Math.min(1, mutated.crossMod2to1 + crossModDelta * 0.7));
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { SynthEngine } from './SynthEngine';
|
import type { SynthEngine, PitchLock } from './SynthEngine';
|
||||||
|
|
||||||
interface InputParams {
|
interface InputParams {
|
||||||
recorded: boolean;
|
recorded: boolean;
|
||||||
@ -110,11 +110,11 @@ export class Input implements SynthEngine<InputParams> {
|
|||||||
return [leftResampled, rightResampled];
|
return [leftResampled, rightResampled];
|
||||||
}
|
}
|
||||||
|
|
||||||
randomParams(): InputParams {
|
randomParams(_pitchLock?: PitchLock): InputParams {
|
||||||
return { recorded: this.leftChannel !== null && this.rightChannel !== null };
|
return { recorded: this.leftChannel !== null && this.rightChannel !== null };
|
||||||
}
|
}
|
||||||
|
|
||||||
mutateParams(params: InputParams): InputParams {
|
mutateParams(params: InputParams, _mutationAmount?: number, _pitchLock?: PitchLock): InputParams {
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import type { SynthEngine } from './SynthEngine';
|
import type { SynthEngine, PitchLock } from './SynthEngine';
|
||||||
|
|
||||||
interface SampleParams {
|
interface SampleParams {
|
||||||
loaded: boolean;
|
loaded: boolean;
|
||||||
@ -66,11 +66,11 @@ export class Sample implements SynthEngine<SampleParams> {
|
|||||||
return [leftResampled, rightResampled];
|
return [leftResampled, rightResampled];
|
||||||
}
|
}
|
||||||
|
|
||||||
randomParams(): SampleParams {
|
randomParams(_pitchLock?: PitchLock): SampleParams {
|
||||||
return { loaded: this.leftChannel !== null && this.rightChannel !== null };
|
return { loaded: this.leftChannel !== null && this.rightChannel !== null };
|
||||||
}
|
}
|
||||||
|
|
||||||
mutateParams(params: SampleParams): SampleParams {
|
mutateParams(params: SampleParams, _mutationAmount?: number, _pitchLock?: PitchLock): SampleParams {
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -102,7 +102,7 @@ export class WavetableEngine implements SynthEngine<WavetableParams> {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const results = await Promise.all(loadPromises);
|
const results = await Promise.all(loadPromises);
|
||||||
const loaded = results.filter((wt): wt is Wavetable => wt !== null);
|
const loaded = results.filter((wt) => wt !== null) as Wavetable[];
|
||||||
|
|
||||||
if (loaded.length > 0) {
|
if (loaded.length > 0) {
|
||||||
this.wavetables = loaded;
|
this.wavetables = loaded;
|
||||||
|
|||||||
@ -21,11 +21,23 @@
|
|||||||
onclick={(e) => e.stopPropagation()}
|
onclick={(e) => e.stopPropagation()}
|
||||||
onkeydown={(e) => e.stopPropagation()}
|
onkeydown={(e) => e.stopPropagation()}
|
||||||
>
|
>
|
||||||
<h1 id="modal-title">Vending Machine</h1>
|
<h1 id="modal-title">Poof: a sample generator</h1>
|
||||||
<p class="description">
|
<p class="description">
|
||||||
Oh, looks like you found a sound vending machine. This one seems slightly
|
Do you need to generate audio samples for your projects? Poof, it's
|
||||||
broken and it seems that you can get sounds for free... Have fun!
|
already done! These are not the best samples you'll ever hear, but they
|
||||||
|
have the right to exist, nonetheless, in the realm of all the random and
|
||||||
|
haphazardly generated digital sounds. Have fun, give computers some love!
|
||||||
</p>
|
</p>
|
||||||
|
<ul>
|
||||||
|
<li class="description">
|
||||||
|
Generate audio samples using various audio synthesis generators. Random
|
||||||
|
parameters.
|
||||||
|
</li>
|
||||||
|
<li class="description">
|
||||||
|
Process each sound with with a growing collection of random effects.
|
||||||
|
</li>
|
||||||
|
<li class="description">Export your samples as WAV files.</li>
|
||||||
|
</ul>
|
||||||
<div class="modal-links">
|
<div class="modal-links">
|
||||||
<p>
|
<p>
|
||||||
Created by <a
|
Created by <a
|
||||||
@ -53,107 +65,197 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
background-color: rgba(0, 0, 0, 0.9);
|
||||||
|
backdrop-filter: blur(4px);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
z-index: 2000;
|
z-index: 2000;
|
||||||
|
animation: fadeIn 0.2s ease-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fadeIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes slideIn {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
transform: translateY(-20px);
|
||||||
|
}
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateY(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background-color: #000;
|
background-color: #000;
|
||||||
border: 2px solid #fff;
|
border: 2px solid #fff;
|
||||||
padding: 1.5rem;
|
padding: 1.25rem;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
width: 90%;
|
width: calc(100% - 2rem);
|
||||||
color: #fff;
|
color: #fff;
|
||||||
max-height: 90vh;
|
max-height: 90vh;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
animation: slideIn 0.3s ease-out;
|
||||||
|
box-shadow: 0 8px 32px rgba(255, 255, 255, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content h1 {
|
.modal-content h1 {
|
||||||
margin: 0 0 0.75rem 0;
|
margin: 0 0 0.5rem 0;
|
||||||
font-size: 1.5rem;
|
font-size: 1.75rem;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
letter-spacing: 0.02em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content .description {
|
.modal-content .description {
|
||||||
margin: 0 0 1rem 0;
|
margin: 0 0 1rem 0;
|
||||||
line-height: 1.5;
|
line-height: 1.6;
|
||||||
color: #ccc;
|
color: #e0e0e0;
|
||||||
font-size: 0.9rem;
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content ul {
|
||||||
|
margin: 0 0 1rem 0;
|
||||||
|
padding-left: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content ul li {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content ul li:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-links {
|
.modal-links {
|
||||||
margin: 1rem 0;
|
margin: 1.25rem 0;
|
||||||
padding: 0.75rem 0;
|
padding: 0.875rem 0;
|
||||||
border-top: 1px solid #333;
|
border-top: 1px solid #444;
|
||||||
border-bottom: 1px solid #333;
|
border-bottom: 1px solid #444;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-links p {
|
.modal-links p {
|
||||||
margin: 0.4rem 0;
|
margin: 0.375rem 0;
|
||||||
font-size: 0.85rem;
|
font-size: 0.8125rem;
|
||||||
color: #ccc;
|
color: #bbb;
|
||||||
line-height: 1.4;
|
line-height: 1.5;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-links a {
|
.modal-links a {
|
||||||
color: #646cff;
|
color: #646cff;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
|
transition: color 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-links a:hover {
|
.modal-links a:hover {
|
||||||
|
color: #8891ff;
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close {
|
.modal-close {
|
||||||
margin-top: 0.75rem;
|
margin-top: 1rem;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: 0.65rem;
|
padding: 0.75rem;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
color: #000;
|
color: #000;
|
||||||
border: none;
|
border: 2px solid #fff;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close:hover {
|
.modal-close:hover {
|
||||||
background-color: #ddd;
|
background-color: #000;
|
||||||
|
color: #fff;
|
||||||
|
transform: translateY(-1px);
|
||||||
|
box-shadow: 0 4px 12px rgba(255, 255, 255, 0.2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 768px) {
|
.modal-close:active {
|
||||||
|
transform: translateY(0);
|
||||||
|
box-shadow: 0 2px 6px rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 480px) {
|
||||||
.modal-content {
|
.modal-content {
|
||||||
padding: 2rem;
|
padding: 1.75rem;
|
||||||
|
width: calc(100% - 3rem);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content h1 {
|
.modal-content h1 {
|
||||||
font-size: 2rem;
|
font-size: 2rem;
|
||||||
|
margin: 0 0 0.75rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content .description {
|
||||||
|
font-size: 0.9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-links p {
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
.modal-content {
|
||||||
|
padding: 2.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
margin: 0 0 1rem 0;
|
margin: 0 0 1rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-content .description {
|
.modal-content .description {
|
||||||
margin: 0 0 1.5rem 0;
|
margin: 0 0 1.25rem 0;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
line-height: 1.6;
|
line-height: 1.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content ul {
|
||||||
|
margin: 0 0 1.25rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-links {
|
.modal-links {
|
||||||
margin: 1.5rem 0;
|
margin: 1.75rem 0;
|
||||||
padding: 1rem 0;
|
padding: 1.125rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-links p {
|
.modal-links p {
|
||||||
font-size: 0.9rem;
|
font-size: 0.9375rem;
|
||||||
margin: 0.5rem 0;
|
margin: 0.5rem 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-close {
|
.modal-close {
|
||||||
margin-top: 1rem;
|
margin-top: 1.25rem;
|
||||||
padding: 0.75rem;
|
padding: 0.875rem;
|
||||||
font-size: 1.1rem;
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (prefers-reduced-motion: reduce) {
|
||||||
|
.modal-overlay,
|
||||||
|
.modal-content {
|
||||||
|
animation: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-close {
|
||||||
|
transition: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-links a {
|
||||||
|
transition: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
Reference in New Issue
Block a user