Skip to content

Commit 63890e9

Browse files
Retrocausal Update
1 parent 06f14bb commit 63890e9

18 files changed

Lines changed: 8764 additions & 2128 deletions

β€ŽAurora/README.mdβ€Ž

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
## Aurora
2+
3+
[Biodiversity as Infrastructure](https://standardgalactic.github.io/research-projects/Aurora/biodiversity-as-infrastructure.pdf)
4+
5+
[Gesture Before Symbol](https://standardgalactic.github.io/research-projects/Aurora/gesture-before-symbol.pdf)
6+
7+
[Obstruction Cohomology](https://standardgalactic.github.io/research-projects/Aurora/obstruction-cohomology.pdf)
8+
9+
[Recomposable Fragmentation](https://standardgalactic.github.io/research-projects/Aurora/recomposable-fragmentation.pdf)
10+
11+
* [Audio Overviews](https://standardgalactic.github.io/research-projects/Aurora/)
-19.8 KB
Binary file not shown.

β€ŽAurora/The_Physics_of_the_Clip_Economy.txtβ€Ž

Lines changed: 434 additions & 437 deletions
Large diffs are not rendered by default.

β€ŽAurora/The_Physics_of_the_Clip_Economy.vttβ€Ž

Lines changed: 937 additions & 946 deletions
Large diffs are not rendered by default.

β€ŽAurora/index.htmlβ€Ž

Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
cat > index.html << 'EOF'
2+
<!DOCTYPE html>
3+
<html lang="en">
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<title>Aurora Monitor</title>
8+
9+
<style>
10+
:root{ --green:#00ff88; }
11+
12+
html,body{
13+
margin:0;
14+
height:100%;
15+
background:#000;
16+
overflow:hidden;
17+
font-family:monospace;
18+
color:var(--green);
19+
}
20+
21+
body::after{
22+
content:"";
23+
position:fixed;
24+
inset:0;
25+
pointer-events:none;
26+
background:repeating-linear-gradient(
27+
to bottom,
28+
rgba(255,255,255,0.04) 0,
29+
rgba(255,255,255,0.04) 1px,
30+
transparent 2px,
31+
transparent 4px
32+
);
33+
opacity:.15;
34+
}
35+
36+
canvas{
37+
position:fixed;
38+
inset:0;
39+
}
40+
41+
.sub{
42+
position:fixed;
43+
bottom:70px;
44+
left:50%;
45+
transform:translateX(-50%);
46+
width:min(92vw,600px);
47+
text-align:center;
48+
font-size:14px;
49+
line-height:1.5;
50+
white-space:pre-wrap;
51+
padding:0 10px;
52+
text-shadow:0 0 8px var(--green);
53+
}
54+
55+
.selector{
56+
position:fixed;
57+
bottom:10px;
58+
left:50%;
59+
transform:translateX(-50%);
60+
display:flex;
61+
gap:6px;
62+
flex-wrap:wrap;
63+
justify-content:center;
64+
width:min(95vw,700px);
65+
}
66+
67+
button{
68+
background:#000;
69+
color:var(--green);
70+
border:1px solid var(--green);
71+
padding:6px 10px;
72+
font-family:monospace;
73+
cursor:pointer;
74+
font-size:11px;
75+
}
76+
77+
button.active{
78+
background:#022;
79+
}
80+
</style>
81+
</head>
82+
83+
<body>
84+
85+
<canvas id="c"></canvas>
86+
<div class="sub" id="sub"></div>
87+
<div class="selector" id="selector"></div>
88+
89+
<audio id="audio" preload="auto"></audio>
90+
91+
<script>
92+
const TRACKS = [
93+
"The_Physics_of_the_Clip_Economy",
94+
"The_Physics_of_Recomposable_Fragmentation",
95+
"Why_Flat_Roofs_Are_Mathematically_Broken",
96+
"The_Universal_Topology_of_Failure",
97+
"The_secret_geometric_dance_of_typing",
98+
"Your_hands_are_not_typing_symbols"
99+
]
100+
101+
const audio = document.getElementById('audio')
102+
const subEl = document.getElementById('sub')
103+
const selector = document.getElementById('selector')
104+
105+
function getStartIndex(){
106+
const p = new URLSearchParams(location.search).get("track")
107+
if(!p) return 0
108+
if(!isNaN(p)) return (+p) % TRACKS.length
109+
const norm = s => s.toLowerCase().replace(/[_\s]/g,'')
110+
const i = TRACKS.findIndex(t => norm(t).includes(norm(p)))
111+
return i >= 0 ? i : 0
112+
}
113+
114+
let current = getStartIndex()
115+
116+
function loadTrack(i){
117+
current = i
118+
lastText = ""
119+
subEl.textContent = ""
120+
audio.src = TRACKS[i] + ".mp3"
121+
audio.load()
122+
loadVTT(TRACKS[i] + ".vtt")
123+
updateUI()
124+
}
125+
126+
let cues = []
127+
let lastText = ""
128+
129+
async function loadVTT(file){
130+
try{
131+
const r = await fetch(file)
132+
if(!r.ok) throw new Error(r.status + " " + file)
133+
const txt = await r.text()
134+
cues = parseVTT(txt)
135+
console.log("Loaded", cues.length, "cues from", file)
136+
}catch(e){
137+
console.warn("VTT load failed:", e)
138+
cues = []
139+
}
140+
}
141+
142+
function parseVTT(txt){
143+
const lines = txt.split('\n')
144+
const cues = []
145+
let i = 0
146+
147+
while(i < lines.length){
148+
const line = lines[i].trim()
149+
if(line.includes('-->')){
150+
const [start, end] = line.split('-->').map(s => s.trim())
151+
i++
152+
const textLines = []
153+
while(i < lines.length && lines[i].trim()){
154+
textLines.push(lines[i].trim())
155+
i++
156+
}
157+
cues.push({
158+
start: toSec(start),
159+
end: toSec(end),
160+
text: textLines.join('\\n')
161+
})
162+
} else {
163+
i++
164+
}
165+
}
166+
return cues
167+
}
168+
169+
function toSec(t){
170+
const parts = t.split(':').map(Number)
171+
if(parts.length === 3) return parts[0]*3600 + parts[1]*60 + parts[2]
172+
if(parts.length === 2) return parts[0]*60 + parts[1]
173+
return 0
174+
}
175+
176+
audio.ontimeupdate = ()=>{
177+
const t = audio.currentTime
178+
const grace = 0.5
179+
let active = null
180+
181+
for(let i = cues.length - 1; i >= 0; i--){
182+
const c = cues[i]
183+
if(t >= c.start - 0.1){
184+
if(t <= c.end + grace){
185+
active = c
186+
}
187+
break
188+
}
189+
}
190+
191+
if(active){
192+
lastText = active.text
193+
}
194+
195+
subEl.textContent = lastText
196+
}
197+
198+
TRACKS.forEach((t,i)=>{
199+
const b = document.createElement("button")
200+
b.textContent = i+1
201+
b.onclick = e=>{
202+
e.stopPropagation()
203+
loadTrack(i)
204+
audio.play()
205+
}
206+
selector.appendChild(b)
207+
})
208+
209+
function updateUI(){
210+
[...selector.children].forEach((b,i)=>{
211+
b.classList.toggle("active", i===current)
212+
})
213+
}
214+
215+
let ctxA, analyser, buf
216+
217+
function initAudio(){
218+
if(ctxA) return
219+
ctxA = new (window.AudioContext||window.webkitAudioContext)()
220+
analyser = ctxA.createAnalyser()
221+
analyser.fftSize = 1024
222+
buf = new Uint8Array(analyser.fftSize)
223+
const src = ctxA.createMediaElementSource(audio)
224+
src.connect(analyser)
225+
analyser.connect(ctxA.destination)
226+
}
227+
228+
document.body.onclick = async ()=>{
229+
initAudio()
230+
if(ctxA.state !== "running"){
231+
await ctxA.resume()
232+
}
233+
if(audio.paused){
234+
await audio.play()
235+
} else {
236+
audio.pause()
237+
}
238+
}
239+
240+
audio.onended = ()=>{
241+
loadTrack((current+1)%TRACKS.length)
242+
audio.play()
243+
}
244+
245+
const c = document.getElementById('c')
246+
const g = c.getContext('2d')
247+
248+
let w,h,cx,cy
249+
250+
function resize(){
251+
w=c.width=innerWidth
252+
h=c.height=innerHeight
253+
cx=w/2; cy=h/2
254+
}
255+
resize()
256+
addEventListener('resize',resize)
257+
258+
function draw(){
259+
g.fillStyle='rgba(0,0,0,0.12)'
260+
g.fillRect(0,0,w,h)
261+
262+
const R = Math.min(w,h)*0.4
263+
264+
g.save()
265+
g.beginPath()
266+
g.arc(cx,cy,R,0,Math.PI*2)
267+
g.clip()
268+
269+
if(analyser){
270+
analyser.getByteTimeDomainData(buf)
271+
const len=buf.length
272+
const lag=25
273+
274+
g.beginPath()
275+
for(let i=0;i<len;i++){
276+
const a=(buf[i]-128)/128
277+
const b=(buf[(i+lag)%len]-128)/128
278+
const t=i/len*Math.PI*2
279+
280+
const x = cx + Math.sin(t*2)*a*R*0.7
281+
const y = cy + Math.sin(t*3)*b*R*0.7
282+
283+
i?g.lineTo(x,y):g.moveTo(x,y)
284+
}
285+
286+
g.strokeStyle='#00ff88'
287+
g.shadowColor='#00ff88'
288+
g.shadowBlur=12
289+
g.stroke()
290+
g.shadowBlur=0
291+
}
292+
293+
g.restore()
294+
295+
g.beginPath()
296+
g.arc(cx,cy,R,0,Math.PI*2)
297+
g.strokeStyle='rgba(0,255,136,0.7)'
298+
g.lineWidth=2
299+
g.stroke()
300+
301+
requestAnimationFrame(draw)
302+
}
303+
304+
draw()
305+
loadTrack(current)
306+
</script>
307+
308+
</body>
309+
</html>

0 commit comments

Comments
Β (0)