first commit

This commit is contained in:
Görkem 2025-04-28 17:42:55 -07:00
parent 5471adc825
commit b2597e1e2a
8 changed files with 1114 additions and 0 deletions

BIN
AurebeshAF-CanonTech.otf Normal file

Binary file not shown.

57
index.html Normal file
View File

@ -0,0 +1,57 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My Website</title>
<link rel="stylesheet" href="./style.css">
<link rel="icon" href="./favicon.ico" type="image/x-icon">
</head>
<body>
<div class="UIbody">
<div class="topBar">
<canvas id="canvas"></canvas>
<div id="grid" class="grid">
<div><p>1</p></div>
<div><p>2</p></div>
<div><p>3</p></div>
<div><p>4</p></div>
<div><p>5</p></div>
<div><p>6</p></div>
<div><p>7</p></div>
<div><p>8</p></div>
<div><p>9</p></div>
</div>
<div id="safeArea" class="safeArea">
<div class="speechtext">
<span id="element"></span>
<!-- Remember that the frontier of the rebellion is everywhere -->
</div>
<div class="recordingNo">7</div>
</div>
</div>
<script>
</script>
</body>
<!-- <audio id="option1" src="./option1.mp3"></audio> -->
<div id="menuButtons" class="menuButtons">
<div id="button1" class="element active" href="recording1.html">option1</div>
<br>
<div id="button2" class="element" href="test2.html">Option 2</div>
<br>
<div id="button3" class="element" href="test2.html">Option 3</div>
</div>
</div>
<script src="main.js"></script>
</body>
</html>

204
main.js Normal file
View File

@ -0,0 +1,204 @@
// var elements = document.querySelectorAll('.element');
// document.addEventListener('keydown', handler(elements.length - 1), false);
// elements[0].classList.add('active');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
fitToContainer(canvas);
let wordsQueue = [];
let startTime = 0;
function fitToContainer(canvas){
// Make it visually fill the positioned parent
canvas.style.width ='100%';
canvas.style.height='100%';
// ...then set the internal size to match
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
canvas.style.display = "none"
document.addEventListener('keydown', function(event) {
// First, remove "active" from all buttons
// Now check which key was pressed and add "active" accordingly
if (event.key === 'a' || event.key === 'A') {
resetActive()
document.getElementById('button1').classList.add('active');
} else if (event.key === 's' || event.key === 'S') {
resetActive()
document.getElementById('button2').classList.add('active');
} else if (event.key === 'd' || event.key === 'D') {
resetActive()
document.getElementById('button3').classList.add('active');
}
else if (event.key === 'Enter') {
playAudio(document.querySelector('.menuButtons .element.active').innerHTML);
}
});
function resetActive(){
document.querySelectorAll('.menuButtons .element').forEach(button => {
button.classList.remove('active');
});
}
function playAudio(filename){
canvas.style.display = "block"
document.getElementById('safeArea').style.display = "flex";
document.getElementById('grid').style.display = "none";
document.getElementById('menuButtons').style.display = "none";
let audioContext;
let analyser;
let source;
let dataArray;
let bufferLength;
const TOTAL_BARS = 44 ; // Only 44 bars now
const BARS_AREA_WIDTH = 320; // Width of bars
const MAX_BAR_HEIGHT = 22; // Max bar height
// const audio = document.getElementById(filename);
const audio = new Audio(filename + ".mp3");
audio.controls = false;
document.body.appendChild(audio);
audio.play();
audio.onplay = function() {
startTime = Date.now();
showWords();
};
audioContext = new (window.AudioContext || window.webkitAudioContext)();
source = audioContext.createMediaElementSource(audio);
analyser = audioContext.createAnalyser();
source.connect(analyser);
analyser.connect(audioContext.destination);
analyser.fftSize = 256;
bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
animate();
audio.addEventListener('ended', (event) => {
canvas.style.display = "none"
document.getElementById('grid').style.display = "flex";
console.log('audio has been ended');
});
function animate() {
requestAnimationFrame(animate);
analyser.getByteFrequencyData(dataArray);
// Clear everything (no ghosting)
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const step = Math.floor(bufferLength / TOTAL_BARS);
const barWidth = BARS_AREA_WIDTH / TOTAL_BARS;
const centerY = canvas.height / 2;
const centerX = (canvas.width - BARS_AREA_WIDTH) / 2;
// Draw center line
ctx.fillStyle = '#ffffff'; // White bars
// Store top bars heights
const barHeights = [];
// Draw top bars
for (let i = 0; i < TOTAL_BARS; i++) {
let sum = 0;
for (let j = 0; j < step; j++) {
sum += dataArray[(i * step) + j] || 0;
}
const average = sum / step;
const barHeight = (average / 255) * MAX_BAR_HEIGHT;
barHeights.push(barHeight); // Save for mirroring
ctx.fillRect(centerX + i * barWidth, centerY-2 - barHeight, barWidth, barHeight);
}
// Draw bottom bars (mirror of top)
for (let i = 0; i < TOTAL_BARS; i++) {
const mirroredHeight = barHeights[i];
ctx.fillRect(centerX + i * barWidth, centerY+2, barWidth, mirroredHeight);
}
}
}
//Subtitle processing part use showWords();
// Parse SRT text into words with timing
function parseSRT(data) {
const regex = /(\d+)\s+(\d{2}:\d{2}:\d{2},\d{3}) --> (\d{2}:\d{2}:\d{2},\d{3})\s+(.+?)(?:\r?\n|$)/gs;
let matches;
const result = [];
while ((matches = regex.exec(data)) !== null) {
result.push({
start: timeStringToMs(matches[2]),
end: timeStringToMs(matches[3]),
text: matches[4].trim()
});
}
console.log(result);
return result;
}
// Convert SRT time format to milliseconds
function timeStringToMs(timeStr) {
const [hours, minutes, seconds] = timeStr.split(':');
const [secs, ms] = seconds.split(',');
return (+hours) * 3600000 + (+minutes) * 60000 + (+secs) * 1000 + (+ms);
}
// Show words at correct times
function showWords() {
const now = Date.now() - startTime;
const subtitleDiv = document.getElementById('element');
if (wordsQueue.length > 0 && now >= wordsQueue[0].start) {
const nextWord = wordsQueue.shift();
subtitleDiv.innerHTML += (subtitleDiv.innerHTML ? ' ' : '') + nextWord.text;
}
requestAnimationFrame(showWords);
}
// Load SRT and start
window.addEventListener('DOMContentLoaded', function() {
fetch('option1.srt') // Adjust path if necessary
.then(response => {
return response.text();
})
.then(data => {
wordsQueue = parseSRT(data);
// document.getElementById('subtitle').innerHTML = '';
})
.catch(error => {
console.error('Failed to load subtitles:', error);
});
});

BIN
option1.mp3 Normal file

Binary file not shown.

640
option1.srt Normal file
View File

@ -0,0 +1,640 @@
1
00:00:02,170 --> 00:00:03,080
There
2
00:00:03,081 --> 00:00:03,220
will
3
00:00:03,221 --> 00:00:03,360
be
4
00:00:03,361 --> 00:00:03,580
times
5
00:00:03,581 --> 00:00:03,900
when
6
00:00:03,950 --> 00:00:04,030
the
7
00:00:04,031 --> 00:00:04,200
struggle
8
00:00:04,201 --> 00:00:04,520
seems
9
00:00:04,521 --> 00:00:05,521
impossible.
10
00:00:06,060 --> 00:00:06,220
I
11
00:00:06,221 --> 00:00:06,320
know
12
00:00:06,321 --> 00:00:06,440
this
13
00:00:06,441 --> 00:00:06,680
already.
14
00:00:07,360 --> 00:00:08,360
Alone,
15
00:00:08,400 --> 00:00:09,400
unsure,
16
00:00:09,640 --> 00:00:09,690
dwarfed
17
00:00:09,691 --> 00:00:10,060
by
18
00:00:10,061 --> 00:00:10,160
the
19
00:00:10,161 --> 00:00:10,460
scale
20
00:00:10,461 --> 00:00:10,620
of
21
00:00:10,621 --> 00:00:10,740
the
22
00:00:10,741 --> 00:00:11,741
enemy.
23
00:00:12,320 --> 00:00:12,900
Remember
24
00:00:12,901 --> 00:00:13,901
this.
25
00:00:14,320 --> 00:00:14,600
Freedom
26
00:00:14,601 --> 00:00:15,260
is
27
00:00:15,261 --> 00:00:15,400
a
28
00:00:15,401 --> 00:00:15,700
pure
29
00:00:15,701 --> 00:00:16,701
idea.
30
00:00:17,700 --> 00:00:17,880
It
31
00:00:17,881 --> 00:00:18,080
occurs
32
00:00:18,081 --> 00:00:18,600
spontaneously
33
00:00:18,601 --> 00:00:19,680
and
34
00:00:19,681 --> 00:00:19,780
without
35
00:00:19,781 --> 00:00:20,781
instruction.
36
00:00:21,340 --> 00:00:21,600
Random
37
00:00:21,601 --> 00:00:21,860
acts
38
00:00:21,861 --> 00:00:22,060
of
39
00:00:22,061 --> 00:00:22,160
insurrection
40
00:00:22,161 --> 00:00:22,760
are
41
00:00:22,761 --> 00:00:23,040
occurring
42
00:00:23,041 --> 00:00:23,700
constantly
43
00:00:23,701 --> 00:00:24,240
throughout
44
00:00:24,241 --> 00:00:24,440
the
45
00:00:24,441 --> 00:00:24,700
galaxy.
46
00:00:25,040 --> 00:00:25,110
There
47
00:00:25,111 --> 00:00:25,160
are
48
00:00:25,161 --> 00:00:25,360
whole
49
00:00:25,361 --> 00:00:26,361
armies,
50
00:00:26,520 --> 00:00:27,000
battalions
51
00:00:27,001 --> 00:00:27,420
that
52
00:00:27,421 --> 00:00:27,540
have
53
00:00:27,541 --> 00:00:27,700
no
54
00:00:27,701 --> 00:00:27,860
idea
55
00:00:27,861 --> 00:00:28,080
that
56
00:00:28,081 --> 00:00:28,240
they've
57
00:00:28,241 --> 00:00:28,460
already
58
00:00:28,461 --> 00:00:28,820
enlisted
59
00:00:28,821 --> 00:00:29,200
in
60
00:00:29,201 --> 00:00:29,300
the
61
00:00:29,301 --> 00:00:30,301
cause.
62
00:00:30,980 --> 00:00:31,560
Remember
63
00:00:31,561 --> 00:00:31,920
that.
64
00:00:31,970 --> 00:00:32,100
The
65
00:00:32,101 --> 00:00:32,460
frontier
66
00:00:32,461 --> 00:00:32,700
of
67
00:00:32,750 --> 00:00:32,830
the
68
00:00:32,831 --> 00:00:33,120
rebellion
69
00:00:33,121 --> 00:00:33,400
is
70
00:00:33,401 --> 00:00:34,401
everywhere.
71
00:00:34,900 --> 00:00:35,080
And
72
00:00:35,081 --> 00:00:35,260
even
73
00:00:35,261 --> 00:00:35,460
the
74
00:00:35,461 --> 00:00:35,840
smallest
75
00:00:35,841 --> 00:00:36,180
act
76
00:00:36,181 --> 00:00:36,360
of
77
00:00:36,361 --> 00:00:36,520
insurrection
78
00:00:36,521 --> 00:00:37,120
pushes
79
00:00:37,121 --> 00:00:37,500
our
80
00:00:37,501 --> 00:00:37,800
lines
81
00:00:37,801 --> 00:00:38,801
forward.
82
00:00:40,020 --> 00:00:40,460
And
83
00:00:40,461 --> 00:00:40,560
then
84
00:00:40,561 --> 00:00:40,760
remember
85
00:00:40,761 --> 00:00:41,761
this.
86
00:00:42,140 --> 00:00:42,360
The
87
00:00:42,361 --> 00:00:42,600
imperial
88
00:00:42,601 --> 00:00:42,800
need
89
00:00:42,801 --> 00:00:42,960
for
90
00:00:42,961 --> 00:00:43,300
control
91
00:00:43,301 --> 00:00:43,520
is
92
00:00:43,521 --> 00:00:43,660
a
93
00:00:43,661 --> 00:00:43,940
desperate
94
00:00:43,941 --> 00:00:44,300
because
95
00:00:44,350 --> 00:00:44,430
it
96
00:00:44,431 --> 00:00:44,500
is
97
00:00:44,501 --> 00:00:44,720
so
98
00:00:44,721 --> 00:00:45,721
unnatural.
99
00:00:46,680 --> 00:00:47,300
Tyridine
100
00:00:47,301 --> 00:00:47,680
requires
101
00:00:47,681 --> 00:00:48,400
constant
102
00:00:48,401 --> 00:00:49,401
effort.
103
00:00:49,720 --> 00:00:49,810
It
104
00:00:49,811 --> 00:00:50,811
breaks.
105
00:00:51,290 --> 00:00:51,350
It
106
00:00:51,351 --> 00:00:52,351
leaks.
107
00:00:52,800 --> 00:00:53,140
Authorities
108
00:00:53,141 --> 00:00:54,141
brittle.
109
00:00:54,760 --> 00:00:55,060
Oppression
110
00:00:55,061 --> 00:00:55,300
is
111
00:00:55,301 --> 00:00:55,420
the
112
00:00:55,421 --> 00:00:55,580
mask
113
00:00:55,581 --> 00:00:55,800
of
114
00:00:55,801 --> 00:00:56,801
fear.
115
00:00:57,480 --> 00:00:58,120
Remember
116
00:00:58,121 --> 00:00:59,121
that.
117
00:00:59,440 --> 00:00:59,860
And
118
00:00:59,861 --> 00:01:00,020
know
119
00:01:00,021 --> 00:01:00,340
this.
120
00:01:00,390 --> 00:01:00,720
That
121
00:01:00,920 --> 00:01:01,580
they
122
00:01:01,581 --> 00:01:01,800
will
123
00:01:01,801 --> 00:01:02,120
come
124
00:01:02,121 --> 00:01:02,460
when
125
00:01:02,461 --> 00:01:02,680
all
126
00:01:02,681 --> 00:01:02,800
these
127
00:01:02,801 --> 00:01:03,400
skirmishes
128
00:01:03,401 --> 00:01:03,720
and
129
00:01:03,721 --> 00:01:04,721
battles.
130
00:01:04,940 --> 00:01:05,260
These
131
00:01:05,261 --> 00:01:05,420
moments
132
00:01:05,421 --> 00:01:05,680
of
133
00:01:05,681 --> 00:01:05,980
defiance
134
00:01:05,981 --> 00:01:06,320
will
135
00:01:06,370 --> 00:01:06,450
have
136
00:01:06,451 --> 00:01:06,720
flooded
137
00:01:06,721 --> 00:01:06,900
the
138
00:01:06,901 --> 00:01:07,060
banks
139
00:01:07,061 --> 00:01:07,280
of
140
00:01:07,330 --> 00:01:07,410
the
141
00:01:07,411 --> 00:01:07,860
empire's
142
00:01:07,861 --> 00:01:08,000
authority
143
00:01:08,001 --> 00:01:08,500
and
144
00:01:08,501 --> 00:01:08,680
then
145
00:01:08,681 --> 00:01:08,840
there
146
00:01:08,841 --> 00:01:08,980
will
147
00:01:08,981 --> 00:01:09,140
be
148
00:01:09,141 --> 00:01:09,460
one,
149
00:01:09,700 --> 00:01:10,020
two,
150
00:01:10,360 --> 00:01:10,500
many.
151
00:01:11,300 --> 00:01:11,480
One
152
00:01:11,481 --> 00:01:11,920
single
153
00:01:11,921 --> 00:01:12,440
thing
154
00:01:12,441 --> 00:01:12,720
will
155
00:01:12,721 --> 00:01:13,020
break
156
00:01:13,021 --> 00:01:13,440
the
157
00:01:13,441 --> 00:01:14,441
siege.
158
00:01:15,940 --> 00:01:16,440
Remember
159
00:01:16,441 --> 00:01:17,441
this.
160
00:01:18,480 --> 00:01:19,480
Try.

93
recording.js Normal file
View File

@ -0,0 +1,93 @@
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
fitToContainer(canvas);
function fitToContainer(canvas){
// Make it visually fill the positioned parent
canvas.style.width ='100%';
canvas.style.height='100%';
// ...then set the internal size to match
canvas.width = canvas.offsetWidth;
canvas.height = canvas.offsetHeight;
}
let audioContext;
let analyser;
let source;
let dataArray;
let bufferLength;
const TOTAL_BARS = 44 ; // Only 44 bars now
const BARS_AREA_WIDTH = 320; // Width of bars
const MAX_BAR_HEIGHT = 22; // Max bar height
// window.onload = function() {
// document.getElementById('my_audio').dispatchEvent(new Event('input', { bubbles: true }));
// }
window.onload = function() {
const audio = document.getElementById("my_audio");
audio.controls = false;
document.body.appendChild(audio);
audio.play();
audioContext = new (window.AudioContext || window.webkitAudioContext)();
source = audioContext.createMediaElementSource(audio);
analyser = audioContext.createAnalyser();
source.connect(analyser);
analyser.connect(audioContext.destination);
analyser.fftSize = 256;
bufferLength = analyser.frequencyBinCount;
dataArray = new Uint8Array(bufferLength);
animate();
}
function animate() {
requestAnimationFrame(animate);
analyser.getByteFrequencyData(dataArray);
// Clear everything (no ghosting)
ctx.fillStyle = '#000000';
ctx.fillRect(0, 0, canvas.width, canvas.height);
const step = Math.floor(bufferLength / TOTAL_BARS);
const barWidth = BARS_AREA_WIDTH / TOTAL_BARS;
const centerY = canvas.height / 2;
const centerX = (canvas.width - BARS_AREA_WIDTH) / 2;
// Draw center line
ctx.fillStyle = '#ffffff'; // White bars
// Store top bars heights
const barHeights = [];
// Draw top bars
for (let i = 0; i < TOTAL_BARS; i++) {
let sum = 0;
for (let j = 0; j < step; j++) {
sum += dataArray[(i * step) + j] || 0;
}
const average = sum / step;
const barHeight = (average / 255) * MAX_BAR_HEIGHT;
barHeights.push(barHeight); // Save for mirroring
ctx.fillRect(centerX + i * barWidth, centerY-2 - barHeight, barWidth, barHeight);
}
// Draw bottom bars (mirror of top)
for (let i = 0; i < TOTAL_BARS; i++) {
const mirroredHeight = barHeights[i];
ctx.fillRect(centerX + i * barWidth, centerY+2, barWidth, mirroredHeight);
}
}

25
recording1.html Normal file
View File

@ -0,0 +1,25 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My Website</title>
<link rel="stylesheet" href="./style.css">
<link rel="icon" href="./favicon.ico" type="image/x-icon">
</head>
<body>
<div class="UIbody">
<div class="topBar">
<canvas id="canvas"></canvas>
</div>
<!-- <input type="file" id="my_audio" accept="audio/*"> -->
<!-- <audio id="my_audio" src="nemik.mp3"></audio> -->
</div>
<script src="recording.js"></script>
</body>
</html>

95
style.css Normal file
View File

@ -0,0 +1,95 @@
@font-face {
font-family: SW;
src: url(./AurebeshAF-CanonTech.otf);
}
body {
background-color: black;
color: white;
}
.recordingNo{
font-size: 90px;
}
#safeArea{
margin-top:52px;
border: 1px solid gray;
display: none;
justify-content: space-between;
}
.speechtext{
font-size: 22px;
line-height: 28px;
height: 190px;
margin: 5px;
overflow: hidden; /* Hide overflowing text */
display: flex;
flex-direction: column;
justify-content: flex-end; /* Stick content to the bottom */
/* white-space: pre-wrap; */
word-wrap: break-word;
overflow-wrap: break-word; /* <-- allow breaking at spaces if needed */
/* white-space: pre-wrap; */
}
#element{
/* padding-right:10px; */
}
.UIbody{
font-family: SW;
margin-left: auto;
margin-right: auto;
width: 320px;
height: 480px;
border: 1px solid white;
overflow: hidden;
}
.topBar {
font-family: SW;
width: 320px;
height: 44px;
margin-top: 10px;
border: 1px solid gray;
}
.grid {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
vertical-align: middle;
/* display: grid;
grid-template-columns: repeat(9, 1fr);*/
height: 100%;
}
.grid div {
display: flex; /* add this */
justify-content: center; /* center horizontally */
align-items: center; /* center vertically */
text-align: center;
border: 1px solid white;
width: 100%;
height: 100%;
}
button {
all: unset
}
.menuButtons{
margin-top: 50px;
font-size: 32px;
padding: 20px;
}
.active {
color: black;
background-color: white;
}