-
Notifications
You must be signed in to change notification settings - Fork 3
/
index.html
260 lines (240 loc) · 9.92 KB
/
index.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
<!DOCTYPE html>
<html lang="en" ng-app="wavelyricApp">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src="FileSaver.js"></script>
<script src="waveform.js"></script>
<script src="markerEditor.js"></script>
<script src="oggEncoder.js">
oggEncoder.js has a worker which uses
https://github.com/higuma/ogg-vorbis-encoder-js
ogg-vorbis-encoder-js by Yuji Miyane under the MIT license
http://www.xiph.org/licenses/bsd/
libogg and libvorbis by Xiph under the BSD license
</script>
<script src="index.js"></script>
<link rel="stylesheet" type="text/css" href="index.css">
<title>
wavelyric
</title>
</head>
<body ng-controller="WavelyricCtrl">
<div id="dropOverlay" ng-show="draggingFile">
<div id="dropOverlayInner">
<div id="dropOverlayText">
Drop file
</div>
</div>
</div>
<header>
<div class="header-inner">
<img src="assets/logo.png">
</div>
</header>
<div id="container">
<div class="narrow">
<div id="mainPanel">
<div id="welcome" ng-show="stage === 'start'" class="stageContainer">
<p class="intro">Hey there! This is wavelyric. <strong>Drag a music file</strong> into the page to get started.</p>
<div id="landingBackground">
<div class="firstText">
<p>
With wavelyric, you can create Karaoke-style timing data for every word in any song. You'll have a waveform representation of the song and a bunch of keyboard shortcuts at your fingertips to help you get going.
</p>
</div>
<div class="secondText">
<p>
When you're finished, you can export to a .lrc file, formatted perfectly for use with <a href="http://store.steampowered.com/app/449000/">Steno Hero</a>, a free typing game aimed at stenographers.
</p>
</div>
</div>
</div>
<div id="loading" ng-show="stage === 'loading'" class="stageContainer">
Loading audio file...
</div>
<div id="newOrImport" ng-show="stage === 'newOrImport'" class="stageContainer">
<div id="newSong" ng-click="stage = 'lyrics'">
<div class="bigWords">New song</div>
Start from scratch using the audio file you chose.
</div>
<div id="importSong" ng-click="stage = 'import'">
<div class="bigWords">Import song</div>
Import a JSON file from wavelyric or a .lrc file from Steno Hero.
</div>
</div>
<div id="lyrics" ng-show="stage === 'lyrics'" class="stageContainer">
Enter the song's lyrics:<br>
<textarea ng-model="lyricsField"></textarea><br>
<button ng-click="loadLyrics()" ng-disabled="lyricsField === ''">Finished</button>
</div>
<div id="import" ng-show="stage === 'import'" class="stageContainer">
Enter JSON or a .lrc file:<br>
<textarea ng-model="importField"></textarea><br>
<button ng-click="import()" ng-disabled="importField === ''">Finished</button>
</div>
<div id="main" ng-show="stage === 'main'" class="stageContainer">
<div id="tabs">
<div class="tab" ng-class="tab === 'metadata' ? 'highlight': ''" ng-click="tab = 'metadata'">Metadata</div>
<div class="tab" ng-class="tab === 'lineTiming' ? 'highlight': ''" ng-click="tab = 'lineTiming'">Line timing</div>
<div class="tab" ng-class="tab === 'wordTiming' ? 'highlight': ''" ng-click="tab = 'wordTiming'">Word timing</div>
<div class="tab" ng-class="tab === 'export' ? 'highlight': ''" ng-click="tab = 'export'">Export</div>
</div>
<div class="tabScreen" ng-show="tab === 'metadata'">
<table id="metadataTable">
<tbody>
<tr>
<td>
Title:
</td>
<td>
<input ng-model='metadata.title'>
</td>
</tr>
<tr>
<td>
Artist:
</td>
<td>
<input ng-model='metadata.artist'>
</td>
</tr>
<tr>
<td>
Album:
</td>
<td>
<input ng-model='metadata.album'>
</td>
</tr>
<tr>
<td>
Released (year):
</td>
<td>
<input ng-model='metadata.year'>
</td>
</tr>
<tr>
<td>
Language:
</td>
<td>
<input ng-model='metadata.language'>
</td>
</tr>
<tr>
<td>
Album art path:
</td>
<td>
<input ng-model='metadata.art'>
</td>
</tr>
<tr>
<td>
Music file path:
</td>
<td>
<input ng-model='metadata.file'>
</td>
</tr>
<tr>
<td>
Difficulty:
</td>
<td>
<select ng-model="metadata.difficulty">
<option value="1">Very easy</option>
<option value="2">Easy</option>
<option value="3">Normal</option>
<option value="4">Hard</option>
<option value="5">Very hard</option>
</select>
</td>
</tr>
</tbody>
</table>
</div>
<div class="tabScreen" ng-show="tab === 'lineTiming'">
<canvas width="900" height="200" id="lineTimingCanvas"></canvas>
<div id="lines">
<table>
<tr>
<td class="lineLabel">
PREVIOUS LINE:
</td>
<td>
<div ng-model="previousLine" id="previousLine">{{showPreviousLine()}}</div>
</td>
</tr>
<tr>
<td class="lineLabel">
CURRENT LINE:
</td>
<td>
<div ng-hide="editingCurrentLine" id="currentLine" ng-click="editLineText()" ng-class="holdingShift && !markers[currentMarker].space? 'holdingShift' : ''">
<span ng-repeat="word in showCurrentLine() track by $index"><span id="{{'invididualLineWord-' + $index}}" class="individualLineWord" ng-click="splitAtWord($event, $index)">{{showCurrentLine()[$index]}}</span> </span>
</div>
<input id="currentLineInput" ng-model="currentLineInput" ng-show="editingCurrentLine" ng-blur="saveEditingText()">
</td>
</tr>
<tr>
<td class="lineLabel">
NEXT LINE:
</td>
<td>
<div ng-model="nextLine" id="nextLine">{{showNextLine()}}</div>
</td>
</tr>
</table>
</div>
<div id="lineTimingInstructions">
<p><strong>Space</strong> to start/stop playback.</p>
<p><strong>N</strong> to place the next line marker, <strong>S</strong> to place <dfn title="A period during which the player cannot continue to type the previous line but may not yet start the next">space</dfn></p>
<p><strong>Drag</strong> markers with the mouse to reposition them. The dragged line and the one before it will have their word timings reset.</p>
<p><strong>Shift-click</strong> a space marker to remove it or a line marker to merge it with the previous line.</p>
<p><strong>Shift-click</strong> a word in the "current line" area to split the line at that word.</p>
<p><strong>Click</strong> the line in the "current line" area to edit the line. If you change the number of words, that line's word timing information will be reset.</p>
<p><strong>Page up/page down</strong> to move to the previous/next marker.</p>
<p><strong>Click</strong> on a marker to move the cursor to the marker.</p>
<p><strong>Arrow keys</strong> or <strong>click</strong> to move the cursor.</p>
<p><strong>Home/end</strong> to move to the beginning or end of the song.</p>
<p><strong><a href="mailto:[email protected]" target="_blank">Email</a></strong> me if you need help. I know it's a bit confusing at first!</p>
</div>
</div>
<div class="tabScreen" ng-show="tab === 'wordTiming'">
<div id="wordTimingInstructions">
<strong>Click</strong> on a line to time individual words.
</div>
<div ng-repeat="wordTiming in wordTimings">
<div class="wordTimingLine" ng-click="clickLine($index)">{{lines[$index]}}</div>
<canvas class="wordTimingCanvas" ng-show="editingLine === $index" id="wordEditor-{{$index}}" width="900" height="150"></canvas>
</div>
</div>
<div class="tabScreen" ng-show="tab === 'export'">
<p>Export to <strong>JSON</strong> for later use with wavelyric (more precision, works with unfinished projects). Export to <strong>Steno Hero</strong> for use with Steno Arcade.</p>
<div id="jsonExports" class="exportSection">
<button ng-click="showJSON();">Show JSON</button>
<button ng-click="saveJSON();">Download JSON</button>
</div>
<div id="stenoHeroExports" class="exportSection">
<button ng-click="showStenoHero();">Show Steno Hero</button>
<button ng-click="saveStenoHero();">Download Steno Hero</button>
</div>
<textarea ng-model="exportArea" id="exportArea" ng-show="showExportArea"></textarea>
<button ng-click="showExportArea = false;" ng-show="showExportArea">Hide</button>
<p>An <strong>ogg</strong> file is an audio file that can be read by Steno Hero. You can download this song as an ogg (experimental!) by clicking "Export Ogg" and waiting a few seconds.</p>
<div id="oggExport" class="exportSection">
<label>Ogg Quality (-0.1 to 1.0): <input type="range" min="-0.1" max="1.0" step="0.1" value="0.5" ng-model="oggQuality" ng-disabled="oggExportInProgress"> <span>{{oggQuality}}</span></label>
<button ng-click="beginOggExport()" ng-disabled="oggExportInProgress">Export Ogg</button>
</div>
</div>
</div>
</div>
<footer>
By <a href="http://timothyaveni.com/">Timothy Aveni</a> <a href="https://github.com/syntaxblitz/wavelyric"><img src="assets/GitHub-Mark-32px.png" class="small-mark"></a>
</footer>
</div>
</div>
</body>
</html>