Deploy Aether Garden application
Browse files
app.py
CHANGED
|
@@ -1164,37 +1164,126 @@ def build_app() -> gr.Blocks:
|
|
| 1164 |
};
|
| 1165 |
|
| 1166 |
const ensureAmbientMelody = () => {
|
| 1167 |
-
if (window._aetherAmbientStarted)
|
|
|
|
|
|
|
|
|
|
| 1168 |
try {
|
| 1169 |
const AudioCtx = window.AudioContext || window.webkitAudioContext;
|
| 1170 |
if (!AudioCtx) return;
|
| 1171 |
const ctx = new AudioCtx();
|
|
|
|
|
|
|
| 1172 |
const master = ctx.createGain();
|
| 1173 |
-
master.gain.value = 0.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1174 |
master.connect(ctx.destination);
|
| 1175 |
|
| 1176 |
-
const
|
| 1177 |
-
|
|
|
|
|
|
|
|
|
|
| 1178 |
const osc = ctx.createOscillator();
|
| 1179 |
-
const
|
| 1180 |
-
|
|
|
|
|
|
|
|
|
|
| 1181 |
osc.frequency.value = freq;
|
| 1182 |
-
|
| 1183 |
-
|
| 1184 |
-
gain.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1185 |
osc.start();
|
| 1186 |
-
|
| 1187 |
-
|
| 1188 |
-
|
| 1189 |
-
|
| 1190 |
-
|
| 1191 |
-
|
| 1192 |
-
|
|
|
|
| 1193 |
};
|
| 1194 |
-
|
| 1195 |
-
setInterval(
|
| 1196 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1197 |
window._aetherAmbientStarted = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1198 |
} catch (_) {}
|
| 1199 |
};
|
| 1200 |
|
|
@@ -1275,6 +1364,7 @@ def build_app() -> gr.Blocks:
|
|
| 1275 |
gate.classList.remove('is-reclosed', 'is-back-visible', 'is-closing');
|
| 1276 |
gate.classList.add('is-opened', 'is-closed');
|
| 1277 |
playOpeningChime();
|
|
|
|
| 1278 |
};
|
| 1279 |
|
| 1280 |
const goToSpread = (idx, direction = 'next') => {
|
|
@@ -1494,6 +1584,7 @@ def build_app() -> gr.Blocks:
|
|
| 1494 |
|
| 1495 |
const beginUnfold = () => {
|
| 1496 |
playOpeningChime();
|
|
|
|
| 1497 |
gate.classList.add('is-unfolding');
|
| 1498 |
if (book3d) book3d.classList.add('is-opening');
|
| 1499 |
if (openBook) openBook.setAttribute('aria-hidden', 'false');
|
|
|
|
| 1164 |
};
|
| 1165 |
|
| 1166 |
const ensureAmbientMelody = () => {
|
| 1167 |
+
if (window._aetherAmbientStarted) {
|
| 1168 |
+
window._aetherAmbientCtx?.resume?.();
|
| 1169 |
+
return;
|
| 1170 |
+
}
|
| 1171 |
try {
|
| 1172 |
const AudioCtx = window.AudioContext || window.webkitAudioContext;
|
| 1173 |
if (!AudioCtx) return;
|
| 1174 |
const ctx = new AudioCtx();
|
| 1175 |
+
window._aetherAmbientCtx = ctx;
|
| 1176 |
+
|
| 1177 |
const master = ctx.createGain();
|
| 1178 |
+
master.gain.value = 0.0001;
|
| 1179 |
+
|
| 1180 |
+
const warmth = ctx.createBiquadFilter();
|
| 1181 |
+
warmth.type = 'lowpass';
|
| 1182 |
+
warmth.frequency.value = prefersReduced ? 1600 : 2400;
|
| 1183 |
+
warmth.Q.value = 0.5;
|
| 1184 |
+
|
| 1185 |
+
const delay = ctx.createDelay(2.8);
|
| 1186 |
+
delay.delayTime.value = 0.48;
|
| 1187 |
+
const delayFb = ctx.createGain();
|
| 1188 |
+
delayFb.gain.value = 0.26;
|
| 1189 |
+
const delayMix = ctx.createGain();
|
| 1190 |
+
delayMix.gain.value = 0.32;
|
| 1191 |
+
|
| 1192 |
+
warmth.connect(delay);
|
| 1193 |
+
delay.connect(delayFb);
|
| 1194 |
+
delayFb.connect(delay);
|
| 1195 |
+
delay.connect(delayMix);
|
| 1196 |
+
delayMix.connect(master);
|
| 1197 |
+
warmth.connect(master);
|
| 1198 |
master.connect(ctx.destination);
|
| 1199 |
|
| 1200 |
+
const now = ctx.currentTime;
|
| 1201 |
+
master.gain.linearRampToValueAtTime(prefersReduced ? 0.009 : 0.013, now + 5);
|
| 1202 |
+
|
| 1203 |
+
const padNotes = [220, 261.63, 293.66, 329.63, 392, 440];
|
| 1204 |
+
padNotes.forEach((freq, i) => {
|
| 1205 |
const osc = ctx.createOscillator();
|
| 1206 |
+
const osc2 = ctx.createOscillator();
|
| 1207 |
+
const g = ctx.createGain();
|
| 1208 |
+
const g2 = ctx.createGain();
|
| 1209 |
+
osc.type = 'sine';
|
| 1210 |
+
osc2.type = 'triangle';
|
| 1211 |
osc.frequency.value = freq;
|
| 1212 |
+
osc2.frequency.value = freq * 1.0015;
|
| 1213 |
+
const base = 0.0007 / (i * 0.55 + 1);
|
| 1214 |
+
g.gain.value = base;
|
| 1215 |
+
g2.gain.value = base * 0.45;
|
| 1216 |
+
osc.connect(g);
|
| 1217 |
+
osc2.connect(g2);
|
| 1218 |
+
g.connect(warmth);
|
| 1219 |
+
g2.connect(warmth);
|
| 1220 |
osc.start();
|
| 1221 |
+
osc2.start();
|
| 1222 |
+
|
| 1223 |
+
const breathe = () => {
|
| 1224 |
+
const t = ctx.currentTime;
|
| 1225 |
+
g.gain.cancelScheduledValues(t);
|
| 1226 |
+
g.gain.setValueAtTime(g.gain.value, t);
|
| 1227 |
+
g.gain.linearRampToValueAtTime(base * 2.1, t + 4 + i * 0.4);
|
| 1228 |
+
g.gain.linearRampToValueAtTime(base * 0.55, t + 10 + i * 0.35);
|
| 1229 |
};
|
| 1230 |
+
breathe();
|
| 1231 |
+
setInterval(breathe, 9000 + i * 800);
|
| 1232 |
});
|
| 1233 |
+
|
| 1234 |
+
const melodyNotes = [
|
| 1235 |
+
392, 440, 493.88, 523.25, 587.33, 659.25,
|
| 1236 |
+
587.33, 523.25, 440, 392, 329.63, 293.66, 329.63, 392
|
| 1237 |
+
];
|
| 1238 |
+
let noteIdx = 0;
|
| 1239 |
+
const playBell = () => {
|
| 1240 |
+
if (!window._aetherAmbientStarted) return;
|
| 1241 |
+
const freq = melodyNotes[noteIdx % melodyNotes.length];
|
| 1242 |
+
noteIdx += 1;
|
| 1243 |
+
const t = ctx.currentTime;
|
| 1244 |
+
const osc = ctx.createOscillator();
|
| 1245 |
+
const env = ctx.createGain();
|
| 1246 |
+
osc.type = 'sine';
|
| 1247 |
+
osc.frequency.value = freq;
|
| 1248 |
+
env.gain.setValueAtTime(0.0001, t);
|
| 1249 |
+
env.gain.exponentialRampToValueAtTime(0.0065, t + 0.12);
|
| 1250 |
+
env.gain.exponentialRampToValueAtTime(0.0001, t + 3.2);
|
| 1251 |
+
osc.connect(env);
|
| 1252 |
+
env.connect(warmth);
|
| 1253 |
+
osc.start(t);
|
| 1254 |
+
osc.stop(t + 3.4);
|
| 1255 |
+
};
|
| 1256 |
+
|
| 1257 |
+
const scheduleMelody = () => {
|
| 1258 |
+
if (!window._aetherAmbientStarted) return;
|
| 1259 |
+
playBell();
|
| 1260 |
+
setTimeout(scheduleMelody, 2600 + Math.random() * 2400);
|
| 1261 |
+
};
|
| 1262 |
+
setTimeout(scheduleMelody, 1800);
|
| 1263 |
+
|
| 1264 |
+
const shimmer = () => {
|
| 1265 |
+
if (!window._aetherAmbientStarted) return;
|
| 1266 |
+
const t = ctx.currentTime;
|
| 1267 |
+
const osc = ctx.createOscillator();
|
| 1268 |
+
const env = ctx.createGain();
|
| 1269 |
+
osc.type = 'triangle';
|
| 1270 |
+
osc.frequency.value = 880 + Math.random() * 264;
|
| 1271 |
+
env.gain.setValueAtTime(0.0001, t);
|
| 1272 |
+
env.gain.exponentialRampToValueAtTime(0.0028, t + 0.6);
|
| 1273 |
+
env.gain.exponentialRampToValueAtTime(0.0001, t + 5);
|
| 1274 |
+
osc.connect(env);
|
| 1275 |
+
env.connect(warmth);
|
| 1276 |
+
osc.start(t);
|
| 1277 |
+
osc.stop(t + 5.2);
|
| 1278 |
+
setTimeout(shimmer, 14000 + Math.random() * 10000);
|
| 1279 |
+
};
|
| 1280 |
+
setTimeout(shimmer, 6000);
|
| 1281 |
+
|
| 1282 |
window._aetherAmbientStarted = true;
|
| 1283 |
+
|
| 1284 |
+
document.addEventListener('visibilitychange', () => {
|
| 1285 |
+
if (document.visibilityState === 'visible') ctx.resume();
|
| 1286 |
+
}, { passive: true });
|
| 1287 |
} catch (_) {}
|
| 1288 |
};
|
| 1289 |
|
|
|
|
| 1364 |
gate.classList.remove('is-reclosed', 'is-back-visible', 'is-closing');
|
| 1365 |
gate.classList.add('is-opened', 'is-closed');
|
| 1366 |
playOpeningChime();
|
| 1367 |
+
ensureAmbientMelody();
|
| 1368 |
};
|
| 1369 |
|
| 1370 |
const goToSpread = (idx, direction = 'next') => {
|
|
|
|
| 1584 |
|
| 1585 |
const beginUnfold = () => {
|
| 1586 |
playOpeningChime();
|
| 1587 |
+
ensureAmbientMelody();
|
| 1588 |
gate.classList.add('is-unfolding');
|
| 1589 |
if (book3d) book3d.classList.add('is-opening');
|
| 1590 |
if (openBook) openBook.setAttribute('aria-hidden', 'false');
|