speechrecorderng 2.25.3 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm2020/lib/audio/array_audio_buffer.mjs +101 -0
- package/esm2020/lib/audio/array_audio_buffer_input_stream.mjs +86 -0
- package/esm2020/lib/audio/audio_data_holder.mjs +109 -0
- package/esm2020/lib/audio/audio_display.mjs +5 -5
- package/esm2020/lib/audio/audio_player.mjs +9 -7
- package/esm2020/lib/audio/capture/capture.mjs +6 -1
- package/esm2020/lib/audio/dsp/level_measure.mjs +97 -55
- package/esm2020/lib/audio/io/stream.mjs +3 -3
- package/esm2020/lib/audio/persistor.mjs +5 -6
- package/esm2020/lib/audio/playback/array_audio_buffer_source_node.mjs +265 -0
- package/esm2020/lib/audio/playback/player.mjs +184 -50
- package/esm2020/lib/audio/ui/audio_canvas_layer_comp.mjs +25 -13
- package/esm2020/lib/audio/ui/audio_display_scroll_pane.mjs +2 -2
- package/esm2020/lib/audio/ui/audiosignal.mjs +206 -77
- package/esm2020/lib/audio/ui/container.mjs +14 -14
- package/esm2020/lib/audio/ui/livelevel.mjs +15 -2
- package/esm2020/lib/audio/ui/sonagram.mjs +343 -160
- package/esm2020/lib/io/stream.mjs +77 -1
- package/esm2020/lib/net/uploader.mjs +15 -3
- package/esm2020/lib/speechrecorder/recording.mjs +52 -7
- package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +99 -7
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +117 -101
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +34 -6
- package/esm2020/lib/speechrecorder/session/progress.mjs +2 -2
- package/esm2020/lib/speechrecorder/session/prompting.mjs +2 -2
- package/esm2020/lib/speechrecorder/session/recorder_combi_pane.mjs +6 -3
- package/esm2020/lib/speechrecorder/session/recording_file_cache.mjs +182 -0
- package/esm2020/lib/speechrecorder/session/recording_list.mjs +23 -10
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +12 -6
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +5 -5
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +13 -9
- package/esm2020/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +8 -5
- package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +118 -95
- package/esm2020/lib/speechrecorderng.component.mjs +2 -2
- package/esm2020/lib/speechrecorderng.module.mjs +5 -4
- package/esm2020/lib/spr.module.version.mjs +2 -2
- package/esm2020/lib/ui/recordingitem_display.mjs +2 -2
- package/fesm2015/speechrecorderng.mjs +2321 -743
- package/fesm2015/speechrecorderng.mjs.map +1 -1
- package/fesm2020/speechrecorderng.mjs +2321 -753
- package/fesm2020/speechrecorderng.mjs.map +1 -1
- package/lib/audio/array_audio_buffer.d.ts +15 -0
- package/lib/audio/array_audio_buffer_input_stream.d.ts +14 -0
- package/lib/audio/audio_data_holder.d.ts +29 -0
- package/lib/audio/audio_display.d.ts +2 -1
- package/lib/audio/audio_player.d.ts +2 -1
- package/lib/audio/capture/capture.d.ts +2 -0
- package/lib/audio/dsp/level_measure.d.ts +2 -1
- package/lib/audio/persistor.d.ts +4 -3
- package/lib/audio/playback/array_audio_buffer_source_node.d.ts +24 -0
- package/lib/audio/playback/player.d.ts +6 -0
- package/lib/audio/ui/audio_canvas_layer_comp.d.ts +4 -1
- package/lib/audio/ui/audio_display_scroll_pane.d.ts +2 -1
- package/lib/audio/ui/audiosignal.d.ts +3 -2
- package/lib/audio/ui/container.d.ts +3 -2
- package/lib/audio/ui/livelevel.d.ts +3 -1
- package/lib/audio/ui/sonagram.d.ts +3 -2
- package/lib/io/stream.d.ts +17 -0
- package/lib/net/uploader.d.ts +6 -1
- package/lib/speechrecorder/recording.d.ts +15 -3
- package/lib/speechrecorder/recordings/recordings.service.d.ts +2 -0
- package/lib/speechrecorder/session/audiorecorder.d.ts +2 -7
- package/lib/speechrecorder/session/basicrecorder.d.ts +9 -3
- package/lib/speechrecorder/session/progress.d.ts +1 -1
- package/lib/speechrecorder/session/prompting.d.ts +1 -1
- package/lib/speechrecorder/session/recorder_combi_pane.d.ts +3 -1
- package/lib/speechrecorder/session/recording_file_cache.d.ts +30 -0
- package/lib/speechrecorder/session/recording_list.d.ts +3 -1
- package/lib/speechrecorder/session/recordingfile/recording-file-meta.component.d.ts +2 -1
- package/lib/speechrecorder/session/recordingfile/recording-file-view.component.d.ts +1 -0
- package/lib/speechrecorder/session/sessionmanager.d.ts +5 -11
- package/lib/speechrecorderng.module.d.ts +2 -1
- package/lib/spr.module.version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -36,6 +36,7 @@ import * as i2$2 from '@angular/material/table';
|
|
|
36
36
|
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
37
37
|
import { MatSelectModule } from '@angular/material/select';
|
|
38
38
|
import { MatInputModule } from '@angular/material/input';
|
|
39
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
39
40
|
|
|
40
41
|
class ActionEvent {
|
|
41
42
|
constructor(_value = null) {
|
|
@@ -109,6 +110,518 @@ class Action {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
113
|
+
class ArrayAudioBufferInputStream {
|
|
114
|
+
constructor(arrayAudioBuffer) {
|
|
115
|
+
this.arrayAudioBuffer = arrayAudioBuffer;
|
|
116
|
+
this._framePos = 0;
|
|
117
|
+
this.chunkFramePos = 0;
|
|
118
|
+
this.chunkIdx = 0;
|
|
119
|
+
this.eod = false;
|
|
120
|
+
//console.debug("Array audio input stream array audio buffer frames: "+arrayAudioBuffer.frameLen);
|
|
121
|
+
}
|
|
122
|
+
close() {
|
|
123
|
+
}
|
|
124
|
+
skipFrames(n) {
|
|
125
|
+
let toSkip = n;
|
|
126
|
+
if (this.chunkIdx >= this.arrayAudioBuffer.chunkCount) {
|
|
127
|
+
this.eod = true;
|
|
128
|
+
if (toSkip > 0) {
|
|
129
|
+
throw Error('Skip out of bounds: Cannot skip ' + toSkip + ' frames.');
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
let chunkBuf0 = this.arrayAudioBuffer.data[0][this.chunkIdx];
|
|
134
|
+
let chunkBufsLen = chunkBuf0.length;
|
|
135
|
+
let currBufSkippable = chunkBufsLen - this.chunkFramePos;
|
|
136
|
+
if (n >= currBufSkippable) {
|
|
137
|
+
this._framePos += currBufSkippable;
|
|
138
|
+
toSkip -= currBufSkippable;
|
|
139
|
+
this.chunkIdx++;
|
|
140
|
+
this.chunkFramePos = 0;
|
|
141
|
+
if (this.chunkIdx < this.arrayAudioBuffer.chunkCount) {
|
|
142
|
+
this.skipFrames(toSkip);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
if (toSkip > 0) {
|
|
146
|
+
throw Error('Skip out of bounds: Cannot skip ' + toSkip + ' frames.');
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
toSkip -= n;
|
|
152
|
+
this.chunkFramePos += n;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
read(buffers) {
|
|
157
|
+
let read = 0;
|
|
158
|
+
let toRead = buffers[0].length;
|
|
159
|
+
while (read < toRead && !this.eod) {
|
|
160
|
+
//console.debug("Chunk "+this.chunkIdx+" of "+this.arrayAudioBuffer.chunkCount+" chunks.")
|
|
161
|
+
if (this.chunkIdx >= this.arrayAudioBuffer.chunkCount) {
|
|
162
|
+
this.eod = true;
|
|
163
|
+
//console.debug("Array audio input stream end of data read frames: "+this.framePos);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
let chunkBuf0 = this.arrayAudioBuffer.data[0][this.chunkIdx];
|
|
167
|
+
let chunkBufsLen = chunkBuf0.length;
|
|
168
|
+
let chunkBufAvail = chunkBufsLen - this.chunkFramePos;
|
|
169
|
+
let r = chunkBufAvail;
|
|
170
|
+
if (r > toRead - read) {
|
|
171
|
+
r = toRead - read;
|
|
172
|
+
}
|
|
173
|
+
for (let ch = 0; ch < buffers.length; ch++) {
|
|
174
|
+
let chChunkBuf = this.arrayAudioBuffer.data[ch][this.chunkIdx];
|
|
175
|
+
for (let bi = 0; bi < r; bi++) {
|
|
176
|
+
buffers[ch][read + bi] = chChunkBuf[this.chunkFramePos + bi];
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
read += r;
|
|
180
|
+
this.chunkFramePos += r;
|
|
181
|
+
if (this.chunkFramePos >= chunkBufsLen) {
|
|
182
|
+
this.chunkIdx++;
|
|
183
|
+
this.chunkFramePos = 0;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
this._framePos += read;
|
|
188
|
+
//console.debug("Read: "+read+", frame pos: "+this.framePos)
|
|
189
|
+
if (this._framePos > this.arrayAudioBuffer.frameLen) {
|
|
190
|
+
console.error("Array audio input stream frame pos: " + this._framePos + " greater then frame length: " + this.arrayAudioBuffer.frameLen);
|
|
191
|
+
}
|
|
192
|
+
return read;
|
|
193
|
+
}
|
|
194
|
+
get framePos() {
|
|
195
|
+
return this._framePos;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
class EditFloat32ArrayInputStream {
|
|
200
|
+
constructor(_srcInputStream, offset = 0, length) {
|
|
201
|
+
this._srcInputStream = _srcInputStream;
|
|
202
|
+
this.offset = offset;
|
|
203
|
+
this.length = length;
|
|
204
|
+
this.framePos = 0;
|
|
205
|
+
this.readFrames = 0;
|
|
206
|
+
if (this.offset < 0) {
|
|
207
|
+
throw Error('Parameter offset must be undefined or greater or equal zero.');
|
|
208
|
+
}
|
|
209
|
+
if (this.length !== undefined && this.length < 0) {
|
|
210
|
+
throw Error('Parameter length must be undefined or greater or equal zero.');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
skipToOffset() {
|
|
214
|
+
if (this.framePos == 0 && this.offset > 0) {
|
|
215
|
+
this._srcInputStream.skipFrames(this.offset);
|
|
216
|
+
this.framePos += this.offset;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
read(buffers) {
|
|
220
|
+
this.skipToOffset();
|
|
221
|
+
let read = 0;
|
|
222
|
+
if (this.length === undefined) {
|
|
223
|
+
read = this._srcInputStream.read(buffers);
|
|
224
|
+
}
|
|
225
|
+
else {
|
|
226
|
+
if (buffers.length > 0) {
|
|
227
|
+
let bufsCh0 = buffers[0];
|
|
228
|
+
let bufsLen = bufsCh0.length;
|
|
229
|
+
let avail = this.length - this.readFrames;
|
|
230
|
+
if (avail > 0) {
|
|
231
|
+
if (avail > bufsLen) {
|
|
232
|
+
read = this._srcInputStream.read(buffers);
|
|
233
|
+
}
|
|
234
|
+
else {
|
|
235
|
+
// temporary buffers required
|
|
236
|
+
let tmpBufs = new Array(buffers.length);
|
|
237
|
+
for (let ch = 0; ch < buffers.length; ch++) {
|
|
238
|
+
tmpBufs[ch] = new Float32Array(avail);
|
|
239
|
+
}
|
|
240
|
+
read = this._srcInputStream.read(tmpBufs);
|
|
241
|
+
for (let ch = 0; ch < buffers.length; ch++) {
|
|
242
|
+
buffers[ch].set(tmpBufs[ch]);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this.readFrames += read;
|
|
249
|
+
this.framePos += read;
|
|
250
|
+
return read;
|
|
251
|
+
}
|
|
252
|
+
skipFrames(n) {
|
|
253
|
+
this.skipToOffset();
|
|
254
|
+
if (this.length === undefined) {
|
|
255
|
+
this._srcInputStream.skipFrames(n);
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
let avail = this.length - this.readFrames;
|
|
259
|
+
if (avail > 0) {
|
|
260
|
+
if (avail >= n) {
|
|
261
|
+
this._srcInputStream.skipFrames(n);
|
|
262
|
+
this.readFrames += n;
|
|
263
|
+
this.framePos += n;
|
|
264
|
+
}
|
|
265
|
+
else {
|
|
266
|
+
throw Error('Tried to skip out of bounds.');
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
close() {
|
|
272
|
+
this._srcInputStream.close();
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
class Float32ArrayChunkerOutStream {
|
|
276
|
+
constructor(outStream) {
|
|
277
|
+
this.outStream = outStream;
|
|
278
|
+
this.bufs = new Array();
|
|
279
|
+
this._channels = 0;
|
|
280
|
+
this._chunkSize = 0;
|
|
281
|
+
this.filled = 0;
|
|
282
|
+
this.receivedFrames = 0;
|
|
283
|
+
this.sentFrames = 0;
|
|
284
|
+
}
|
|
285
|
+
createBuffers() {
|
|
286
|
+
this.bufs = new Array(this._channels);
|
|
287
|
+
for (let ch = 0; ch < this._channels; ch++) {
|
|
288
|
+
this.bufs[ch] = new Float32Array(this._chunkSize);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
set chunkSize(chunkSize) {
|
|
292
|
+
this._chunkSize = chunkSize;
|
|
293
|
+
this.createBuffers();
|
|
294
|
+
}
|
|
295
|
+
get chunkSize() {
|
|
296
|
+
return this._chunkSize;
|
|
297
|
+
}
|
|
298
|
+
set channels(channels) {
|
|
299
|
+
this._channels = channels;
|
|
300
|
+
this.createBuffers();
|
|
301
|
+
}
|
|
302
|
+
get channels() {
|
|
303
|
+
return this._channels;
|
|
304
|
+
}
|
|
305
|
+
available() {
|
|
306
|
+
return this._chunkSize - this.filled;
|
|
307
|
+
}
|
|
308
|
+
write(buffers) {
|
|
309
|
+
let copied = 0;
|
|
310
|
+
if (buffers.length > 0) {
|
|
311
|
+
let buffersLen = buffers[0].length;
|
|
312
|
+
this.receivedFrames += buffersLen;
|
|
313
|
+
let avail = buffersLen;
|
|
314
|
+
// Fill out buffers until all values copied
|
|
315
|
+
while (avail > 0) {
|
|
316
|
+
let toFill = this._chunkSize - this.filled;
|
|
317
|
+
if (toFill > avail) {
|
|
318
|
+
toFill = avail;
|
|
319
|
+
}
|
|
320
|
+
let sliceEnd = copied + toFill;
|
|
321
|
+
// Firefox on Android sends only the first channel
|
|
322
|
+
for (let ch = 0; ch < buffersLen; ch++) {
|
|
323
|
+
if (buffers[ch]) {
|
|
324
|
+
let cpPrt = buffers[ch].slice(copied, sliceEnd);
|
|
325
|
+
let buf = this.bufs[ch];
|
|
326
|
+
buf.set(cpPrt, this.filled);
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
copied += toFill;
|
|
330
|
+
avail -= toFill;
|
|
331
|
+
this.filled += toFill;
|
|
332
|
+
if (this.filled == this._chunkSize) {
|
|
333
|
+
this.outStream.write(this.bufs);
|
|
334
|
+
this.sentFrames += this.filled;
|
|
335
|
+
this.filled = 0;
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return copied;
|
|
340
|
+
}
|
|
341
|
+
flush() {
|
|
342
|
+
if (this.filled > 0) {
|
|
343
|
+
let restBufs = new Array(this._channels);
|
|
344
|
+
for (let ch = 0; ch < this._channels; ch++) {
|
|
345
|
+
restBufs[ch] = this.bufs[ch].slice(0, this.filled);
|
|
346
|
+
}
|
|
347
|
+
this.outStream.write(restBufs);
|
|
348
|
+
this.outStream.flush();
|
|
349
|
+
this.sentFrames += this.filled;
|
|
350
|
+
this.filled = 0;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
close() {
|
|
354
|
+
this.outStream.close();
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Code from audio_source_worklet.js as string constant to be loaded as module
|
|
359
|
+
// Changes in audio_source_worklet.js must be copied and pasted to this string constant
|
|
360
|
+
const aswpStr = "\n" +
|
|
361
|
+
"// Important note: Changes in audio_source_worklet.js must be copied and pasted to the string constant aswpStr in array_audio_buffer_source_node.ts\n" +
|
|
362
|
+
"\n" +
|
|
363
|
+
"\n" +
|
|
364
|
+
"class AudioSourceProcessor extends AudioWorkletProcessor{\n" +
|
|
365
|
+
"\n" +
|
|
366
|
+
" filledFrames=0;\n" +
|
|
367
|
+
" audioBuffers=new Array();\n" +
|
|
368
|
+
" currentAudioBuffer=null;\n" +
|
|
369
|
+
" currentAudioBufferFramePos=0;\n" +
|
|
370
|
+
" currentAudioBufferAvail=0;\n" +
|
|
371
|
+
" running=false;\n" +
|
|
372
|
+
" ended=false;\n" +
|
|
373
|
+
"\n" +
|
|
374
|
+
" constructor() {\n" +
|
|
375
|
+
" super({numberOfInputs:0,numberOfOutputs:1});\n" +
|
|
376
|
+
" this.port.onmessage=(msgEv)=>{\n" +
|
|
377
|
+
" // received audio playback data from application\n" +
|
|
378
|
+
" //console.debug(\"Audio source worklet msg: Received.\");\n" +
|
|
379
|
+
"\n" +
|
|
380
|
+
" if(msgEv.data.cmd){\n" +
|
|
381
|
+
" if('data'===msgEv.data.cmd) {\n" +
|
|
382
|
+
" let chs = msgEv.data.chs;\n" +
|
|
383
|
+
"\n" +
|
|
384
|
+
" let audioData = new Array(chs);\n" +
|
|
385
|
+
" for (let ch = 0; ch < chs; ch++) {\n" +
|
|
386
|
+
" audioData[ch] = new Float32Array(msgEv.data.audioData[ch]);\n" +
|
|
387
|
+
" }\n" +
|
|
388
|
+
" let msgChBufLen=audioData[0].length;\n" +
|
|
389
|
+
" this.audioBuffers.push(audioData);\n" +
|
|
390
|
+
" this.filledFrames += msgChBufLen;\n" +
|
|
391
|
+
" //console.debug(\"Audio source worklet msg: Filled \" + this.filledFrames+ \" in \"+this.audioBuffers.length+\" buffers.\");\n" +
|
|
392
|
+
"\n" +
|
|
393
|
+
" }else if('start'===msgEv.data.cmd){\n" +
|
|
394
|
+
" this.running=true;\n" +
|
|
395
|
+
" }else if('stop'===msgEv.data.cmd){\n" +
|
|
396
|
+
" //console.debug(\"Stop...\");\n" +
|
|
397
|
+
" this.running=false;\n" +
|
|
398
|
+
" // clear buffers\n" +
|
|
399
|
+
" this.filledFrames=0;\n" +
|
|
400
|
+
" while(this.audioBuffers.length > 0) {\n" +
|
|
401
|
+
" this.audioBuffers.pop();\n" +
|
|
402
|
+
" }\n" +
|
|
403
|
+
" this.currentAudioBuffer=new Float32Array(0);\n" +
|
|
404
|
+
" }\n" +
|
|
405
|
+
" }\n" +
|
|
406
|
+
" }\n" +
|
|
407
|
+
" }\n" +
|
|
408
|
+
"\n" +
|
|
409
|
+
" process(\n" +
|
|
410
|
+
" inputs,\n" +
|
|
411
|
+
" outputs,\n" +
|
|
412
|
+
" parameters\n" +
|
|
413
|
+
" ){\n" +
|
|
414
|
+
" //console.debug(\"Audio source worklet: process \"+outputs.length+ \" output buffers.\");\n" +
|
|
415
|
+
" // copy ring buffer data to outputs\n" +
|
|
416
|
+
" if(!this.running){\n" +
|
|
417
|
+
" return !this.ended;\n" +
|
|
418
|
+
" }\n" +
|
|
419
|
+
"\n" +
|
|
420
|
+
" let output=outputs[0];\n" +
|
|
421
|
+
" let chs=output.length;\n" +
|
|
422
|
+
" //console.debug(\"Audio source worklet: Output channels: \"+chs);\n" +
|
|
423
|
+
" if(chs>0) {\n" +
|
|
424
|
+
"\n" +
|
|
425
|
+
" let outCh0 = output[0];\n" +
|
|
426
|
+
" let outChLen = outCh0.length;\n" +
|
|
427
|
+
"\n" +
|
|
428
|
+
" if(!this.currentAudioBuffer){\n" +
|
|
429
|
+
" // get first buffer\n" +
|
|
430
|
+
" let nxtBuff=this.audioBuffers.shift();\n" +
|
|
431
|
+
" if(nxtBuff) {\n" +
|
|
432
|
+
" this.currentAudioBuffer = nxtBuff;\n" +
|
|
433
|
+
" this.currentAudioBufferFramePos=0;\n" +
|
|
434
|
+
" this.currentAudioBufferAvail=this.currentAudioBuffer[0].length;\n" +
|
|
435
|
+
" }else{\n" +
|
|
436
|
+
" return true;\n" +
|
|
437
|
+
" }\n" +
|
|
438
|
+
" }\n" +
|
|
439
|
+
"\n" +
|
|
440
|
+
" let copied=0;\n" +
|
|
441
|
+
" do{\n" +
|
|
442
|
+
" if(this.currentAudioBufferAvail==0){\n" +
|
|
443
|
+
" let nxtBuff=this.audioBuffers.shift();\n" +
|
|
444
|
+
" if(nxtBuff){\n" +
|
|
445
|
+
" this.currentAudioBuffer=nxtBuff;\n" +
|
|
446
|
+
" this.currentAudioBufferFramePos=0;\n" +
|
|
447
|
+
" this.currentAudioBufferAvail=this.currentAudioBuffer[0].length;\n" +
|
|
448
|
+
" //console.debug(\"Next buffer with \"+this.currentAudioBufferAvail+ \" frames\");\n" +
|
|
449
|
+
" this.port.postMessage({eventType:'bufferNotification',filledFrames:this.filledFrames});\n" +
|
|
450
|
+
" }else{\n" +
|
|
451
|
+
" this.ended=true;\n" +
|
|
452
|
+
" this.port.postMessage({eventType:'ended'});\n" +
|
|
453
|
+
" //console.debug(\"Stream ended\");\n" +
|
|
454
|
+
" break;\n" +
|
|
455
|
+
" }\n" +
|
|
456
|
+
" }\n" +
|
|
457
|
+
" //console.debug(\"outChLen: \"+outChLen+\", copied: \"+copied+\", current avail: \"+this.currentAudioBufferAvail);\n" +
|
|
458
|
+
" let toCopy=outChLen-copied;\n" +
|
|
459
|
+
" if(toCopy>this.currentAudioBufferAvail){\n" +
|
|
460
|
+
" toCopy=this.currentAudioBufferAvail;\n" +
|
|
461
|
+
" }\n" +
|
|
462
|
+
" //console.debug(\"Copy \"+toCopy+\" frames...\");\n" +
|
|
463
|
+
" for(let ch=0;ch<chs;ch++) {\n" +
|
|
464
|
+
" let outCh=output[ch];\n" +
|
|
465
|
+
" for (let i = 0; i < toCopy; i++) {\n" +
|
|
466
|
+
" outCh[copied+i]=this.currentAudioBuffer[ch][this.currentAudioBufferFramePos+i];\n" +
|
|
467
|
+
" }\n" +
|
|
468
|
+
" }\n" +
|
|
469
|
+
" copied+=toCopy;\n" +
|
|
470
|
+
" this.currentAudioBufferFramePos+=toCopy;\n" +
|
|
471
|
+
" this.currentAudioBufferAvail-=toCopy;\n" +
|
|
472
|
+
"\n" +
|
|
473
|
+
" }while(copied<outChLen);\n" +
|
|
474
|
+
" this.filledFrames-=copied;\n" +
|
|
475
|
+
" //console.debug(\"Copied \"+copied+\" frames.\");\n" +
|
|
476
|
+
" }\n" +
|
|
477
|
+
" return !this.ended;\n" +
|
|
478
|
+
" }\n" +
|
|
479
|
+
"}\n" +
|
|
480
|
+
"\n" +
|
|
481
|
+
"registerProcessor('audio-source-worklet',AudioSourceProcessor);\n";
|
|
482
|
+
class ArrayAudioBufferSourceNode extends AudioWorkletNode {
|
|
483
|
+
constructor(context) {
|
|
484
|
+
super(context, 'audio-source-worklet');
|
|
485
|
+
this._bufferFillSeconds = ArrayAudioBufferSourceNode.DEFAULT_BUFFER_FILL_SECONDS;
|
|
486
|
+
this.bufferFillFrames = 0;
|
|
487
|
+
this._arrayAudioBuffer = null;
|
|
488
|
+
this._audioInputStream = null;
|
|
489
|
+
this._aisBufs = null;
|
|
490
|
+
this.filledFrames = 0;
|
|
491
|
+
this.onended = null;
|
|
492
|
+
this.channelCountMode = 'explicit';
|
|
493
|
+
this.port.onmessage = (msgEv) => {
|
|
494
|
+
var _a;
|
|
495
|
+
if (msgEv.data) {
|
|
496
|
+
let evType = msgEv.data.eventType;
|
|
497
|
+
if (evType) {
|
|
498
|
+
if ('bufferNotification' === evType) {
|
|
499
|
+
this.filledFrames = msgEv.data.filledFrames;
|
|
500
|
+
//console.debug("Buffer notification: filled frames: " + this.filledFrames);
|
|
501
|
+
this.fillBuffer();
|
|
502
|
+
}
|
|
503
|
+
else if ('ended' === evType) {
|
|
504
|
+
let drainTime = 0;
|
|
505
|
+
if ((_a = this._arrayAudioBuffer) === null || _a === void 0 ? void 0 : _a.sampleRate) {
|
|
506
|
+
drainTime = ArrayAudioBufferSourceNode.QUANTUM_FRAME_LEN / this._arrayAudioBuffer.sampleRate;
|
|
507
|
+
}
|
|
508
|
+
//let dstAny:any=this.context.destination;
|
|
509
|
+
//console.debug('Destination node tail-time: '+dstAny['tail-time']);
|
|
510
|
+
window.setTimeout(() => {
|
|
511
|
+
var _a;
|
|
512
|
+
(_a = this.onended) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
513
|
+
}, drainTime * 1000);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
fillBuffer(frameOffset) {
|
|
520
|
+
if (this._arrayAudioBuffer && this._audioInputStream && this._aisBufs) {
|
|
521
|
+
let filled = this.filledFrames;
|
|
522
|
+
let bufLen = 0;
|
|
523
|
+
while (filled < this.bufferFillFrames) {
|
|
524
|
+
let read = this._audioInputStream.read(this._aisBufs);
|
|
525
|
+
//console.log("ArrayAudioBufferSourceNode: read: "+read)
|
|
526
|
+
if (read) {
|
|
527
|
+
let trBuffers = new Array(this.channelCount);
|
|
528
|
+
for (let ch = 0; ch < this.channelCount; ch++) {
|
|
529
|
+
let adCh = this._aisBufs[ch];
|
|
530
|
+
let adChCopy = new Float32Array(adCh.length);
|
|
531
|
+
bufLen = adChCopy.length;
|
|
532
|
+
adChCopy.set(adCh);
|
|
533
|
+
trBuffers[ch] = adChCopy.buffer;
|
|
534
|
+
}
|
|
535
|
+
this.port.postMessage({
|
|
536
|
+
cmd: 'data',
|
|
537
|
+
chs: this.channelCount,
|
|
538
|
+
audioData: trBuffers
|
|
539
|
+
}, trBuffers);
|
|
540
|
+
filled += read;
|
|
541
|
+
}
|
|
542
|
+
else {
|
|
543
|
+
break;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
get arrayAudioBuffer() {
|
|
549
|
+
return this._arrayAudioBuffer;
|
|
550
|
+
}
|
|
551
|
+
set arrayAudioBuffer(value) {
|
|
552
|
+
var _a, _b;
|
|
553
|
+
this._arrayAudioBuffer = value;
|
|
554
|
+
if ((_a = this._arrayAudioBuffer) === null || _a === void 0 ? void 0 : _a.channelCount) {
|
|
555
|
+
this.channelCount = (_b = this._arrayAudioBuffer) === null || _b === void 0 ? void 0 : _b.channelCount;
|
|
556
|
+
this.bufferFillFrames = this._arrayAudioBuffer.sampleRate * this._bufferFillSeconds;
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
get bufferFillSeconds() {
|
|
560
|
+
return this._bufferFillSeconds;
|
|
561
|
+
}
|
|
562
|
+
set bufferFillSeconds(value) {
|
|
563
|
+
this._bufferFillSeconds = value;
|
|
564
|
+
}
|
|
565
|
+
start(when, offset, duration) {
|
|
566
|
+
if (when) {
|
|
567
|
+
throw Error("when, offest,duration parameters currently not supported by ArrayAudioBufferSourceNode class");
|
|
568
|
+
}
|
|
569
|
+
if (this._arrayAudioBuffer) {
|
|
570
|
+
let arrAis = new ArrayAudioBufferInputStream(this._arrayAudioBuffer);
|
|
571
|
+
if (offset === undefined && duration === undefined) {
|
|
572
|
+
this._audioInputStream = arrAis;
|
|
573
|
+
}
|
|
574
|
+
else {
|
|
575
|
+
let offsetFrames = 0;
|
|
576
|
+
let durationFrames = undefined;
|
|
577
|
+
if (offset !== undefined) {
|
|
578
|
+
offsetFrames = Math.floor(offset * this._arrayAudioBuffer.sampleRate);
|
|
579
|
+
}
|
|
580
|
+
if (duration !== undefined) {
|
|
581
|
+
durationFrames = Math.floor(duration * this._arrayAudioBuffer.sampleRate);
|
|
582
|
+
}
|
|
583
|
+
this._audioInputStream = new EditFloat32ArrayInputStream(arrAis, offsetFrames, durationFrames);
|
|
584
|
+
}
|
|
585
|
+
let chs = this._arrayAudioBuffer.channelCount;
|
|
586
|
+
this._aisBufs = new Array(chs);
|
|
587
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
588
|
+
this._aisBufs[ch] = new Float32Array(1024);
|
|
589
|
+
}
|
|
590
|
+
this.fillBuffer();
|
|
591
|
+
this.port.postMessage({ cmd: 'start' });
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
stop() {
|
|
595
|
+
var _a;
|
|
596
|
+
this.port.postMessage({ cmd: 'stop' });
|
|
597
|
+
(_a = this.onended) === null || _a === void 0 ? void 0 : _a.call(this);
|
|
598
|
+
}
|
|
599
|
+
}
|
|
600
|
+
ArrayAudioBufferSourceNode.QUANTUM_FRAME_LEN = 128;
|
|
601
|
+
ArrayAudioBufferSourceNode.DEFAULT_BUFFER_FILL_SECONDS = 10;
|
|
602
|
+
class AudioSourceWorkletModuleLoader {
|
|
603
|
+
static loadModule(context) {
|
|
604
|
+
return new Promise((resolve, reject) => {
|
|
605
|
+
if (AudioSourceWorkletModuleLoader.moduleLoaded) {
|
|
606
|
+
resolve.call(self);
|
|
607
|
+
}
|
|
608
|
+
else {
|
|
609
|
+
let audioWorkletModuleBlob = new Blob([aswpStr], { type: 'text/javascript' });
|
|
610
|
+
let audioWorkletModuleBlobUrl = window.URL.createObjectURL(audioWorkletModuleBlob);
|
|
611
|
+
context.resume();
|
|
612
|
+
context.audioWorklet.addModule(audioWorkletModuleBlobUrl).then(() => {
|
|
613
|
+
AudioSourceWorkletModuleLoader.moduleLoaded = true;
|
|
614
|
+
resolve.call(self);
|
|
615
|
+
}).catch((reason) => {
|
|
616
|
+
console.error(reason);
|
|
617
|
+
reject.call(reason);
|
|
618
|
+
});
|
|
619
|
+
}
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
AudioSourceWorkletModuleLoader.moduleLoaded = false;
|
|
624
|
+
|
|
112
625
|
var EventType;
|
|
113
626
|
(function (EventType) {
|
|
114
627
|
EventType[EventType["CLOSED"] = 0] = "CLOSED";
|
|
@@ -135,10 +648,17 @@ class AudioPlayer {
|
|
|
135
648
|
this.running = false;
|
|
136
649
|
this._audioClip = null;
|
|
137
650
|
this._audioBuffer = null;
|
|
651
|
+
this._arrayAudioBuffer = null;
|
|
138
652
|
this.sourceBufferNode = null;
|
|
653
|
+
this.sourceAudioWorkletNode = null;
|
|
139
654
|
this.playStartTime = null;
|
|
140
655
|
this.timerVar = null;
|
|
141
656
|
this.context = context;
|
|
657
|
+
// AudioSourceWorkletModuleLoader.loadModule(this.context).then(()=>{
|
|
658
|
+
// console.debug("Audio source worklet module loaded.");
|
|
659
|
+
// }).catch((error: any)=>{
|
|
660
|
+
// console.error('Could not add module '+error);
|
|
661
|
+
// });
|
|
142
662
|
this.listener = listener;
|
|
143
663
|
this.bufSize = AudioPlayer.DEFAULT_BUFSIZE;
|
|
144
664
|
this.n = navigator;
|
|
@@ -169,17 +689,23 @@ class AudioPlayer {
|
|
|
169
689
|
return this._stopAction;
|
|
170
690
|
}
|
|
171
691
|
set audioClip(audioClip) {
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
if (audioClip && audioClip.
|
|
175
|
-
|
|
692
|
+
let length = 0;
|
|
693
|
+
let chs = 0;
|
|
694
|
+
if (audioClip && audioClip.audioDataHolder) {
|
|
695
|
+
let audioDataHolder = audioClip.audioDataHolder;
|
|
696
|
+
chs = audioDataHolder.numberOfChannels;
|
|
176
697
|
if (chs > 0) {
|
|
177
|
-
length =
|
|
698
|
+
length = audioDataHolder.frameLen;
|
|
178
699
|
if (chs > this.context.destination.maxChannelCount) {
|
|
179
700
|
// TODO exception
|
|
180
701
|
}
|
|
181
702
|
}
|
|
182
|
-
|
|
703
|
+
if (audioDataHolder.buffer) {
|
|
704
|
+
this.audioBuffer = audioDataHolder.buffer;
|
|
705
|
+
}
|
|
706
|
+
if (audioDataHolder.arrayBuffer) {
|
|
707
|
+
this.arrayAudioBuffer = audioDataHolder.arrayBuffer;
|
|
708
|
+
}
|
|
183
709
|
audioClip.addSelectionObserver((ac) => {
|
|
184
710
|
this._startSelectionAction.disabled = this.startSelectionDisabled();
|
|
185
711
|
if (!this.startSelectionAction.disabled && this._autoPlayOnSelectToggleAction.value) {
|
|
@@ -189,12 +715,14 @@ class AudioPlayer {
|
|
|
189
715
|
}
|
|
190
716
|
else {
|
|
191
717
|
this.audioBuffer = null;
|
|
718
|
+
//this.arrayAudioBuffer=null;
|
|
192
719
|
}
|
|
193
720
|
this._audioClip = audioClip;
|
|
194
721
|
}
|
|
195
722
|
set audioBuffer(audioBuffer) {
|
|
196
723
|
this.stop();
|
|
197
724
|
this._audioBuffer = audioBuffer;
|
|
725
|
+
this._arrayAudioBuffer = null;
|
|
198
726
|
if (audioBuffer && this.context) {
|
|
199
727
|
this._startAction.disabled = false;
|
|
200
728
|
this._startSelectionAction.disabled = this.startSelectionDisabled();
|
|
@@ -213,23 +741,86 @@ class AudioPlayer {
|
|
|
213
741
|
get audioBuffer() {
|
|
214
742
|
return this._audioBuffer;
|
|
215
743
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
744
|
+
set arrayAudioBuffer(arrayAudioBuffer) {
|
|
745
|
+
this.stop();
|
|
746
|
+
this._audioBuffer = null;
|
|
747
|
+
this._arrayAudioBuffer = arrayAudioBuffer;
|
|
748
|
+
if (arrayAudioBuffer && this.context) {
|
|
749
|
+
AudioSourceWorkletModuleLoader.loadModule(this.context).then(() => {
|
|
750
|
+
this._startAction.disabled = false;
|
|
751
|
+
this._startSelectionAction.disabled = this.startSelectionDisabled();
|
|
752
|
+
if (this.listener) {
|
|
753
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
754
|
+
}
|
|
755
|
+
}).catch((error) => {
|
|
756
|
+
this._startAction.disabled = true;
|
|
757
|
+
this._startSelectionAction.disabled = true;
|
|
758
|
+
if (this.listener) {
|
|
759
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.CLOSED));
|
|
760
|
+
}
|
|
761
|
+
console.error('Could not add module ' + error);
|
|
762
|
+
});
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
227
765
|
this._startAction.disabled = true;
|
|
228
766
|
this._startSelectionAction.disabled = true;
|
|
229
|
-
this._stopAction.disabled = false;
|
|
230
|
-
//this.timerVar = window.setInterval((e)=>this.updatePlayPosition(), 200);
|
|
231
767
|
if (this.listener) {
|
|
232
|
-
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.
|
|
768
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.CLOSED));
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
get arrayAudioBuffer() {
|
|
773
|
+
return this._arrayAudioBuffer;
|
|
774
|
+
}
|
|
775
|
+
start() {
|
|
776
|
+
if (!this._startAction.disabled && !this.running) {
|
|
777
|
+
this.context.resume();
|
|
778
|
+
if (this._audioBuffer) {
|
|
779
|
+
this.sourceBufferNode = this.context.createBufferSource();
|
|
780
|
+
this.sourceBufferNode.buffer = this._audioBuffer;
|
|
781
|
+
this.sourceBufferNode.connect(this.context.destination);
|
|
782
|
+
this.sourceBufferNode.onended = () => this.onended();
|
|
783
|
+
this.playStartTime = this.context.currentTime;
|
|
784
|
+
this.running = true;
|
|
785
|
+
this.sourceBufferNode.start();
|
|
786
|
+
this.playStartTime = this.context.currentTime;
|
|
787
|
+
this._startAction.disabled = true;
|
|
788
|
+
this._startSelectionAction.disabled = true;
|
|
789
|
+
this._stopAction.disabled = false;
|
|
790
|
+
//this.timerVar = window.setInterval((e)=>this.updatePlayPosition(), 200);
|
|
791
|
+
if (this.listener) {
|
|
792
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.STARTED));
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
else if (this._arrayAudioBuffer) {
|
|
796
|
+
if (this._arrayAudioBuffer) {
|
|
797
|
+
this.sourceAudioWorkletNode = new ArrayAudioBufferSourceNode(this.context);
|
|
798
|
+
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
799
|
+
let msg = 'Unknwon error';
|
|
800
|
+
if (ev instanceof ErrorEvent) {
|
|
801
|
+
msg = ev.message;
|
|
802
|
+
}
|
|
803
|
+
console.error("Audio source worklet error: " + msg);
|
|
804
|
+
if (this.listener) {
|
|
805
|
+
// TODO
|
|
806
|
+
// this.listener.error(msg);
|
|
807
|
+
// this.listener.audioPlayerUpdate(new AudioPlayerEvent());
|
|
808
|
+
}
|
|
809
|
+
};
|
|
810
|
+
this.sourceAudioWorkletNode.arrayAudioBuffer = this._arrayAudioBuffer;
|
|
811
|
+
this.sourceAudioWorkletNode.connect(this.context.destination); // this already starts playing
|
|
812
|
+
this.sourceAudioWorkletNode.onended = () => this.onended();
|
|
813
|
+
this.playStartTime = this.context.currentTime;
|
|
814
|
+
this.running = true;
|
|
815
|
+
this.sourceAudioWorkletNode.start();
|
|
816
|
+
this.playStartTime = this.context.currentTime;
|
|
817
|
+
this._startAction.disabled = true;
|
|
818
|
+
this._startSelectionAction.disabled = true;
|
|
819
|
+
this._stopAction.disabled = false;
|
|
820
|
+
if (this.listener) {
|
|
821
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.STARTED));
|
|
822
|
+
}
|
|
823
|
+
}
|
|
233
824
|
}
|
|
234
825
|
}
|
|
235
826
|
}
|
|
@@ -239,34 +830,79 @@ class AudioPlayer {
|
|
|
239
830
|
startSelected() {
|
|
240
831
|
if (!this._startAction.disabled && !this.running) {
|
|
241
832
|
this.context.resume();
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
this.listener
|
|
833
|
+
if (this._audioBuffer) {
|
|
834
|
+
this.sourceBufferNode = this.context.createBufferSource();
|
|
835
|
+
this.sourceBufferNode.buffer = this._audioBuffer;
|
|
836
|
+
this.sourceBufferNode.connect(this.context.destination);
|
|
837
|
+
this.sourceBufferNode.onended = () => this.onended();
|
|
838
|
+
this.playStartTime = this.context.currentTime;
|
|
839
|
+
this.running = true;
|
|
840
|
+
// unfortunately Web Audio API uses time values not frames
|
|
841
|
+
let ac = this._audioClip;
|
|
842
|
+
let offset = 0;
|
|
843
|
+
if (ac && ac.selection) {
|
|
844
|
+
let s = ac.selection;
|
|
845
|
+
let sr = ac.audioDataHolder.sampleRate;
|
|
846
|
+
offset = s.leftFrame / sr;
|
|
847
|
+
let stopPosInsecs = s.rightFrame / sr;
|
|
848
|
+
let dur = stopPosInsecs - offset;
|
|
849
|
+
// TODO check valid values
|
|
850
|
+
this.sourceBufferNode.start(0, offset, dur);
|
|
851
|
+
}
|
|
852
|
+
else {
|
|
853
|
+
this.sourceBufferNode.start();
|
|
854
|
+
}
|
|
855
|
+
this.playStartTime = this.context.currentTime - offset;
|
|
856
|
+
this._startAction.disabled = true;
|
|
857
|
+
this._startSelectionAction.disabled = true;
|
|
858
|
+
this._stopAction.disabled = false;
|
|
859
|
+
//this.timerVar = window.setInterval((e)=>this.updatePlayPosition(), 200);
|
|
860
|
+
if (this.listener) {
|
|
861
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.STARTED));
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
else if (this._arrayAudioBuffer) {
|
|
865
|
+
if (this._arrayAudioBuffer) {
|
|
866
|
+
let aabsn = new ArrayAudioBufferSourceNode(this.context);
|
|
867
|
+
this.sourceAudioWorkletNode = aabsn;
|
|
868
|
+
aabsn.onprocessorerror = (ev) => {
|
|
869
|
+
let msg = 'Unknwon error';
|
|
870
|
+
if (ev instanceof ErrorEvent) {
|
|
871
|
+
msg = ev.message;
|
|
872
|
+
}
|
|
873
|
+
console.error("Audio source worklet error: " + msg);
|
|
874
|
+
if (this.listener) {
|
|
875
|
+
// TODO
|
|
876
|
+
// this.listener.error(msg);
|
|
877
|
+
// this.listener.audioPlayerUpdate(new AudioPlayerEvent());
|
|
878
|
+
}
|
|
879
|
+
};
|
|
880
|
+
aabsn.arrayAudioBuffer = this._arrayAudioBuffer;
|
|
881
|
+
aabsn.connect(this.context.destination); // this already starts playing
|
|
882
|
+
aabsn.onended = () => this.onended();
|
|
883
|
+
this.playStartTime = this.context.currentTime;
|
|
884
|
+
this.running = true;
|
|
885
|
+
let ac = this._audioClip;
|
|
886
|
+
let offset = 0;
|
|
887
|
+
if (ac && ac.selection) {
|
|
888
|
+
let s = ac.selection;
|
|
889
|
+
let sr = ac.audioDataHolder.sampleRate;
|
|
890
|
+
offset = s.leftFrame / sr;
|
|
891
|
+
let stopPosInsecs = s.rightFrame / sr;
|
|
892
|
+
let dur = stopPosInsecs - offset;
|
|
893
|
+
aabsn.start(0, offset, dur);
|
|
894
|
+
}
|
|
895
|
+
else {
|
|
896
|
+
aabsn.start();
|
|
897
|
+
}
|
|
898
|
+
this.playStartTime = this.context.currentTime - offset;
|
|
899
|
+
this._startAction.disabled = true;
|
|
900
|
+
this._startSelectionAction.disabled = true;
|
|
901
|
+
this._stopAction.disabled = false;
|
|
902
|
+
if (this.listener) {
|
|
903
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.STARTED));
|
|
904
|
+
}
|
|
905
|
+
}
|
|
270
906
|
}
|
|
271
907
|
}
|
|
272
908
|
}
|
|
@@ -275,6 +911,9 @@ class AudioPlayer {
|
|
|
275
911
|
if (this.sourceBufferNode) {
|
|
276
912
|
this.sourceBufferNode.stop();
|
|
277
913
|
}
|
|
914
|
+
if (this.sourceAudioWorkletNode) {
|
|
915
|
+
this.sourceAudioWorkletNode.stop();
|
|
916
|
+
}
|
|
278
917
|
if (this.timerVar !== null) {
|
|
279
918
|
window.clearInterval(this.timerVar);
|
|
280
919
|
}
|
|
@@ -288,7 +927,7 @@ class AudioPlayer {
|
|
|
288
927
|
if (this.timerVar != null) {
|
|
289
928
|
window.clearInterval(this.timerVar);
|
|
290
929
|
}
|
|
291
|
-
this._startAction.disabled = !(this.audioBuffer);
|
|
930
|
+
this._startAction.disabled = !(this.audioBuffer || this.arrayAudioBuffer);
|
|
292
931
|
this._startSelectionAction.disabled = this.startSelectionDisabled();
|
|
293
932
|
this._stopAction.disabled = true;
|
|
294
933
|
this.running = false;
|
|
@@ -305,10 +944,17 @@ class AudioPlayer {
|
|
|
305
944
|
}
|
|
306
945
|
get playPositionFrames() {
|
|
307
946
|
let ppFrs = null;
|
|
947
|
+
let sr = null;
|
|
308
948
|
if (this._audioBuffer) {
|
|
949
|
+
sr = this._audioBuffer.sampleRate;
|
|
950
|
+
}
|
|
951
|
+
else if (this._arrayAudioBuffer) {
|
|
952
|
+
sr = this._arrayAudioBuffer.sampleRate;
|
|
953
|
+
}
|
|
954
|
+
if (sr) {
|
|
309
955
|
let ppTime = this.playPositionTime;
|
|
310
956
|
if (ppTime !== null) {
|
|
311
|
-
ppFrs =
|
|
957
|
+
ppFrs = sr * ppTime;
|
|
312
958
|
}
|
|
313
959
|
}
|
|
314
960
|
return ppFrs;
|
|
@@ -522,6 +1168,107 @@ class ProjectUtil {
|
|
|
522
1168
|
}
|
|
523
1169
|
ProjectUtil.DEFAULT_AUDIO_CHANNEL_COUNT = 2;
|
|
524
1170
|
|
|
1171
|
+
class ArrayAudioBuffer {
|
|
1172
|
+
constructor(_channelCount, _sampleRate, _data) {
|
|
1173
|
+
this._channelCount = _channelCount;
|
|
1174
|
+
this._sampleRate = _sampleRate;
|
|
1175
|
+
this._data = _data;
|
|
1176
|
+
this._chunkCount = 0;
|
|
1177
|
+
this._frameLen = 0;
|
|
1178
|
+
if (this._data.length > 0) {
|
|
1179
|
+
let ch0Data = this.data[0];
|
|
1180
|
+
for (let ch0Chk of ch0Data) {
|
|
1181
|
+
this._chunkCount++;
|
|
1182
|
+
this._frameLen += ch0Chk.length;
|
|
1183
|
+
}
|
|
1184
|
+
}
|
|
1185
|
+
}
|
|
1186
|
+
static fromAudioBuffer(audioBuffer, chunkFrameSize = 8192) {
|
|
1187
|
+
let aab;
|
|
1188
|
+
let chs = audioBuffer.numberOfChannels;
|
|
1189
|
+
let frameLength = audioBuffer.length;
|
|
1190
|
+
//let chunksSize=Math.ceil(frameLength/chunkFrameSize);
|
|
1191
|
+
let framePos = 0;
|
|
1192
|
+
let data = new Array(chs);
|
|
1193
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
1194
|
+
data[ch] = new Array();
|
|
1195
|
+
}
|
|
1196
|
+
let toCopy = frameLength - framePos;
|
|
1197
|
+
while (toCopy > 0) {
|
|
1198
|
+
let toCopyChunk = chunkFrameSize;
|
|
1199
|
+
if (toCopyChunk > toCopy) {
|
|
1200
|
+
// last chunk, the rest
|
|
1201
|
+
toCopyChunk = toCopy;
|
|
1202
|
+
}
|
|
1203
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
1204
|
+
data[ch].push(audioBuffer.getChannelData(ch).slice(framePos, framePos + toCopyChunk));
|
|
1205
|
+
}
|
|
1206
|
+
framePos += toCopyChunk;
|
|
1207
|
+
toCopy -= toCopyChunk;
|
|
1208
|
+
}
|
|
1209
|
+
aab = new ArrayAudioBuffer(chs, audioBuffer.sampleRate, data);
|
|
1210
|
+
return aab;
|
|
1211
|
+
}
|
|
1212
|
+
get channelCount() {
|
|
1213
|
+
return this._channelCount;
|
|
1214
|
+
}
|
|
1215
|
+
frames(framePos, frameLen, bufs) {
|
|
1216
|
+
let ccFramePos = 0;
|
|
1217
|
+
let trgFramePos = framePos;
|
|
1218
|
+
let ch0Data = this.data[0];
|
|
1219
|
+
let cPos = 0;
|
|
1220
|
+
let filled = 0;
|
|
1221
|
+
let ci = 0;
|
|
1222
|
+
while (filled < frameLen && ci < this._chunkCount) {
|
|
1223
|
+
// Current chunk
|
|
1224
|
+
let cc0 = ch0Data[ci];
|
|
1225
|
+
let ccLen = cc0.length;
|
|
1226
|
+
let ccFrameEndPos = ccFramePos + ccLen;
|
|
1227
|
+
if (trgFramePos >= ccFramePos && trgFramePos < ccFrameEndPos) {
|
|
1228
|
+
let toCp = frameLen - filled;
|
|
1229
|
+
cPos = trgFramePos - ccFramePos;
|
|
1230
|
+
if (cPos + toCp > ccLen) {
|
|
1231
|
+
toCp = ccLen - cPos;
|
|
1232
|
+
}
|
|
1233
|
+
for (let ch = 0; ch < bufs.length; ch++) {
|
|
1234
|
+
let cc = this.data[ch][ci];
|
|
1235
|
+
for (let i = 0; i < toCp; i++) {
|
|
1236
|
+
bufs[ch][filled + i] = cc[cPos + i];
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
filled += toCp;
|
|
1240
|
+
trgFramePos += toCp;
|
|
1241
|
+
cPos += toCp;
|
|
1242
|
+
ccFramePos += toCp;
|
|
1243
|
+
if (cPos >= ccLen) {
|
|
1244
|
+
ccFramePos = ccFrameEndPos;
|
|
1245
|
+
cPos = 0;
|
|
1246
|
+
ci++;
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
else {
|
|
1250
|
+
// next chunk
|
|
1251
|
+
ccFramePos = ccFrameEndPos;
|
|
1252
|
+
cPos = 0;
|
|
1253
|
+
ci++;
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
return filled;
|
|
1257
|
+
}
|
|
1258
|
+
get sampleRate() {
|
|
1259
|
+
return this._sampleRate;
|
|
1260
|
+
}
|
|
1261
|
+
get frameLen() {
|
|
1262
|
+
return this._frameLen;
|
|
1263
|
+
}
|
|
1264
|
+
get chunkCount() {
|
|
1265
|
+
return this._chunkCount;
|
|
1266
|
+
}
|
|
1267
|
+
get data() {
|
|
1268
|
+
return this._data;
|
|
1269
|
+
}
|
|
1270
|
+
}
|
|
1271
|
+
|
|
525
1272
|
const CHROME_ACTIVATE_ECHO_CANCELLATION_WITH_AGC = false;
|
|
526
1273
|
const DEBUG_TRACE_LEVEL = 0;
|
|
527
1274
|
const ENABLE_AUDIO_WORKLET = true;
|
|
@@ -1092,6 +1839,10 @@ class AudioCapture {
|
|
|
1092
1839
|
}
|
|
1093
1840
|
return ab;
|
|
1094
1841
|
}
|
|
1842
|
+
audioBufferArray() {
|
|
1843
|
+
let aba = new ArrayAudioBuffer(this.channelCount, this.currentSampleRate, this.data);
|
|
1844
|
+
return aba;
|
|
1845
|
+
}
|
|
1095
1846
|
}
|
|
1096
1847
|
AudioCapture.BUFFER_SIZE = 8192;
|
|
1097
1848
|
|
|
@@ -1471,21 +2222,28 @@ class RecordingFileDescriptorImpl {
|
|
|
1471
2222
|
constructor() { }
|
|
1472
2223
|
}
|
|
1473
2224
|
class RecordingFile {
|
|
1474
|
-
constructor(uuid, sessionId,
|
|
2225
|
+
constructor(uuid, sessionId, audioDataHolder) {
|
|
1475
2226
|
this.recordingFileId = null;
|
|
1476
2227
|
this.uuid = null;
|
|
2228
|
+
this.serverPersisted = false;
|
|
2229
|
+
this.keepAudioDataCache = false;
|
|
1477
2230
|
this.date = null;
|
|
1478
2231
|
this._dateAsDateObj = null;
|
|
1479
2232
|
this.startedDate = null;
|
|
1480
2233
|
this._startedAsDateObj = null;
|
|
1481
|
-
this.
|
|
2234
|
+
this.audioDataHolder = null;
|
|
1482
2235
|
this.session = null;
|
|
1483
2236
|
this.frames = null;
|
|
2237
|
+
this.timeLength = null;
|
|
1484
2238
|
this.editSampleRate = null;
|
|
1485
2239
|
this.editStartFrame = null;
|
|
1486
2240
|
this.editEndFrame = null;
|
|
1487
2241
|
this.session = sessionId;
|
|
1488
|
-
this.
|
|
2242
|
+
this.audioDataHolder = audioDataHolder;
|
|
2243
|
+
if (audioDataHolder) {
|
|
2244
|
+
this.frames = audioDataHolder.frameLen;
|
|
2245
|
+
this.timeLength = audioDataHolder.duration;
|
|
2246
|
+
}
|
|
1489
2247
|
this.uuid = uuid;
|
|
1490
2248
|
}
|
|
1491
2249
|
filenameString() {
|
|
@@ -1497,14 +2255,27 @@ class RecordingFile {
|
|
|
1497
2255
|
fns += this.uuid;
|
|
1498
2256
|
return fns;
|
|
1499
2257
|
}
|
|
2258
|
+
equals(otherRecordingFile) {
|
|
2259
|
+
if (otherRecordingFile !== null) {
|
|
2260
|
+
if (otherRecordingFile === this) {
|
|
2261
|
+
return true;
|
|
2262
|
+
}
|
|
2263
|
+
if (otherRecordingFile.uuid === this.uuid) {
|
|
2264
|
+
return true;
|
|
2265
|
+
}
|
|
2266
|
+
}
|
|
2267
|
+
return false;
|
|
2268
|
+
}
|
|
2269
|
+
toString() {
|
|
2270
|
+
return 'Recording file: UUID: ' + this.uuid + ', session: ' + this.session;
|
|
2271
|
+
}
|
|
1500
2272
|
}
|
|
1501
2273
|
class SprRecordingFile extends RecordingFile {
|
|
1502
|
-
constructor(sessionId, itemcode, version,
|
|
1503
|
-
super(UUID.generate(), sessionId,
|
|
2274
|
+
constructor(sessionId, itemcode, version, audioDataHolder) {
|
|
2275
|
+
super(UUID.generate(), sessionId, audioDataHolder);
|
|
1504
2276
|
this.session = sessionId;
|
|
1505
2277
|
this.itemCode = itemcode;
|
|
1506
2278
|
this.version = version;
|
|
1507
|
-
this.audioBuffer = audioBuffer;
|
|
1508
2279
|
}
|
|
1509
2280
|
filenameString() {
|
|
1510
2281
|
let fns = '';
|
|
@@ -1519,6 +2290,31 @@ class SprRecordingFile extends RecordingFile {
|
|
|
1519
2290
|
fns += this.uuid;
|
|
1520
2291
|
return fns;
|
|
1521
2292
|
}
|
|
2293
|
+
toString() {
|
|
2294
|
+
return 'Recording file: UUID: ' + this.uuid + ', session: ' + this.session + ', itemcode: ' + this.itemCode + ', version: ' + this.version + ', UUID: ' + this.uuid;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
class RecordingFileUtils {
|
|
2298
|
+
static setAudioData(rf, audioDataHolder) {
|
|
2299
|
+
rf.audioDataHolder = audioDataHolder;
|
|
2300
|
+
if (audioDataHolder) {
|
|
2301
|
+
rf.frames = audioDataHolder.frameLen;
|
|
2302
|
+
rf.timeLength = audioDataHolder.duration;
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
static sampleCount(rf) {
|
|
2306
|
+
if (rf.audioDataHolder) {
|
|
2307
|
+
return rf.audioDataHolder.sampleCounts();
|
|
2308
|
+
}
|
|
2309
|
+
else {
|
|
2310
|
+
return 0;
|
|
2311
|
+
}
|
|
2312
|
+
}
|
|
2313
|
+
static expireAudioData(rf) {
|
|
2314
|
+
let rv = rf.audioDataHolder;
|
|
2315
|
+
rf.audioDataHolder = null;
|
|
2316
|
+
return rv;
|
|
2317
|
+
}
|
|
1522
2318
|
}
|
|
1523
2319
|
|
|
1524
2320
|
// state of an upload
|
|
@@ -1569,7 +2365,8 @@ class UploaderStatusChangeEvent {
|
|
|
1569
2365
|
}
|
|
1570
2366
|
}
|
|
1571
2367
|
class Upload {
|
|
1572
|
-
constructor(blob, url) {
|
|
2368
|
+
constructor(blob, url, serverPersistable = null) {
|
|
2369
|
+
this.serverPersistable = serverPersistable;
|
|
1573
2370
|
this.toString = () => {
|
|
1574
2371
|
let s = `Upload: Status: ${this.status}, URL: ${this._url}`;
|
|
1575
2372
|
if (this._data instanceof Blob) {
|
|
@@ -1590,6 +2387,17 @@ class Upload {
|
|
|
1590
2387
|
get data() {
|
|
1591
2388
|
return this._data;
|
|
1592
2389
|
}
|
|
2390
|
+
done() {
|
|
2391
|
+
this.status = UploadStatus$1.DONE;
|
|
2392
|
+
//console.debug("Single upload done.");
|
|
2393
|
+
if (this.serverPersistable) {
|
|
2394
|
+
this.serverPersistable.serverPersisted = true;
|
|
2395
|
+
//console.debug("Single upload set server persisted: "+this.serverPersistable);
|
|
2396
|
+
}
|
|
2397
|
+
else {
|
|
2398
|
+
//console.debug("Server persistable not set.");
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
1593
2401
|
}
|
|
1594
2402
|
class Uploader {
|
|
1595
2403
|
constructor(http, withCredentials = false) {
|
|
@@ -1628,7 +2436,7 @@ class Uploader {
|
|
|
1628
2436
|
return si;
|
|
1629
2437
|
}
|
|
1630
2438
|
uploadDone(ul) {
|
|
1631
|
-
ul.
|
|
2439
|
+
ul.done();
|
|
1632
2440
|
// remove upload from queue
|
|
1633
2441
|
for (let i = 0; i < this.que.length; i++) {
|
|
1634
2442
|
if (this.que[i] === ul) {
|
|
@@ -2063,16 +2871,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
2063
2871
|
}], ctorParameters: function () { return []; } });
|
|
2064
2872
|
|
|
2065
2873
|
class AudioClip {
|
|
2066
|
-
constructor(
|
|
2874
|
+
constructor(_audioDataHolder) {
|
|
2875
|
+
this._audioDataHolder = _audioDataHolder;
|
|
2067
2876
|
this._selection = null;
|
|
2068
2877
|
this._levelInfos = null;
|
|
2069
2878
|
this.selectionObservers = new Array();
|
|
2070
|
-
this._buffer = buffer;
|
|
2071
2879
|
}
|
|
2072
|
-
get
|
|
2073
|
-
return this.
|
|
2880
|
+
get audioDataHolder() {
|
|
2881
|
+
return this._audioDataHolder;
|
|
2074
2882
|
}
|
|
2075
|
-
;
|
|
2076
2883
|
get selection() {
|
|
2077
2884
|
return this._selection;
|
|
2078
2885
|
}
|
|
@@ -2175,19 +2982,32 @@ class ViewSelection {
|
|
|
2175
2982
|
class BasicAudioCanvasLayerComponent extends CanvasLayerComponent {
|
|
2176
2983
|
constructor() {
|
|
2177
2984
|
super(...arguments);
|
|
2178
|
-
|
|
2985
|
+
//protected _audioData: AudioBuffer|null=null;
|
|
2986
|
+
//protected _arrayAudioData: ArrayAudioBuffer|null=null;
|
|
2987
|
+
this._audioDataHolder = null;
|
|
2179
2988
|
this._bgColor = 'white';
|
|
2180
2989
|
this._selectColor = 'rgba(0%,0%,100%,25%)';
|
|
2181
2990
|
}
|
|
2991
|
+
frameLength() {
|
|
2992
|
+
let frameLength = null;
|
|
2993
|
+
// if (this._audioData && this._audioData.numberOfChannels > 0) {
|
|
2994
|
+
// let ch0 = this._audioData.getChannelData(0);
|
|
2995
|
+
// frameLength = ch0.length;
|
|
2996
|
+
//
|
|
2997
|
+
// }else if(this._arrayAudioData){
|
|
2998
|
+
// frameLength=this._arrayAudioData.frameLen;
|
|
2999
|
+
// }
|
|
3000
|
+
return frameLength;
|
|
3001
|
+
}
|
|
2182
3002
|
/**
|
|
2183
3003
|
* Returns pixel position depending on current zoom setting.
|
|
2184
3004
|
* @param framePos audio frame (sample) position
|
|
2185
3005
|
*/
|
|
2186
3006
|
frameToXPixelPosition(framePos) {
|
|
3007
|
+
var _a;
|
|
2187
3008
|
let pixelPos = null;
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
let frameLength = ch0.length;
|
|
3009
|
+
let frameLength = (_a = this._audioDataHolder) === null || _a === void 0 ? void 0 : _a.frameLen;
|
|
3010
|
+
if (frameLength !== undefined) {
|
|
2191
3011
|
let vw;
|
|
2192
3012
|
if (this.bounds) {
|
|
2193
3013
|
vw = this.bounds.dimension.width;
|
|
@@ -2216,10 +3036,10 @@ class BasicAudioCanvasLayerComponent extends CanvasLayerComponent {
|
|
|
2216
3036
|
}
|
|
2217
3037
|
}
|
|
2218
3038
|
viewPortXPixelToFramePosition(xViewPortPixelPos) {
|
|
3039
|
+
var _a;
|
|
2219
3040
|
let vpXramePos = null;
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
let frameLength = ch0.length;
|
|
3041
|
+
let frameLength = (_a = this._audioDataHolder) === null || _a === void 0 ? void 0 : _a.frameLen;
|
|
3042
|
+
if (frameLength !== undefined) {
|
|
2223
3043
|
let vw;
|
|
2224
3044
|
if (this.bounds) {
|
|
2225
3045
|
vw = this.bounds.dimension.width;
|
|
@@ -2396,8 +3216,8 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2396
3216
|
if (viewSel) {
|
|
2397
3217
|
let frameStart = this.viewPortXPixelToFramePosition(viewSel.startX);
|
|
2398
3218
|
let frameEnd = this.viewPortXPixelToFramePosition(viewSel.endX);
|
|
2399
|
-
if (this.
|
|
2400
|
-
ns = new Selection(this.
|
|
3219
|
+
if (this._audioDataHolder && frameStart != null && frameEnd != null) {
|
|
3220
|
+
ns = new Selection(this._audioDataHolder.sampleRate, frameStart, frameEnd);
|
|
2401
3221
|
}
|
|
2402
3222
|
}
|
|
2403
3223
|
this.selectingEventEmitter.emit(ns);
|
|
@@ -2407,8 +3227,8 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2407
3227
|
if (viewSel) {
|
|
2408
3228
|
let frameStart = this.viewPortXPixelToFramePosition(viewSel.startX);
|
|
2409
3229
|
let frameEnd = this.viewPortXPixelToFramePosition(viewSel.endX);
|
|
2410
|
-
if (this.
|
|
2411
|
-
ns = new Selection(this.
|
|
3230
|
+
if (this._audioDataHolder && frameStart != null && frameEnd != null) {
|
|
3231
|
+
ns = new Selection(this._audioDataHolder.sampleRate, frameStart, frameEnd);
|
|
2412
3232
|
}
|
|
2413
3233
|
}
|
|
2414
3234
|
this.selectedEventEmitter.emit(ns);
|
|
@@ -2489,7 +3309,7 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2489
3309
|
g.lineTo(xViewPortPixelpos, h);
|
|
2490
3310
|
g.closePath();
|
|
2491
3311
|
g.stroke();
|
|
2492
|
-
if (this.
|
|
3312
|
+
if (this._audioDataHolder) {
|
|
2493
3313
|
g.font = '14px sans-serif';
|
|
2494
3314
|
g.fillStyle = 'yellow';
|
|
2495
3315
|
g.fillText(framePos.toString(), xViewPortPixelpos + 2, 50);
|
|
@@ -2501,6 +3321,7 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2501
3321
|
}
|
|
2502
3322
|
}
|
|
2503
3323
|
}
|
|
3324
|
+
AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD = 10 * 60 * 48000; // Use streaming/chunking if audio clip has more than this number of samples
|
|
2504
3325
|
AudioCanvasLayerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AudioCanvasLayerComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
2505
3326
|
AudioCanvasLayerComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "12.0.0", version: "13.3.11", type: AudioCanvasLayerComponent, inputs: { pointerPosition: "pointerPosition", selecting: "selecting", selection: "selection" }, outputs: { pointerPositionEventEmitter: "pointerPositionEventEmitter", selectingEventEmitter: "selectingEventEmitter", selectedEventEmitter: "selectedEventEmitter" }, host: { listeners: { "document:mouseup": "onMouseup($event)" } }, viewQueries: [{ propertyName: "bgCanvasRef", first: true, predicate: ["bg"], descendants: true, static: true }, { propertyName: "cursorCanvasRef", first: true, predicate: ["cursor"], descendants: true, static: true }], usesInheritance: true, ngImport: i0 });
|
|
2506
3327
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AudioCanvasLayerComponent, decorators: [{
|
|
@@ -2535,7 +3356,7 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2535
3356
|
this._playFramePosition = null;
|
|
2536
3357
|
this.worker = null;
|
|
2537
3358
|
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
2538
|
-
this.
|
|
3359
|
+
this._audioDataHolder = null;
|
|
2539
3360
|
this._bgColor = 'black';
|
|
2540
3361
|
this._selectColor = 'rgba(255,255,0,0.8)';
|
|
2541
3362
|
}
|
|
@@ -2588,25 +3409,26 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2588
3409
|
*/
|
|
2589
3410
|
workerFunction() {
|
|
2590
3411
|
addEventListener('message', ({ data }) => {
|
|
2591
|
-
let audioData = data.audioData;
|
|
2592
|
-
let
|
|
2593
|
-
let
|
|
2594
|
-
let
|
|
2595
|
-
let vw = data.vw;
|
|
2596
|
-
let chs = data.chs;
|
|
2597
|
-
let
|
|
3412
|
+
let audioData = data.audioData; // audio data part required to render view port
|
|
3413
|
+
let auOffset = data.audioDataOffset;
|
|
3414
|
+
let l = data.l; // left pixel position of view port
|
|
3415
|
+
let w = data.w; // width of viewport
|
|
3416
|
+
let vw = data.vw; // total width of (virtual) audio view (not viewport width)
|
|
3417
|
+
let chs = data.chs; // number of channels
|
|
3418
|
+
let dataFrameLength = data.audioDataFrameLength; // frame length of audio data part required for view port
|
|
3419
|
+
let frameLength = data.frameLength; // total frame length (of audio clip)
|
|
3420
|
+
//console.debug("W: left: "+l+", w:"+w+", vw: "+vw+", chs: "+chs+", frameLength: "+frameLength);
|
|
2598
3421
|
let psMinMax = new Float32Array(0);
|
|
2599
|
-
if (audioData && w >= 0 && vw > 0) {
|
|
3422
|
+
if (audioData && audioData.length > 0 && w >= 0 && vw > 0) {
|
|
2600
3423
|
let framesPerPixel = frameLength / vw;
|
|
2601
|
-
let y = 0;
|
|
2602
3424
|
let pointsLen = w * chs;
|
|
2603
3425
|
// one for min one for max
|
|
2604
3426
|
let arrLen = pointsLen * 2;
|
|
2605
3427
|
psMinMax = new Float32Array(arrLen);
|
|
2606
3428
|
let chFramePos = 0;
|
|
3429
|
+
let chFrameLength = audioData.length / chs;
|
|
2607
3430
|
for (let ch = 0; ch < chs; ch++) {
|
|
2608
|
-
|
|
2609
|
-
chFramePos = ch * frameLength;
|
|
3431
|
+
chFramePos = ch * chFrameLength;
|
|
2610
3432
|
for (let pii = 0; pii < w; pii++) {
|
|
2611
3433
|
let virtPii = l + pii;
|
|
2612
3434
|
let pMin = Infinity;
|
|
@@ -2616,24 +3438,28 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2616
3438
|
for (let ai = 0; ai < framesPerPixel; ai++) {
|
|
2617
3439
|
let framePos = pixelFramePos + ai;
|
|
2618
3440
|
let a = 0;
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
|
|
3441
|
+
let bufPos = framePos - auOffset;
|
|
3442
|
+
//let bufPos=framePos;
|
|
3443
|
+
if (bufPos >= 0 && bufPos < audioData.length) {
|
|
3444
|
+
a = audioData[bufPos];
|
|
3445
|
+
//console.debug("W: ch: "+ch+", pixelFramePos: "+pixelFramePos+", framePos: "+framePos+", auOffset: "+auOffset+", bufPos: "+bufPos+", audioData.length: "+audioData.length+", a: "+a);
|
|
3446
|
+
if (a < pMin) {
|
|
3447
|
+
pMin = a;
|
|
3448
|
+
}
|
|
3449
|
+
if (a > pMax) {
|
|
3450
|
+
pMax = a;
|
|
3451
|
+
}
|
|
2627
3452
|
}
|
|
2628
3453
|
}
|
|
2629
3454
|
let psMinPos = ch * w + pii;
|
|
2630
3455
|
psMinMax[psMinPos] = pMin;
|
|
2631
3456
|
let psMaxPos = pointsLen + psMinPos;
|
|
2632
3457
|
psMinMax[psMaxPos] = pMax;
|
|
3458
|
+
//console.debug("psMinMax["+psMinPos+"]="+pMin+",psMinMax["+psMaxPos+"]="+pMax);
|
|
2633
3459
|
}
|
|
2634
3460
|
}
|
|
2635
3461
|
}
|
|
2636
|
-
postMessage({ psMinMax: psMinMax, l: data.l,
|
|
3462
|
+
postMessage({ psMinMax: psMinMax, l: data.l, w: data.w, chs: data.chs, eod: data.eod }, [psMinMax.buffer]);
|
|
2637
3463
|
});
|
|
2638
3464
|
}
|
|
2639
3465
|
startDraw(clear = true) {
|
|
@@ -2661,41 +3487,143 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2661
3487
|
if (this.bounds && this.bounds.dimension) {
|
|
2662
3488
|
let w = Math.round(this.bounds.dimension.width);
|
|
2663
3489
|
let h = Math.round(this.bounds.dimension.height);
|
|
2664
|
-
if (this.
|
|
3490
|
+
if (this._audioDataHolder && w > 0 && h > 0) {
|
|
2665
3491
|
//this.wo = new Worker('./audiosignal.worker.js',{type: 'module'});
|
|
2666
3492
|
this.worker = new Worker(this.workerURL);
|
|
2667
3493
|
//this.wo = new Worker('worker/audiosignal.worker.ts');
|
|
2668
3494
|
//let Worker = require('worker!../../../workers/uploader/main');
|
|
2669
|
-
let chs = this.
|
|
2670
|
-
let
|
|
2671
|
-
|
|
2672
|
-
|
|
2673
|
-
|
|
2674
|
-
let
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
2678
|
-
//let
|
|
3495
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
3496
|
+
let leftPos = Math.round(this.bounds.position.left);
|
|
3497
|
+
let renderPos = leftPos;
|
|
3498
|
+
let vw = Math.round(this.virtualDimension.width);
|
|
3499
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
3500
|
+
let framesPerPixel = Math.ceil(frameLength / vw);
|
|
3501
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
3502
|
+
//let arrayAudioBuffer=this._audioDataHolder.arrayBuffer;
|
|
3503
|
+
let arrAbBuf;
|
|
3504
|
+
//let ais:ArrayAudioBufferInputStream|null=null;
|
|
3505
|
+
//let aisBuf:Float32Array[]|null=null;
|
|
3506
|
+
let psMinMax = null;
|
|
2679
3507
|
if (this.worker) {
|
|
2680
3508
|
this.worker.onmessage = (me) => {
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
3509
|
+
if (me.data.eod === true) {
|
|
3510
|
+
let psMinMaxTmp;
|
|
3511
|
+
if (psMinMax) {
|
|
3512
|
+
psMinMaxTmp = psMinMax;
|
|
3513
|
+
}
|
|
3514
|
+
else {
|
|
3515
|
+
psMinMaxTmp = me.data.psMinMax;
|
|
3516
|
+
}
|
|
3517
|
+
this.drawRendered(leftPos, w, h, chs, psMinMaxTmp);
|
|
3518
|
+
if (this.worker) {
|
|
3519
|
+
this.worker.terminate();
|
|
3520
|
+
}
|
|
3521
|
+
this.worker = null;
|
|
3522
|
+
}
|
|
3523
|
+
else if (this._audioDataHolder && arrAbBuf) {
|
|
3524
|
+
let rw = me.data.w;
|
|
3525
|
+
let rPointsLen = chs * rw;
|
|
3526
|
+
let pointsLen = chs * w;
|
|
3527
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3528
|
+
if (psMinMax) {
|
|
3529
|
+
let rBasePos = ch * rw;
|
|
3530
|
+
let basePos = ch * w;
|
|
3531
|
+
let rPosMin = rBasePos;
|
|
3532
|
+
let rPosMax = rPointsLen + rPosMin;
|
|
3533
|
+
let posMin = basePos + (renderPos - leftPos);
|
|
3534
|
+
let posMax = pointsLen + posMin;
|
|
3535
|
+
psMinMax[posMin] = me.data.psMinMax[rPosMin];
|
|
3536
|
+
//console.debug('Min: ('+pos+'): '+me.data.psMinMax[0]);
|
|
3537
|
+
psMinMax[posMax] = me.data.psMinMax[rPosMax];
|
|
3538
|
+
// console.debug('Max: ('+(pointsLen+pos)+'): '+me.data.psMinMax[1]);
|
|
3539
|
+
//console.debug("psMinMax["+posMin+"]="+me.data.psMinMax[rPosMin]+" (rPosMin="+rPosMin+"),psMinMax["+posMax+"]="+me.data.psMinMax[rPosMax]);
|
|
3540
|
+
}
|
|
3541
|
+
}
|
|
3542
|
+
let eod = false;
|
|
3543
|
+
renderPos++;
|
|
3544
|
+
let ad;
|
|
3545
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw);
|
|
3546
|
+
if (renderPos < leftPos + w) {
|
|
3547
|
+
let read = this._audioDataHolder.frames(leftFramePos, framesPerPixel, arrAbBuf);
|
|
3548
|
+
//console.debug("First read frame: "+arrAbBuf[0][0]);
|
|
3549
|
+
ad = new Float32Array(chs * framesPerPixel);
|
|
3550
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3551
|
+
ad.set(arrAbBuf[ch], ch * framesPerPixel);
|
|
3552
|
+
}
|
|
3553
|
+
eod = (read <= 0);
|
|
3554
|
+
}
|
|
3555
|
+
else {
|
|
3556
|
+
ad = new Float32Array();
|
|
3557
|
+
eod = true;
|
|
3558
|
+
}
|
|
3559
|
+
let adBuf = ad.buffer;
|
|
3560
|
+
if (this.worker) {
|
|
3561
|
+
this.worker.postMessage({
|
|
3562
|
+
l: renderPos,
|
|
3563
|
+
w: me.data.w,
|
|
3564
|
+
h: h,
|
|
3565
|
+
vw: vw,
|
|
3566
|
+
chs: chs,
|
|
3567
|
+
frameLength: frameLength,
|
|
3568
|
+
audioData: ad,
|
|
3569
|
+
audioDataOffset: leftFramePos,
|
|
3570
|
+
eod: eod
|
|
3571
|
+
}, [adBuf]);
|
|
3572
|
+
}
|
|
2685
3573
|
}
|
|
2686
|
-
this.worker = null;
|
|
2687
3574
|
};
|
|
2688
3575
|
}
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
|
|
2696
|
-
|
|
2697
|
-
|
|
2698
|
-
|
|
3576
|
+
if (audioBuffer && audioBuffer.length * audioBuffer.numberOfChannels < AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD) {
|
|
3577
|
+
// Render whole clip at once
|
|
3578
|
+
arrAbBuf = null;
|
|
3579
|
+
psMinMax = null;
|
|
3580
|
+
let ad = new Float32Array(chs * frameLength);
|
|
3581
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3582
|
+
ad.set(audioBuffer.getChannelData(ch), ch * frameLength);
|
|
3583
|
+
}
|
|
3584
|
+
this.worker.postMessage({
|
|
3585
|
+
l: leftPos,
|
|
3586
|
+
w: w,
|
|
3587
|
+
vw: vw,
|
|
3588
|
+
chs: chs,
|
|
3589
|
+
frameLength: frameLength,
|
|
3590
|
+
audioData: ad,
|
|
3591
|
+
audioDataOffset: 0,
|
|
3592
|
+
eod: true
|
|
3593
|
+
}, [ad.buffer]);
|
|
3594
|
+
}
|
|
3595
|
+
else {
|
|
3596
|
+
// Render pixel by pixel
|
|
3597
|
+
if (w > 0) {
|
|
3598
|
+
if (framesPerPixel > 0) {
|
|
3599
|
+
let rw = 1;
|
|
3600
|
+
//ais = new ArrayAudioBufferInputStream(arrayAudioBuffer);
|
|
3601
|
+
arrAbBuf = new Array(chs);
|
|
3602
|
+
psMinMax = new Float32Array(chs * w * 2);
|
|
3603
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3604
|
+
arrAbBuf[ch] = new Float32Array(framesPerPixel);
|
|
3605
|
+
}
|
|
3606
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw);
|
|
3607
|
+
let auOffset = leftFramePos; // should always be 0
|
|
3608
|
+
//let read=arrayAudioBuffer.frames(leftFramePos,framesPerPixel,arrAbBuf);
|
|
3609
|
+
let read = this._audioDataHolder.frames(leftFramePos, framesPerPixel, arrAbBuf);
|
|
3610
|
+
let ad = new Float32Array(chs * framesPerPixel);
|
|
3611
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3612
|
+
ad.set(arrAbBuf[ch], ch * framesPerPixel);
|
|
3613
|
+
}
|
|
3614
|
+
this.worker.postMessage({
|
|
3615
|
+
l: renderPos,
|
|
3616
|
+
w: rw,
|
|
3617
|
+
vw: vw,
|
|
3618
|
+
chs: chs,
|
|
3619
|
+
frameLength: frameLength,
|
|
3620
|
+
audioData: ad,
|
|
3621
|
+
audioDataOffset: auOffset,
|
|
3622
|
+
eod: (read <= 0)
|
|
3623
|
+
}, [ad.buffer]);
|
|
3624
|
+
}
|
|
3625
|
+
}
|
|
3626
|
+
}
|
|
2699
3627
|
}
|
|
2700
3628
|
else {
|
|
2701
3629
|
let g = this.signalCanvas.getContext("2d");
|
|
@@ -2705,42 +3633,42 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2705
3633
|
}
|
|
2706
3634
|
}
|
|
2707
3635
|
}
|
|
2708
|
-
drawRendered(
|
|
3636
|
+
drawRendered(left, w, h, chs, psMinMax) {
|
|
2709
3637
|
this.drawBg();
|
|
2710
|
-
this.signalCanvas.style.left =
|
|
2711
|
-
this.signalCanvas.width =
|
|
2712
|
-
this.signalCanvas.height =
|
|
3638
|
+
this.signalCanvas.style.left = left.toString() + 'px';
|
|
3639
|
+
this.signalCanvas.width = w;
|
|
3640
|
+
this.signalCanvas.height = h;
|
|
2713
3641
|
let g = this.signalCanvas.getContext("2d");
|
|
2714
3642
|
if (g) {
|
|
2715
|
-
g.clearRect(0, 0,
|
|
3643
|
+
g.clearRect(0, 0, w, h);
|
|
2716
3644
|
//g.fillStyle = "black";
|
|
2717
3645
|
//g.fillRect(0, 0, me.data.w, me.data.h);
|
|
2718
|
-
let pointsLen =
|
|
3646
|
+
let pointsLen = w * chs;
|
|
2719
3647
|
// one for min one for max
|
|
2720
3648
|
let arrLen = pointsLen * 2;
|
|
2721
|
-
if (this.
|
|
3649
|
+
if (this._audioDataHolder) {
|
|
2722
3650
|
let std = Date.now();
|
|
2723
|
-
let chH =
|
|
3651
|
+
let chH = h / chs;
|
|
2724
3652
|
let y = 0;
|
|
2725
|
-
for (let ch = 0; ch <
|
|
3653
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
2726
3654
|
let x = 0;
|
|
2727
|
-
let psMinPos = ch *
|
|
3655
|
+
let psMinPos = ch * w;
|
|
2728
3656
|
let psMaxPos = pointsLen + psMinPos;
|
|
2729
3657
|
g.fillStyle = 'green';
|
|
2730
3658
|
g.strokeStyle = 'green';
|
|
2731
3659
|
// draw audio signal as single polygon
|
|
2732
3660
|
g.beginPath();
|
|
2733
|
-
g.moveTo(0, y + (chH / 2) +
|
|
2734
|
-
for (let pii = 0; pii <
|
|
2735
|
-
let psMax =
|
|
3661
|
+
g.moveTo(0, y + (chH / 2) + psMinMax[psMaxPos] * chH / 2);
|
|
3662
|
+
for (let pii = 0; pii < w; pii++) {
|
|
3663
|
+
let psMax = psMinMax[psMaxPos + pii];
|
|
2736
3664
|
let pv = psMax * chH / 2;
|
|
2737
3665
|
let yd = y + (chH / 2) - pv;
|
|
2738
3666
|
//console.log("LineTo: : "+pii+" "+yd)
|
|
2739
3667
|
g.lineTo(pii, yd);
|
|
2740
3668
|
}
|
|
2741
|
-
let revPixelStart =
|
|
3669
|
+
let revPixelStart = w - 1;
|
|
2742
3670
|
for (let pii = revPixelStart; pii >= 0; pii--) {
|
|
2743
|
-
let psMin =
|
|
3671
|
+
let psMin = psMinMax[psMinPos + pii];
|
|
2744
3672
|
let pv = psMin * chH / 2;
|
|
2745
3673
|
let yd = y + (chH / 2) - pv;
|
|
2746
3674
|
//console.log("LineTo: : "+pii+" "+yd)
|
|
@@ -2764,13 +3692,23 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2764
3692
|
g.clearRect(0, 0, w, h);
|
|
2765
3693
|
//g.fillStyle = "black";
|
|
2766
3694
|
//g.fillRect(0, 0, w, h);
|
|
2767
|
-
if (this.
|
|
3695
|
+
if (this._audioDataHolder) {
|
|
2768
3696
|
let std = Date.now();
|
|
2769
|
-
let chs = this.
|
|
3697
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
2770
3698
|
let chH = h / chs;
|
|
2771
|
-
let frameLength = this.
|
|
3699
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
2772
3700
|
let framesPerPixel = frameLength / w;
|
|
2773
3701
|
let y = 0;
|
|
3702
|
+
let ais = null;
|
|
3703
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
3704
|
+
let aisBuffer = null;
|
|
3705
|
+
if (!audioBuffer) {
|
|
3706
|
+
ais = this._audioDataHolder.audioInputStream();
|
|
3707
|
+
aisBuffer = new Array(chs);
|
|
3708
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3709
|
+
aisBuffer[ch] = new Float32Array(framesPerPixel);
|
|
3710
|
+
}
|
|
3711
|
+
}
|
|
2774
3712
|
for (let ch = 0; ch < chs; ch++) {
|
|
2775
3713
|
let x = 0;
|
|
2776
3714
|
let psMin = new Float32Array(w);
|
|
@@ -2779,20 +3717,33 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2779
3717
|
for (let pii = 0; pii < w; pii++) {
|
|
2780
3718
|
let pMin = 0;
|
|
2781
3719
|
let pMax = 0;
|
|
2782
|
-
|
|
2783
|
-
|
|
2784
|
-
|
|
2785
|
-
|
|
2786
|
-
|
|
2787
|
-
pMin
|
|
3720
|
+
if (audioBuffer) {
|
|
3721
|
+
// calculate pixel min/max amplitude
|
|
3722
|
+
for (let ai = 0; ai < framesPerPixel; ai++) {
|
|
3723
|
+
//let framePos=(pii*framesPerPixel)+ai;
|
|
3724
|
+
let a = audioBuffer.getChannelData(ch)[framePos++];
|
|
3725
|
+
if (a < pMin) {
|
|
3726
|
+
pMin = a;
|
|
3727
|
+
}
|
|
3728
|
+
if (a > pMax) {
|
|
3729
|
+
pMax = a;
|
|
3730
|
+
}
|
|
2788
3731
|
}
|
|
2789
|
-
|
|
2790
|
-
|
|
3732
|
+
}
|
|
3733
|
+
else if (ais && aisBuffer) {
|
|
3734
|
+
let r = ais.read(aisBuffer);
|
|
3735
|
+
for (let ai = 0; ai < r; ai++) {
|
|
3736
|
+
let a = aisBuffer[ch][ai];
|
|
3737
|
+
if (a < pMin) {
|
|
3738
|
+
pMin = a;
|
|
3739
|
+
}
|
|
3740
|
+
if (a > pMax) {
|
|
3741
|
+
pMax = a;
|
|
3742
|
+
}
|
|
2791
3743
|
}
|
|
2792
3744
|
}
|
|
2793
3745
|
psMin[pii] = pMin;
|
|
2794
3746
|
psMax[pii] = pMax;
|
|
2795
|
-
//console.log("Min: ", pMin, " max: ", pMax);
|
|
2796
3747
|
}
|
|
2797
3748
|
g.fillStyle = 'green';
|
|
2798
3749
|
g.strokeStyle = 'green';
|
|
@@ -2817,12 +3768,11 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2817
3768
|
g.stroke();
|
|
2818
3769
|
y += chH;
|
|
2819
3770
|
}
|
|
2820
|
-
//this.drawPlayPosition();
|
|
2821
3771
|
}
|
|
2822
3772
|
}
|
|
2823
3773
|
}
|
|
2824
3774
|
setData(audioData) {
|
|
2825
|
-
this.
|
|
3775
|
+
this._audioDataHolder = audioData;
|
|
2826
3776
|
this.playFramePosition = 0;
|
|
2827
3777
|
}
|
|
2828
3778
|
}
|
|
@@ -3191,7 +4141,7 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3191
4141
|
this._playFramePosition = null;
|
|
3192
4142
|
this.dftSize = DEFAULT_DFT_SIZE;
|
|
3193
4143
|
this.worker = null;
|
|
3194
|
-
this.
|
|
4144
|
+
this._audioDataHolder = null;
|
|
3195
4145
|
this.markers = new Array();
|
|
3196
4146
|
this.dft = new DFTFloat32(this.dftSize);
|
|
3197
4147
|
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
@@ -3244,7 +4194,7 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3244
4194
|
g.lineTo(xViewPortPixelpos, h);
|
|
3245
4195
|
g.closePath();
|
|
3246
4196
|
g.stroke();
|
|
3247
|
-
if (this.
|
|
4197
|
+
if (this._audioDataHolder) {
|
|
3248
4198
|
let framePosRound = this.viewPortXPixelToFramePosition(xViewPortPixelpos);
|
|
3249
4199
|
if (framePosRound != null) {
|
|
3250
4200
|
g.font = '14px sans-serif';
|
|
@@ -3508,11 +4458,21 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3508
4458
|
}
|
|
3509
4459
|
GaussianWindow.DEFAULT_SIGMA = 0.3;
|
|
3510
4460
|
self.onmessage = function (msg) {
|
|
4461
|
+
//console.debug("Sonagram render thread");
|
|
3511
4462
|
let l = msg.data.l;
|
|
3512
4463
|
let w = msg.data.w;
|
|
3513
4464
|
let h = msg.data.h;
|
|
3514
4465
|
let vw = msg.data.vw;
|
|
3515
4466
|
let chs = msg.data.chs;
|
|
4467
|
+
let audioDataOffset = 0;
|
|
4468
|
+
let adOffset = msg.data.audioDataOffset;
|
|
4469
|
+
if (adOffset) {
|
|
4470
|
+
audioDataOffset = adOffset;
|
|
4471
|
+
}
|
|
4472
|
+
let maxPsd = null;
|
|
4473
|
+
if (msg.data.maxPsd !== undefined) {
|
|
4474
|
+
maxPsd = msg.data.maxPsd;
|
|
4475
|
+
}
|
|
3516
4476
|
let audioData = new Array(chs);
|
|
3517
4477
|
for (let ch = 0; ch < chs; ch++) {
|
|
3518
4478
|
audioData[ch] = new Float32Array(msg.data['audioData'][ch]);
|
|
@@ -3528,16 +4488,17 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3528
4488
|
}
|
|
3529
4489
|
let imgData = new Uint8ClampedArray(arrSize);
|
|
3530
4490
|
//console.log("Render method:");
|
|
3531
|
-
|
|
4491
|
+
//console.debug("Created imgData arrSize: "+arrSize+" ", w, "x", h);
|
|
4492
|
+
let calcMaxPsd = -Infinity;
|
|
4493
|
+
if (arrSize > 0) {
|
|
3532
4494
|
let chH = Math.round(h / chs);
|
|
3533
4495
|
let framesPerPixel = frameLength / vw;
|
|
3534
|
-
//console.
|
|
4496
|
+
//console.debug("Render: ", w, "x", h);
|
|
3535
4497
|
let b = new Float32Array(dftSize);
|
|
3536
4498
|
let sona = new Array(chs);
|
|
3537
|
-
let
|
|
3538
|
-
let p = 0;
|
|
4499
|
+
//let p = 0;
|
|
3539
4500
|
for (let ch = 0; ch < chs; ch++) {
|
|
3540
|
-
p = ch * frameLength;
|
|
4501
|
+
//p = ch * frameLength;
|
|
3541
4502
|
let chDataLen = audioData[ch].length;
|
|
3542
4503
|
let x = 0;
|
|
3543
4504
|
// initialize DFT array buffer
|
|
@@ -3554,8 +4515,13 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3554
4515
|
// initialize for negative sample positions and out of bounds positions
|
|
3555
4516
|
let chDat = 0;
|
|
3556
4517
|
// Set audio sample if available
|
|
3557
|
-
|
|
3558
|
-
|
|
4518
|
+
let adp = samplePos - audioDataOffset;
|
|
4519
|
+
if (adp >= 0 && adp < chDataLen) {
|
|
4520
|
+
chDat = audioData[ch][adp];
|
|
4521
|
+
//console.debug("Audio data: "+chDat);
|
|
4522
|
+
}
|
|
4523
|
+
else {
|
|
4524
|
+
//console.debug("Sample buf pos oob: adp: "+adp+", chDataLen: "+chDataLen+", samplePos: "+samplePos+", i: "+i);
|
|
3559
4525
|
}
|
|
3560
4526
|
// apply Window
|
|
3561
4527
|
b[i] = chDat * wf.getScale(i);
|
|
@@ -3565,63 +4531,78 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3565
4531
|
// Get maximum value of spectral energy
|
|
3566
4532
|
for (let s = 0; s < dftBands; s++) {
|
|
3567
4533
|
let psd = (2 * Math.pow(spectr[s], 2)) / dftBands;
|
|
3568
|
-
if (psd >
|
|
3569
|
-
|
|
4534
|
+
if (psd > calcMaxPsd) {
|
|
4535
|
+
calcMaxPsd = psd;
|
|
3570
4536
|
}
|
|
3571
4537
|
}
|
|
3572
4538
|
// Set render model data for this pixel
|
|
3573
4539
|
sona[ch][pii] = spectr;
|
|
3574
4540
|
}
|
|
3575
4541
|
}
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
scaledVal =
|
|
3596
|
-
|
|
3597
|
-
scaledVal
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
rgbVal =
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
4542
|
+
if (!msg.data.norender) {
|
|
4543
|
+
if (!maxPsd) {
|
|
4544
|
+
maxPsd = calcMaxPsd;
|
|
4545
|
+
}
|
|
4546
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4547
|
+
for (let pii = 0; pii < w; pii++) {
|
|
4548
|
+
let allBlack = true;
|
|
4549
|
+
for (let y = 0; y < chH; y++) {
|
|
4550
|
+
let freqIdx = Math.round(y * dftBands / chH);
|
|
4551
|
+
// calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
4552
|
+
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
4553
|
+
let val = sona[ch][pii][freqIdx];
|
|
4554
|
+
let psd = (2 * Math.pow(val, 2)) / dftBands;
|
|
4555
|
+
// Calculate logarithmic value
|
|
4556
|
+
//let psdLog = ips.dsp.DSPUtils.toLevelInDB(psd / maxPsd);
|
|
4557
|
+
let linearLevel = psd / maxPsd;
|
|
4558
|
+
let psdLog = 10 * Math.log(linearLevel) / Math.log(10);
|
|
4559
|
+
// Fixed dynamic Range value of 70dB for now
|
|
4560
|
+
let dynRangeInDb = 70;
|
|
4561
|
+
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
4562
|
+
// are the following checks necessary for clamped array ?
|
|
4563
|
+
if (scaledVal > 1.0)
|
|
4564
|
+
scaledVal = 1;
|
|
4565
|
+
if (scaledVal < 0.0) {
|
|
4566
|
+
scaledVal = 0;
|
|
4567
|
+
}
|
|
4568
|
+
let rgbVal = Math.round(255 * scaledVal);
|
|
4569
|
+
if (rgbVal < 0) {
|
|
4570
|
+
// System.out.println("Neg RGB val: "+rgbVal);
|
|
4571
|
+
rgbVal = 0;
|
|
4572
|
+
}
|
|
4573
|
+
if (rgbVal > 255) {
|
|
4574
|
+
rgbVal = 255;
|
|
4575
|
+
}
|
|
4576
|
+
rgbVal = 255 - rgbVal;
|
|
4577
|
+
if (rgbVal > 0) {
|
|
4578
|
+
allBlack = false;
|
|
4579
|
+
}
|
|
4580
|
+
let py = chH - y;
|
|
4581
|
+
let dataPos = ((((ch * chH) + py) * w) + pii) * 4;
|
|
4582
|
+
imgData[dataPos + 0] = rgbVal; //R
|
|
4583
|
+
imgData[dataPos + 1] = rgbVal; //G
|
|
4584
|
+
imgData[dataPos + 2] = rgbVal; //B
|
|
4585
|
+
imgData[dataPos + 3] = 255; //A (alpha: fully opaque)
|
|
4586
|
+
//console.debug("Rendered: py: "+py+", rgbval: "+rgbVal);
|
|
4587
|
+
// example 1x1, 2chs
|
|
4588
|
+
// ch0x0y0R,ch0x0y0G,ch0x0y0B,ch0x0y0A,
|
|
4589
|
+
// ch0x1y0R,ch0x1y0G,ch0x1y0B,ch0x1y0A,
|
|
4590
|
+
// ch0x0y0R,ch0x0y0G,ch0x0y0B,ch0x0y0A,
|
|
4591
|
+
// ch0x1y1R,ch0x1y1G,ch0x1y1B,ch0x1y1A,
|
|
4592
|
+
// ch1x0y0R,ch1x0y0G,ch1x0y0B,ch1x0y0A,
|
|
4593
|
+
// ch1x1y0R,ch1x1y0G,ch1x1y0B,ch1x1y0A,
|
|
4594
|
+
// ch1x0y0R,ch1x0y0G,ch1x0y0B,ch1x0y0A,
|
|
4595
|
+
// ch1x1y1R,ch1x1y1G,ch1x1y1B,ch1x1y1A
|
|
3610
4596
|
}
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
imgData[dataPos + 1] = rgbVal; //G
|
|
3615
|
-
imgData[dataPos + 2] = rgbVal; //B
|
|
3616
|
-
imgData[dataPos + 3] = 255; //A (alpha: fully opaque)
|
|
4597
|
+
// if (allBlack) {
|
|
4598
|
+
// console.log("Black: ", pii, " ", ch);
|
|
4599
|
+
// }
|
|
3617
4600
|
}
|
|
3618
|
-
// if (allBlack) {
|
|
3619
|
-
// console.log("Black: ", pii, " ", ch);
|
|
3620
|
-
// }
|
|
3621
4601
|
}
|
|
3622
4602
|
}
|
|
3623
4603
|
}
|
|
3624
|
-
|
|
4604
|
+
//console.debug("Render thread post message imgData: "+imgData.length)
|
|
4605
|
+
postMessage({ imgData: imgData, l: l, w: msg.data.w, h: msg.data.h, vw: vw, maxPsd: calcMaxPsd, terminate: msg.data.terminate }, [imgData.buffer]);
|
|
3625
4606
|
};
|
|
3626
4607
|
}
|
|
3627
4608
|
startDraw(clear = true) {
|
|
@@ -3651,42 +4632,190 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3651
4632
|
if (this.bounds) {
|
|
3652
4633
|
let w = Math.round(this.bounds.dimension.width);
|
|
3653
4634
|
let h = Math.round(this.bounds.dimension.height);
|
|
3654
|
-
if (this.
|
|
4635
|
+
if (this._audioDataHolder && w > 0 && h > 0) {
|
|
3655
4636
|
this.worker = new Worker(this.workerURL);
|
|
3656
4637
|
//this.wo = new Worker('./worker/sonagram.worker', { type: `module` });
|
|
3657
|
-
let chs = this.
|
|
3658
|
-
let
|
|
3659
|
-
let
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
let
|
|
4638
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
4639
|
+
let vw = Math.round(this.virtualDimension.width);
|
|
4640
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
4641
|
+
let framesPerPixel = Math.ceil(frameLength / vw);
|
|
4642
|
+
let leftPos = Math.round(this.bounds.position.left);
|
|
4643
|
+
let renderPos = leftPos;
|
|
4644
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
4645
|
+
//let arrayAudioBuffer=this._audioDataHolder.arrayBuffer;
|
|
4646
|
+
let arrAbBuf;
|
|
4647
|
+
let imgData;
|
|
4648
|
+
let maxPsd = -Infinity;
|
|
4649
|
+
let norender = true;
|
|
3665
4650
|
if (this.worker) {
|
|
3666
4651
|
this.worker.onmessage = (me) => {
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
|
|
4652
|
+
if (true === me.data.terminate) {
|
|
4653
|
+
let drawImgData;
|
|
4654
|
+
if (imgData) {
|
|
4655
|
+
drawImgData = imgData;
|
|
4656
|
+
}
|
|
4657
|
+
else {
|
|
4658
|
+
drawImgData = me.data.imgData;
|
|
4659
|
+
}
|
|
4660
|
+
this.drawRendered(w, h, drawImgData);
|
|
4661
|
+
if (this.worker) {
|
|
4662
|
+
this.worker.terminate();
|
|
4663
|
+
}
|
|
4664
|
+
this.worker = null;
|
|
4665
|
+
}
|
|
4666
|
+
else {
|
|
4667
|
+
// set rendered vertical values of one pixel of timescale
|
|
4668
|
+
//let dataPos = renderPos * h * 4;
|
|
4669
|
+
if (norender) {
|
|
4670
|
+
if (me.data.maxPsd > maxPsd) {
|
|
4671
|
+
maxPsd = me.data.maxPsd;
|
|
4672
|
+
//console.debug("new maxPsd: "+maxPsd);
|
|
4673
|
+
}
|
|
4674
|
+
}
|
|
4675
|
+
else {
|
|
4676
|
+
let chH = Math.round(h / chs);
|
|
4677
|
+
let idp = me.data.l - leftPos;
|
|
4678
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4679
|
+
for (let y = 0; y < chH; y++) {
|
|
4680
|
+
let py = chH - y;
|
|
4681
|
+
let dataPos = ((((ch * chH) + py) * w) + idp) * 4;
|
|
4682
|
+
let mePos = ((ch * chH) + py) * 4;
|
|
4683
|
+
//let lastPos = dataPos + me.data.imgData.length;
|
|
4684
|
+
//if (lastPos < imgData.length) {
|
|
4685
|
+
// set one pixel
|
|
4686
|
+
imgData[dataPos] = me.data.imgData[mePos];
|
|
4687
|
+
imgData[dataPos + 1] = me.data.imgData[mePos + 1];
|
|
4688
|
+
imgData[dataPos + 2] = me.data.imgData[mePos + 2];
|
|
4689
|
+
imgData[dataPos + 3] = me.data.imgData[mePos + 3];
|
|
4690
|
+
//} else {
|
|
4691
|
+
//console.error("Out of range: " + dataPos + "+" + me.data.imgData.length + ">=" + imgData.length);
|
|
4692
|
+
// }
|
|
4693
|
+
}
|
|
4694
|
+
}
|
|
4695
|
+
}
|
|
4696
|
+
if (this._audioDataHolder && arrAbBuf && this.worker) {
|
|
4697
|
+
// proceed with next pixel
|
|
4698
|
+
renderPos++;
|
|
4699
|
+
//console.debug("Render pos: "+renderPos);
|
|
4700
|
+
let terminate = false;
|
|
4701
|
+
let windowEnd = renderPos >= leftPos + w;
|
|
4702
|
+
if (windowEnd) {
|
|
4703
|
+
if (norender) {
|
|
4704
|
+
// phase two: rendering
|
|
4705
|
+
norender = false;
|
|
4706
|
+
// start from beginning
|
|
4707
|
+
renderPos = leftPos;
|
|
4708
|
+
//console.debug("now rendering: maxPsd: "+maxPsd);
|
|
4709
|
+
}
|
|
4710
|
+
else {
|
|
4711
|
+
// terminate render phase
|
|
4712
|
+
terminate = true;
|
|
4713
|
+
}
|
|
4714
|
+
}
|
|
4715
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw) - this.dftSize / 2;
|
|
4716
|
+
if (leftFramePos < 0) {
|
|
4717
|
+
leftFramePos = 0;
|
|
4718
|
+
}
|
|
4719
|
+
let ada = new Array(chs);
|
|
4720
|
+
//console.debug("Render pos: "+renderPos+" leftFramePos: "+leftFramePos);
|
|
4721
|
+
if (!terminate) {
|
|
4722
|
+
if (this._audioDataHolder) {
|
|
4723
|
+
let read = this._audioDataHolder.frames(leftFramePos, this.dftSize, arrAbBuf);
|
|
4724
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4725
|
+
// Need a copy here for the worker, otherwise this.audioData is not accessible after posting to the worker
|
|
4726
|
+
ada[ch] = arrAbBuf[ch].buffer.slice(0);
|
|
4727
|
+
}
|
|
4728
|
+
}
|
|
4729
|
+
}
|
|
4730
|
+
else {
|
|
4731
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4732
|
+
ada[ch] = new ArrayBuffer(0);
|
|
4733
|
+
}
|
|
4734
|
+
}
|
|
4735
|
+
this.worker.postMessage({
|
|
4736
|
+
audioData: ada,
|
|
4737
|
+
audioDataOffset: leftFramePos,
|
|
4738
|
+
l: renderPos,
|
|
4739
|
+
w: me.data.w,
|
|
4740
|
+
h: h,
|
|
4741
|
+
vw: vw,
|
|
4742
|
+
chs: chs,
|
|
4743
|
+
frameLength: frameLength,
|
|
4744
|
+
dftSize: this.dftSize,
|
|
4745
|
+
maxPsd: maxPsd,
|
|
4746
|
+
norender: norender,
|
|
4747
|
+
terminate: terminate
|
|
4748
|
+
}, ada);
|
|
4749
|
+
}
|
|
4750
|
+
}
|
|
4751
|
+
};
|
|
4752
|
+
}
|
|
4753
|
+
if (audioBuffer && audioBuffer.length * audioBuffer.numberOfChannels < AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD) {
|
|
4754
|
+
let ada = new Array(chs);
|
|
4755
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4756
|
+
// Need a copy here for the worker, otherwise this.audioData is not accessible after posting to the worker
|
|
4757
|
+
ada[ch] = audioBuffer.getChannelData(ch).buffer.slice(0);
|
|
4758
|
+
}
|
|
4759
|
+
let start = Date.now();
|
|
4760
|
+
if (this.markerCanvas) {
|
|
4761
|
+
let g = this.markerCanvas.getContext("2d");
|
|
4762
|
+
if (g) {
|
|
4763
|
+
g.fillText("Rendering...", 10, 20);
|
|
4764
|
+
}
|
|
4765
|
+
}
|
|
4766
|
+
this.worker.postMessage({
|
|
4767
|
+
audioData: ada,
|
|
4768
|
+
l: leftPos,
|
|
4769
|
+
w: w,
|
|
4770
|
+
h: h,
|
|
4771
|
+
vw: Math.round(this.virtualDimension.width),
|
|
4772
|
+
chs: chs,
|
|
4773
|
+
frameLength: frameLength,
|
|
4774
|
+
dftSize: this.dftSize,
|
|
4775
|
+
terminate: true
|
|
4776
|
+
}, ada);
|
|
4777
|
+
}
|
|
4778
|
+
else {
|
|
4779
|
+
if (w > 0) {
|
|
4780
|
+
if (framesPerPixel > 0) {
|
|
4781
|
+
let arrSize = w * h * 4;
|
|
4782
|
+
if (arrSize < 0) {
|
|
4783
|
+
arrSize = 0;
|
|
4784
|
+
}
|
|
4785
|
+
imgData = new Uint8ClampedArray(arrSize);
|
|
4786
|
+
let rw = 1;
|
|
4787
|
+
//ais = new ArrayAudioBufferInputStream(arrayAudioBuffer);
|
|
4788
|
+
arrAbBuf = new Array(chs);
|
|
4789
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4790
|
+
arrAbBuf[ch] = new Float32Array(this.dftSize);
|
|
4791
|
+
}
|
|
4792
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw) - this.dftSize / 2;
|
|
4793
|
+
let framesToRead = this.dftSize;
|
|
4794
|
+
if (leftFramePos < 0) {
|
|
4795
|
+
//framesToRead=this.dftSize+leftFramePos;
|
|
4796
|
+
leftFramePos = 0;
|
|
4797
|
+
}
|
|
4798
|
+
let read = this._audioDataHolder.frames(leftFramePos, framesToRead, arrAbBuf);
|
|
4799
|
+
let ad = new Float32Array(chs * framesToRead);
|
|
4800
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4801
|
+
ad.set(arrAbBuf[ch], ch * framesToRead);
|
|
4802
|
+
}
|
|
4803
|
+
this.worker.postMessage({
|
|
4804
|
+
l: renderPos,
|
|
4805
|
+
w: rw,
|
|
4806
|
+
h: h,
|
|
4807
|
+
vw: vw,
|
|
4808
|
+
chs: chs,
|
|
4809
|
+
frameLength: frameLength,
|
|
4810
|
+
audioData: ad,
|
|
4811
|
+
audioDataOffset: leftFramePos,
|
|
4812
|
+
dftSize: this.dftSize,
|
|
4813
|
+
norender: norender,
|
|
4814
|
+
terminate: false
|
|
4815
|
+
}, [ad.buffer]);
|
|
3670
4816
|
}
|
|
3671
|
-
this.worker = null;
|
|
3672
|
-
};
|
|
3673
|
-
}
|
|
3674
|
-
if (this.markerCanvas) {
|
|
3675
|
-
let g = this.markerCanvas.getContext("2d");
|
|
3676
|
-
if (g) {
|
|
3677
|
-
g.fillText("Rendering...", 10, 20);
|
|
3678
4817
|
}
|
|
3679
4818
|
}
|
|
3680
|
-
this.worker.postMessage({
|
|
3681
|
-
audioData: ada,
|
|
3682
|
-
l: Math.round(this.bounds.position.left),
|
|
3683
|
-
w: w,
|
|
3684
|
-
h: h,
|
|
3685
|
-
vw: Math.round(this.virtualDimension.width),
|
|
3686
|
-
chs: chs,
|
|
3687
|
-
frameLength: frameLength,
|
|
3688
|
-
dftSize: this.dftSize
|
|
3689
|
-
}, ada);
|
|
3690
4819
|
}
|
|
3691
4820
|
else {
|
|
3692
4821
|
let g = this.sonagramCanvas.getContext("2d");
|
|
@@ -3696,17 +4825,17 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3696
4825
|
}
|
|
3697
4826
|
}
|
|
3698
4827
|
}
|
|
3699
|
-
drawRendered(
|
|
4828
|
+
drawRendered(w, h, imgData) {
|
|
3700
4829
|
if (this.sonagramCanvas) {
|
|
3701
|
-
this.sonagramCanvas.width =
|
|
3702
|
-
this.sonagramCanvas.height =
|
|
4830
|
+
this.sonagramCanvas.width = w;
|
|
4831
|
+
this.sonagramCanvas.height = h;
|
|
3703
4832
|
let g = this.sonagramCanvas.getContext("2d");
|
|
3704
4833
|
if (g) {
|
|
3705
|
-
let imgDataArr =
|
|
3706
|
-
if (
|
|
3707
|
-
let
|
|
3708
|
-
|
|
3709
|
-
g.putImageData(
|
|
4834
|
+
let imgDataArr = imgData;
|
|
4835
|
+
if (w > 0 && h > 0) {
|
|
4836
|
+
let gImgData = g.createImageData(w, h);
|
|
4837
|
+
gImgData.data.set(imgDataArr);
|
|
4838
|
+
g.putImageData(gImgData, 0, 0);
|
|
3710
4839
|
}
|
|
3711
4840
|
}
|
|
3712
4841
|
}
|
|
@@ -3722,91 +4851,95 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3722
4851
|
g.clearRect(0, 0, w, h);
|
|
3723
4852
|
g.fillStyle = "white";
|
|
3724
4853
|
g.fillRect(0, 0, w, h);
|
|
3725
|
-
if (this.
|
|
4854
|
+
if (this._audioDataHolder) {
|
|
3726
4855
|
let spectSize = Math.floor(this.dftSize / 2);
|
|
3727
|
-
let chs = this.
|
|
4856
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
3728
4857
|
let chH = h / chs;
|
|
3729
|
-
let frameLength = this.
|
|
4858
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
3730
4859
|
let framesPerPixel = frameLength / w;
|
|
3731
4860
|
let y = 0;
|
|
3732
|
-
|
|
3733
|
-
let
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
let
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
framePos =
|
|
3745
|
-
|
|
3746
|
-
|
|
3747
|
-
|
|
3748
|
-
|
|
3749
|
-
|
|
3750
|
-
|
|
3751
|
-
sona[ch][pii] = spectr;
|
|
3752
|
-
// @ts-ignore
|
|
3753
|
-
let pMax = Math.max.apply(null, spectr);
|
|
3754
|
-
if (pMax > max) {
|
|
3755
|
-
max = pMax;
|
|
3756
|
-
}
|
|
3757
|
-
for (let s = 0; s < spectSize; s++) {
|
|
3758
|
-
let psd = (2 * Math.pow(spectr[s], 2)) / spectSize;
|
|
3759
|
-
if (psd > maxPsd) {
|
|
3760
|
-
maxPsd = psd;
|
|
4861
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
4862
|
+
let arrayAudioBuffer = this._audioDataHolder.arrayBuffer;
|
|
4863
|
+
if (audioBuffer) {
|
|
4864
|
+
let b = new Float32Array(this.dftSize);
|
|
4865
|
+
let sona = new Array(chs);
|
|
4866
|
+
let max = 0;
|
|
4867
|
+
let maxPsd = -Infinity;
|
|
4868
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4869
|
+
let x = 0;
|
|
4870
|
+
sona[ch] = new Array(w);
|
|
4871
|
+
let chData = audioBuffer.getChannelData(ch);
|
|
4872
|
+
// TODO center buffer
|
|
4873
|
+
let framePos = 0;
|
|
4874
|
+
for (let pii = 0; pii < w; pii++) {
|
|
4875
|
+
framePos = Math.round(pii * framesPerPixel);
|
|
4876
|
+
// calculate DFT at pixel position
|
|
4877
|
+
for (let i = 0; i < this.dftSize; i++) {
|
|
4878
|
+
let chDat = chData[framePos + i];
|
|
4879
|
+
b[i] = chDat;
|
|
3761
4880
|
}
|
|
3762
|
-
|
|
3763
|
-
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
3768
|
-
let framePos = 0;
|
|
3769
|
-
for (let pii = 0; pii < w; pii++) {
|
|
3770
|
-
framePos = pii * framesPerPixel;
|
|
3771
|
-
for (let y = 0; y < h; y++) {
|
|
3772
|
-
let freqIdx = Math.round(y * spectSize / h);
|
|
3773
|
-
// calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
3774
|
-
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
3775
|
-
let val = sona[ch][pii][freqIdx];
|
|
3776
|
-
let psd = (2 * Math.pow(val, 2)) / spectSize;
|
|
3777
|
-
// Calculate logarithmic
|
|
3778
|
-
let psdLog = DSPUtils.toLevelInDB(psd / maxPsd);
|
|
3779
|
-
let dynRangeInDb = 70;
|
|
3780
|
-
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
3781
|
-
if (scaledVal > 1)
|
|
3782
|
-
scaledVal = 1;
|
|
3783
|
-
if (scaledVal < 0) {
|
|
3784
|
-
scaledVal = 0;
|
|
4881
|
+
let spectr = this.dft.processRealMagnitude(b);
|
|
4882
|
+
sona[ch][pii] = spectr;
|
|
4883
|
+
// @ts-ignore
|
|
4884
|
+
let pMax = Math.max.apply(null, spectr);
|
|
4885
|
+
if (pMax > max) {
|
|
4886
|
+
max = pMax;
|
|
3785
4887
|
}
|
|
3786
|
-
let
|
|
3787
|
-
|
|
3788
|
-
|
|
3789
|
-
|
|
4888
|
+
for (let s = 0; s < spectSize; s++) {
|
|
4889
|
+
let psd = (2 * Math.pow(spectr[s], 2)) / spectSize;
|
|
4890
|
+
if (psd > maxPsd) {
|
|
4891
|
+
maxPsd = psd;
|
|
4892
|
+
}
|
|
3790
4893
|
}
|
|
3791
|
-
|
|
3792
|
-
|
|
4894
|
+
}
|
|
4895
|
+
}
|
|
4896
|
+
//console.log("max: ", max);
|
|
4897
|
+
maxPsd = (2 * Math.pow(max, 2)) / spectSize;
|
|
4898
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4899
|
+
let framePos = 0;
|
|
4900
|
+
for (let pii = 0; pii < w; pii++) {
|
|
4901
|
+
framePos = pii * framesPerPixel;
|
|
4902
|
+
for (let y = 0; y < h; y++) {
|
|
4903
|
+
let freqIdx = Math.round(y * spectSize / h);
|
|
4904
|
+
// calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
4905
|
+
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
4906
|
+
let val = sona[ch][pii][freqIdx];
|
|
4907
|
+
let psd = (2 * Math.pow(val, 2)) / spectSize;
|
|
4908
|
+
// Calculate logarithmic
|
|
4909
|
+
let psdLog = DSPUtils.toLevelInDB(psd / maxPsd);
|
|
4910
|
+
let dynRangeInDb = 70;
|
|
4911
|
+
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
4912
|
+
if (scaledVal > 1)
|
|
4913
|
+
scaledVal = 1;
|
|
4914
|
+
if (scaledVal < 0) {
|
|
4915
|
+
scaledVal = 0;
|
|
4916
|
+
}
|
|
4917
|
+
let rgbVal = (255 * scaledVal);
|
|
4918
|
+
if (rgbVal < 0) {
|
|
4919
|
+
// System.out.println("Neg RGB val: "+rgbVal);
|
|
4920
|
+
rgbVal = 0;
|
|
4921
|
+
}
|
|
4922
|
+
if (rgbVal > 255) {
|
|
4923
|
+
rgbVal = 255;
|
|
4924
|
+
}
|
|
4925
|
+
rgbVal = 255 - rgbVal;
|
|
4926
|
+
let colorStr = CSSUtils.toColorString(rgbVal, rgbVal, rgbVal);
|
|
4927
|
+
g.fillStyle = colorStr;
|
|
4928
|
+
g.fillRect(pii, chH - y, 1, 1);
|
|
3793
4929
|
}
|
|
3794
|
-
rgbVal = 255 - rgbVal;
|
|
3795
|
-
let colorStr = CSSUtils.toColorString(rgbVal, rgbVal, rgbVal);
|
|
3796
|
-
g.fillStyle = colorStr;
|
|
3797
|
-
g.fillRect(pii, chH - y, 1, 1);
|
|
3798
4930
|
}
|
|
3799
4931
|
}
|
|
4932
|
+
this.drawPlayPosition();
|
|
4933
|
+
}
|
|
4934
|
+
else if (arrayAudioBuffer) {
|
|
4935
|
+
throw Error("Redraw with array audio buffer not supported.");
|
|
3800
4936
|
}
|
|
3801
|
-
this.drawPlayPosition();
|
|
3802
4937
|
}
|
|
3803
4938
|
}
|
|
3804
4939
|
}
|
|
3805
4940
|
setData(audioData) {
|
|
3806
|
-
this.
|
|
4941
|
+
this._audioDataHolder = audioData;
|
|
3807
4942
|
this.playFramePosition = 0;
|
|
3808
|
-
//this.redraw();
|
|
3809
|
-
//this.startRender();
|
|
3810
4943
|
}
|
|
3811
4944
|
}
|
|
3812
4945
|
Sonagram.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: Sonagram, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4031,13 +5164,13 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4031
5164
|
}
|
|
4032
5165
|
currentXZoom() {
|
|
4033
5166
|
let xz = this._xZoom;
|
|
4034
|
-
if (xz == null && this.
|
|
5167
|
+
if (xz == null && this._audioDataHolder) {
|
|
4035
5168
|
let ow = this.ce.offsetWidth;
|
|
4036
5169
|
if (ow < 1) {
|
|
4037
5170
|
// at least one pixel width to avoid x-zoom zero values
|
|
4038
5171
|
ow = 1;
|
|
4039
5172
|
}
|
|
4040
|
-
xz = ow / this.
|
|
5173
|
+
xz = ow / this._audioDataHolder.duration;
|
|
4041
5174
|
}
|
|
4042
5175
|
return xz;
|
|
4043
5176
|
}
|
|
@@ -4116,9 +5249,10 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4116
5249
|
this._layout(false, false);
|
|
4117
5250
|
}
|
|
4118
5251
|
layout(clear = true) {
|
|
5252
|
+
var _a;
|
|
4119
5253
|
if (this.ce && this.dc) {
|
|
4120
5254
|
const clientW = this.ce.clientWidth;
|
|
4121
|
-
if (this.
|
|
5255
|
+
if (this._audioDataHolder) {
|
|
4122
5256
|
if (this._fixFitToPanel) {
|
|
4123
5257
|
// Set the virtual canvas width to the visible width
|
|
4124
5258
|
if (this.ce.style.width != '100%') {
|
|
@@ -4129,7 +5263,7 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4129
5263
|
else {
|
|
4130
5264
|
if (this._xZoom) {
|
|
4131
5265
|
// Set the virtual canvas width according to the value of the user selected xZoom value
|
|
4132
|
-
const newClW = Math.round(this._xZoom * this.
|
|
5266
|
+
const newClW = Math.round(this._xZoom * ((_a = this._audioDataHolder) === null || _a === void 0 ? void 0 : _a.duration));
|
|
4133
5267
|
this.ce.style.width = newClW + 'px';
|
|
4134
5268
|
}
|
|
4135
5269
|
else {
|
|
@@ -4141,22 +5275,22 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4141
5275
|
this._layout(clear, true);
|
|
4142
5276
|
}
|
|
4143
5277
|
}
|
|
4144
|
-
set audioData(
|
|
5278
|
+
set audioData(audioDataHolder) {
|
|
4145
5279
|
this._audioClip = null;
|
|
4146
|
-
this.
|
|
4147
|
-
this.as.setData(
|
|
4148
|
-
this.so.setData(
|
|
5280
|
+
this._audioDataHolder = audioDataHolder;
|
|
5281
|
+
this.as.setData(audioDataHolder);
|
|
5282
|
+
this.so.setData(audioDataHolder);
|
|
4149
5283
|
this.layout();
|
|
4150
5284
|
}
|
|
4151
5285
|
get audioData() {
|
|
4152
|
-
return this.
|
|
5286
|
+
return this._audioDataHolder;
|
|
4153
5287
|
}
|
|
4154
5288
|
set audioClip(audioClip) {
|
|
4155
5289
|
this._audioClip = audioClip;
|
|
4156
5290
|
let audioData = null;
|
|
4157
5291
|
let sel = null;
|
|
4158
5292
|
if (audioClip) {
|
|
4159
|
-
audioData = audioClip.
|
|
5293
|
+
audioData = audioClip.audioDataHolder;
|
|
4160
5294
|
if (this._audioClip) {
|
|
4161
5295
|
this._audioClip.addSelectionObserver((clip) => {
|
|
4162
5296
|
this.selection = clip.selection;
|
|
@@ -4164,9 +5298,9 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4164
5298
|
}
|
|
4165
5299
|
sel = audioClip.selection;
|
|
4166
5300
|
}
|
|
4167
|
-
this.
|
|
4168
|
-
this.as.setData(this.
|
|
4169
|
-
this.so.setData(this.
|
|
5301
|
+
this._audioDataHolder = audioData;
|
|
5302
|
+
this.as.setData(this._audioDataHolder);
|
|
5303
|
+
this.so.setData(this._audioDataHolder);
|
|
4170
5304
|
this.selecting = null;
|
|
4171
5305
|
this.selection = sel;
|
|
4172
5306
|
this.layout();
|
|
@@ -4358,7 +5492,7 @@ class AudioDisplayScrollPane {
|
|
|
4358
5492
|
let audioData = null;
|
|
4359
5493
|
let sel = null;
|
|
4360
5494
|
if (audioClip) {
|
|
4361
|
-
audioData = audioClip.
|
|
5495
|
+
audioData = audioClip.audioDataHolder;
|
|
4362
5496
|
sel = audioClip.selection;
|
|
4363
5497
|
audioClip.addSelectionObserver((clip) => {
|
|
4364
5498
|
this.zoomSelectedAction.disabled = (clip.selection == null);
|
|
@@ -4629,17 +5763,17 @@ class AudioDisplay {
|
|
|
4629
5763
|
console.log("Play started");
|
|
4630
5764
|
this.status = 'Playing...';
|
|
4631
5765
|
}
|
|
4632
|
-
set audioData(
|
|
4633
|
-
this.audioDisplayScrollPane.audioData =
|
|
5766
|
+
set audioData(audioData) {
|
|
5767
|
+
this.audioDisplayScrollPane.audioData = audioData;
|
|
4634
5768
|
if (this.playStartAction) {
|
|
4635
|
-
this.playStartAction.disabled = (
|
|
5769
|
+
this.playStartAction.disabled = (audioData == null);
|
|
4636
5770
|
}
|
|
4637
5771
|
}
|
|
4638
5772
|
set audioClip(audioClip) {
|
|
4639
5773
|
let audioData = null;
|
|
4640
5774
|
let sel = null;
|
|
4641
5775
|
if (audioClip) {
|
|
4642
|
-
audioData = audioClip.buffer;
|
|
5776
|
+
audioData = audioClip.audioDataHolder.buffer;
|
|
4643
5777
|
sel = audioClip.selection;
|
|
4644
5778
|
}
|
|
4645
5779
|
this._audioClip = audioClip;
|
|
@@ -4752,7 +5886,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
4752
5886
|
|
|
4753
5887
|
class Progress {
|
|
4754
5888
|
constructor() {
|
|
4755
|
-
this.items =
|
|
5889
|
+
this.items = undefined;
|
|
4756
5890
|
this.selectedItemIdx = 0;
|
|
4757
5891
|
this.enableDownload = false;
|
|
4758
5892
|
this.onRowSelect = new EventEmitter();
|
|
@@ -5492,7 +6626,7 @@ class Prompting {
|
|
|
5492
6626
|
constructor() {
|
|
5493
6627
|
this.promptItem = null;
|
|
5494
6628
|
this.showPrompt = false;
|
|
5495
|
-
this.items =
|
|
6629
|
+
this.items = undefined;
|
|
5496
6630
|
this.enableDownload = false;
|
|
5497
6631
|
this.audioSignalCollapsed = true;
|
|
5498
6632
|
this.displayAudioClip = null;
|
|
@@ -5807,6 +6941,7 @@ class LevelBar {
|
|
|
5807
6941
|
this._streamingMode = false;
|
|
5808
6942
|
this._staticLevelInfos = null;
|
|
5809
6943
|
this._playFramePosition = null;
|
|
6944
|
+
this._stateLoading = false;
|
|
5810
6945
|
this.warnDBLevel = DEFAULT_WARN_DB_LEVEL$1;
|
|
5811
6946
|
this.dbValues = new Array();
|
|
5812
6947
|
}
|
|
@@ -5852,6 +6987,10 @@ class LevelBar {
|
|
|
5852
6987
|
}
|
|
5853
6988
|
this.layoutStatic();
|
|
5854
6989
|
}
|
|
6990
|
+
set stateLoading(loading) {
|
|
6991
|
+
this._stateLoading = loading;
|
|
6992
|
+
this.layoutStatic();
|
|
6993
|
+
}
|
|
5855
6994
|
set channelCount(channelCount) {
|
|
5856
6995
|
this.reset();
|
|
5857
6996
|
}
|
|
@@ -6032,6 +7171,12 @@ class LevelBar {
|
|
|
6032
7171
|
}
|
|
6033
7172
|
}
|
|
6034
7173
|
}
|
|
7174
|
+
else if (this._stateLoading) {
|
|
7175
|
+
g.strokeStyle = 'white';
|
|
7176
|
+
g.fillStyle = 'white';
|
|
7177
|
+
g.font = '20px sans-serif';
|
|
7178
|
+
g.fillText("Loading...", 10, 25);
|
|
7179
|
+
}
|
|
6035
7180
|
}
|
|
6036
7181
|
}
|
|
6037
7182
|
}
|
|
@@ -6074,7 +7219,7 @@ class LevelBar {
|
|
|
6074
7219
|
}
|
|
6075
7220
|
}
|
|
6076
7221
|
LevelBar.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: LevelBar, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
6077
|
-
LevelBar.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: LevelBar, selector: "audio-levelbar", inputs: { streamingMode: "streamingMode", displayLevelInfos: "displayLevelInfos" }, host: { listeners: { "scroll": "onScroll($event)", "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "virtualCanvasRef", first: true, predicate: ["virtualCanvas"], descendants: true, static: true }, { propertyName: "liveLevelCanvasRef", first: true, predicate: ["levelbar"], descendants: true, static: true }, { propertyName: "markerCanvasRef", first: true, predicate: ["markerCanvas"], descendants: true, static: true }], ngImport: i0, template: `
|
|
7222
|
+
LevelBar.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: LevelBar, selector: "audio-levelbar", inputs: { streamingMode: "streamingMode", displayLevelInfos: "displayLevelInfos", stateLoading: "stateLoading" }, host: { listeners: { "scroll": "onScroll($event)", "window:resize": "onResize($event)" } }, viewQueries: [{ propertyName: "virtualCanvasRef", first: true, predicate: ["virtualCanvas"], descendants: true, static: true }, { propertyName: "liveLevelCanvasRef", first: true, predicate: ["levelbar"], descendants: true, static: true }, { propertyName: "markerCanvasRef", first: true, predicate: ["markerCanvas"], descendants: true, static: true }], ngImport: i0, template: `
|
|
6078
7223
|
<div #virtualCanvas>
|
|
6079
7224
|
<canvas #levelbar></canvas>
|
|
6080
7225
|
<canvas #markerCanvas></canvas>
|
|
@@ -6131,6 +7276,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
6131
7276
|
type: Input
|
|
6132
7277
|
}], displayLevelInfos: [{
|
|
6133
7278
|
type: Input
|
|
7279
|
+
}], stateLoading: [{
|
|
7280
|
+
type: Input
|
|
6134
7281
|
}], onResize: [{
|
|
6135
7282
|
type: HostListener,
|
|
6136
7283
|
args: ['window:resize', ['$event']]
|
|
@@ -6721,47 +7868,68 @@ class PeakLevelInterceptor {
|
|
|
6721
7868
|
}
|
|
6722
7869
|
}
|
|
6723
7870
|
class LevelMeasure {
|
|
7871
|
+
//private bufferLevelInfos=new Array<LevelInfo>();
|
|
7872
|
+
//private peakLevelInfo!:LevelInfo;
|
|
6724
7873
|
constructor() {
|
|
6725
7874
|
this.worker = null;
|
|
6726
7875
|
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
6727
7876
|
}
|
|
6728
|
-
calcBufferLevelInfos(
|
|
7877
|
+
calcBufferLevelInfos(audioDataHolder, bufferTimeLength) {
|
|
6729
7878
|
return new Promise((resolve) => {
|
|
6730
|
-
|
|
6731
|
-
let
|
|
6732
|
-
let
|
|
7879
|
+
var _a;
|
|
7880
|
+
let chs = audioDataHolder.numberOfChannels;
|
|
7881
|
+
let bufferFrameLength = Math.round(audioDataHolder.sampleRate * bufferTimeLength);
|
|
7882
|
+
let ais = audioDataHolder.audioInputStream();
|
|
7883
|
+
let audioBuffers = new Array(chs);
|
|
7884
|
+
let trBuffers = new Array(chs);
|
|
6733
7885
|
for (let ch = 0; ch < chs; ch++) {
|
|
6734
|
-
|
|
6735
|
-
let adChCopy = new Float32Array(adCh.length);
|
|
6736
|
-
adChCopy.set(adCh);
|
|
6737
|
-
buffers[ch] = adChCopy.buffer;
|
|
7886
|
+
audioBuffers[ch] = new Float32Array(bufferFrameLength);
|
|
6738
7887
|
}
|
|
7888
|
+
let bufferLevelInfos = new Array();
|
|
7889
|
+
let peakLevelInfo = new LevelInfo(chs);
|
|
6739
7890
|
this.worker = new Worker(this.workerURL);
|
|
6740
7891
|
this.worker.onmessage = (me) => {
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
linLevelArrs
|
|
6744
|
-
|
|
6745
|
-
|
|
6746
|
-
|
|
6747
|
-
|
|
6748
|
-
|
|
6749
|
-
|
|
6750
|
-
|
|
6751
|
-
|
|
7892
|
+
var _a;
|
|
7893
|
+
if (me.data.linLevelBuffers) {
|
|
7894
|
+
let linLevelArrs = new Array(chs);
|
|
7895
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7896
|
+
linLevelArrs[ch] = new Float32Array(me.data.linLevelBuffers[ch]);
|
|
7897
|
+
}
|
|
7898
|
+
let bufferCount = Math.ceil(me.data.frameLength / me.data.bufferFrameLength);
|
|
7899
|
+
let framePos = 0;
|
|
7900
|
+
for (let bi = 0; bi < bufferCount; bi++) {
|
|
7901
|
+
let minLevels = new Array(chs);
|
|
7902
|
+
let maxLevels = new Array(chs);
|
|
7903
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7904
|
+
let linLvlArrPos = bi * 2;
|
|
7905
|
+
minLevels[ch] = linLevelArrs[ch][linLvlArrPos];
|
|
7906
|
+
maxLevels[ch] = linLevelArrs[ch][linLvlArrPos + 1];
|
|
7907
|
+
}
|
|
7908
|
+
let bli = new LevelInfo(chs, framePos, me.data.bufferFrameLength, minLevels, maxLevels);
|
|
7909
|
+
bufferLevelInfos.push(bli);
|
|
7910
|
+
peakLevelInfo.merge(bli);
|
|
7911
|
+
}
|
|
7912
|
+
}
|
|
7913
|
+
if (me.data.eod === true) {
|
|
7914
|
+
// end of data, terminate worker and return result
|
|
7915
|
+
this.terminateWorker();
|
|
7916
|
+
resolve(new LevelInfos(bufferLevelInfos, peakLevelInfo));
|
|
7917
|
+
}
|
|
7918
|
+
else {
|
|
7919
|
+
let read = ais.read(audioBuffers);
|
|
6752
7920
|
for (let ch = 0; ch < chs; ch++) {
|
|
6753
|
-
let
|
|
6754
|
-
|
|
6755
|
-
maxLevels[ch] = linLevelArrs[ch][linLvlArrPos + 1];
|
|
7921
|
+
let copy = new Float32Array(audioBuffers[ch]);
|
|
7922
|
+
trBuffers[ch] = copy.buffer;
|
|
6756
7923
|
}
|
|
6757
|
-
|
|
6758
|
-
bufferLevelInfos.push(bli);
|
|
6759
|
-
peakLevelInfo.merge(bli);
|
|
7924
|
+
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.postMessage({ bufferFrameLength: bufferFrameLength, audioData: trBuffers, chs: chs, len: read }, trBuffers);
|
|
6760
7925
|
}
|
|
6761
|
-
this.terminateWorker();
|
|
6762
|
-
resolve(new LevelInfos(bufferLevelInfos, peakLevelInfo));
|
|
6763
7926
|
};
|
|
6764
|
-
|
|
7927
|
+
let read = ais.read(audioBuffers);
|
|
7928
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7929
|
+
let copy = new Float32Array(audioBuffers[ch]);
|
|
7930
|
+
trBuffers[ch] = copy.buffer;
|
|
7931
|
+
}
|
|
7932
|
+
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.postMessage({ bufferFrameLength: bufferFrameLength, audioData: trBuffers, chs: chs, len: read }, trBuffers);
|
|
6765
7933
|
});
|
|
6766
7934
|
}
|
|
6767
7935
|
terminateWorker() {
|
|
@@ -6773,40 +7941,63 @@ class LevelMeasure {
|
|
|
6773
7941
|
*/
|
|
6774
7942
|
workerFunction() {
|
|
6775
7943
|
self.onmessage = function (msg) {
|
|
6776
|
-
let
|
|
7944
|
+
let len = msg.data.len;
|
|
6777
7945
|
let bufferFrameLength = msg.data.bufferFrameLength;
|
|
6778
|
-
|
|
6779
|
-
|
|
6780
|
-
|
|
6781
|
-
|
|
7946
|
+
if (len == -1) {
|
|
7947
|
+
// start
|
|
7948
|
+
postMessage({
|
|
7949
|
+
eod: false,
|
|
7950
|
+
bufferFrameLength: bufferFrameLength,
|
|
7951
|
+
frameLength: len
|
|
7952
|
+
});
|
|
6782
7953
|
}
|
|
6783
|
-
|
|
6784
|
-
|
|
6785
|
-
|
|
6786
|
-
|
|
7954
|
+
if (len == 0) {
|
|
7955
|
+
postMessage({
|
|
7956
|
+
eod: true,
|
|
7957
|
+
bufferFrameLength: bufferFrameLength,
|
|
7958
|
+
frameLength: len
|
|
7959
|
+
});
|
|
6787
7960
|
}
|
|
6788
|
-
|
|
7961
|
+
else {
|
|
7962
|
+
let chs = msg.data.chs;
|
|
7963
|
+
let audioData = new Array(chs);
|
|
7964
|
+
let linLevels = new Array(chs);
|
|
6789
7965
|
for (let ch = 0; ch < chs; ch++) {
|
|
6790
|
-
|
|
6791
|
-
for (let s = 0; s < frameLength; s++) {
|
|
6792
|
-
let bi = Math.floor(s / bufferFrameLength);
|
|
6793
|
-
let lvlArrPos = bi * 2;
|
|
6794
|
-
//let bs = s % bufferFrameLength;
|
|
6795
|
-
let chSample = chData[s];
|
|
6796
|
-
if (chSample < linLevels[ch][lvlArrPos]) {
|
|
6797
|
-
linLevels[ch][lvlArrPos] = chSample;
|
|
6798
|
-
}
|
|
6799
|
-
lvlArrPos++;
|
|
6800
|
-
if (chSample > linLevels[ch][lvlArrPos]) {
|
|
6801
|
-
linLevels[ch][lvlArrPos] = chSample;
|
|
6802
|
-
}
|
|
6803
|
-
}
|
|
7966
|
+
audioData[ch] = new Float32Array(msg.data.audioData[ch]);
|
|
6804
7967
|
}
|
|
6805
|
-
|
|
7968
|
+
//let frameLength = audioData[0].length;
|
|
7969
|
+
let bufferCount = Math.ceil(len / bufferFrameLength);
|
|
6806
7970
|
for (let ch = 0; ch < chs; ch++) {
|
|
6807
|
-
|
|
7971
|
+
linLevels[ch] = new Float32Array(bufferCount * 2);
|
|
7972
|
+
}
|
|
7973
|
+
if (audioData && chs > 0) {
|
|
7974
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7975
|
+
let chData = audioData[ch];
|
|
7976
|
+
for (let s = 0; s < len; s++) {
|
|
7977
|
+
let bi = Math.floor(s / bufferFrameLength);
|
|
7978
|
+
let lvlArrPos = bi * 2;
|
|
7979
|
+
//let bs = s % bufferFrameLength;
|
|
7980
|
+
let chSample = chData[s];
|
|
7981
|
+
if (chSample < linLevels[ch][lvlArrPos]) {
|
|
7982
|
+
linLevels[ch][lvlArrPos] = chSample;
|
|
7983
|
+
}
|
|
7984
|
+
lvlArrPos++;
|
|
7985
|
+
if (chSample > linLevels[ch][lvlArrPos]) {
|
|
7986
|
+
linLevels[ch][lvlArrPos] = chSample;
|
|
7987
|
+
}
|
|
7988
|
+
}
|
|
7989
|
+
}
|
|
7990
|
+
const linLevelBufs = new Array(chs);
|
|
7991
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7992
|
+
linLevelBufs[ch] = linLevels[ch].buffer;
|
|
7993
|
+
}
|
|
7994
|
+
postMessage({
|
|
7995
|
+
eod: false,
|
|
7996
|
+
bufferFrameLength: bufferFrameLength,
|
|
7997
|
+
frameLength: len,
|
|
7998
|
+
linLevelBuffers: linLevelBufs
|
|
7999
|
+
}, linLevelBufs);
|
|
6808
8000
|
}
|
|
6809
|
-
postMessage({ bufferFrameLength: bufferFrameLength, frameLength: frameLength, linLevelBuffers: linLevelBufs }, linLevelBufs);
|
|
6810
8001
|
}
|
|
6811
8002
|
};
|
|
6812
8003
|
}
|
|
@@ -7182,7 +8373,7 @@ RecordingItemDisplay.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
|
|
|
7182
8373
|
<audio-levelbar fxFlex="1 0 1" [streamingMode]="streamingMode" [displayLevelInfos]="_displayLevelInfos"></audio-levelbar>
|
|
7183
8374
|
<spr-recordingitemcontrols fxFlex="0 0 0" [audioLoaded]="displayAudioBuffer!==null" [playStartAction]="playStartAction" [playStopAction]="playStopAction" [peakDbLvl]="peakDbLvl" [agc]="_agc" (onShowRecordingDetails)="onShowRecordingDetails.emit()"></spr-recordingitemcontrols>
|
|
7184
8375
|
</div>
|
|
7185
|
-
`, isInline: true, styles: ["div{width:100%;background:darkgray;padding:4px;box-sizing:border-box;flex-wrap:nowrap}\n", "audio-levelbar{box-sizing:border-box}\n"], components: [{ type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos"] }, { type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i3$1.DefaultStyleDirective, selector: " [ngStyle], [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl], [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl], [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i8.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }] });
|
|
8376
|
+
`, isInline: true, styles: ["div{width:100%;background:darkgray;padding:4px;box-sizing:border-box;flex-wrap:nowrap}\n", "audio-levelbar{box-sizing:border-box}\n"], components: [{ type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos", "stateLoading"] }, { type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i3$1.DefaultStyleDirective, selector: " [ngStyle], [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl], [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl], [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i8.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }] });
|
|
7186
8377
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingItemDisplay, decorators: [{
|
|
7187
8378
|
type: Component,
|
|
7188
8379
|
args: [{
|
|
@@ -7228,89 +8419,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
7228
8419
|
type: Input
|
|
7229
8420
|
}] } });
|
|
7230
8421
|
|
|
7231
|
-
class Float32ArrayChunkerOutStream {
|
|
7232
|
-
constructor(outStream) {
|
|
7233
|
-
this.outStream = outStream;
|
|
7234
|
-
this.bufs = new Array();
|
|
7235
|
-
this._channels = 0;
|
|
7236
|
-
this._chunkSize = 0;
|
|
7237
|
-
this.filled = 0;
|
|
7238
|
-
this.receivedFrames = 0;
|
|
7239
|
-
this.sentFrames = 0;
|
|
7240
|
-
}
|
|
7241
|
-
createBuffers() {
|
|
7242
|
-
this.bufs = new Array(this._channels);
|
|
7243
|
-
for (let ch = 0; ch < this._channels; ch++) {
|
|
7244
|
-
this.bufs[ch] = new Float32Array(this._chunkSize);
|
|
7245
|
-
}
|
|
7246
|
-
}
|
|
7247
|
-
set chunkSize(chunkSize) {
|
|
7248
|
-
this._chunkSize = chunkSize;
|
|
7249
|
-
this.createBuffers();
|
|
7250
|
-
}
|
|
7251
|
-
get chunkSize() {
|
|
7252
|
-
return this._chunkSize;
|
|
7253
|
-
}
|
|
7254
|
-
set channels(channels) {
|
|
7255
|
-
this._channels = channels;
|
|
7256
|
-
this.createBuffers();
|
|
7257
|
-
}
|
|
7258
|
-
get channels() {
|
|
7259
|
-
return this._channels;
|
|
7260
|
-
}
|
|
7261
|
-
available() {
|
|
7262
|
-
return this._chunkSize - this.filled;
|
|
7263
|
-
}
|
|
7264
|
-
write(buffers) {
|
|
7265
|
-
let copied = 0;
|
|
7266
|
-
if (buffers.length > 0) {
|
|
7267
|
-
let buffersLen = buffers[0].length;
|
|
7268
|
-
this.receivedFrames += buffersLen;
|
|
7269
|
-
let avail = buffersLen;
|
|
7270
|
-
// Fill out buffers until all values copied
|
|
7271
|
-
while (avail > 0) {
|
|
7272
|
-
let toFill = this._chunkSize - this.filled;
|
|
7273
|
-
if (toFill > avail) {
|
|
7274
|
-
toFill = avail;
|
|
7275
|
-
}
|
|
7276
|
-
let sliceEnd = copied + toFill;
|
|
7277
|
-
// Firefox on Android sends only the first channel
|
|
7278
|
-
for (let ch = 0; ch < buffersLen; ch++) {
|
|
7279
|
-
if (buffers[ch]) {
|
|
7280
|
-
let cpPrt = buffers[ch].slice(copied, sliceEnd);
|
|
7281
|
-
let buf = this.bufs[ch];
|
|
7282
|
-
buf.set(cpPrt, this.filled);
|
|
7283
|
-
}
|
|
7284
|
-
}
|
|
7285
|
-
copied += toFill;
|
|
7286
|
-
avail -= toFill;
|
|
7287
|
-
this.filled += toFill;
|
|
7288
|
-
if (this.filled == this._chunkSize) {
|
|
7289
|
-
this.outStream.write(this.bufs);
|
|
7290
|
-
this.sentFrames += this.filled;
|
|
7291
|
-
this.filled = 0;
|
|
7292
|
-
}
|
|
7293
|
-
}
|
|
7294
|
-
}
|
|
7295
|
-
return copied;
|
|
7296
|
-
}
|
|
7297
|
-
flush() {
|
|
7298
|
-
if (this.filled > 0) {
|
|
7299
|
-
let restBufs = new Array(this._channels);
|
|
7300
|
-
for (let ch = 0; ch < this._channels; ch++) {
|
|
7301
|
-
restBufs[ch] = this.bufs[ch].slice(0, this.filled);
|
|
7302
|
-
}
|
|
7303
|
-
this.outStream.write(restBufs);
|
|
7304
|
-
this.outStream.flush();
|
|
7305
|
-
this.sentFrames += this.filled;
|
|
7306
|
-
this.filled = 0;
|
|
7307
|
-
}
|
|
7308
|
-
}
|
|
7309
|
-
close() {
|
|
7310
|
-
this.outStream.close();
|
|
7311
|
-
}
|
|
7312
|
-
}
|
|
7313
|
-
|
|
7314
8422
|
class SequenceAudioFloat32ChunkerOutStream extends Float32ArrayChunkerOutStream {
|
|
7315
8423
|
constructor(outStream, chunkDurationSeconds) {
|
|
7316
8424
|
super(outStream);
|
|
@@ -7319,11 +8427,11 @@ class SequenceAudioFloat32ChunkerOutStream extends Float32ArrayChunkerOutStream
|
|
|
7319
8427
|
this.sequenceAudioFloat32OutStream = outStream;
|
|
7320
8428
|
}
|
|
7321
8429
|
setFormat(channels, sampleRate) {
|
|
7322
|
-
console.debug("SequenceAudioFloat32ChunkerOutStream:setFormat(channels: "
|
|
8430
|
+
//console.debug("SequenceAudioFloat32ChunkerOutStream:setFormat(channels: "+channels+",sampleRate: "+sampleRate+")")
|
|
7323
8431
|
this.channels = channels;
|
|
7324
8432
|
this.sampleRate = sampleRate;
|
|
7325
8433
|
this.chunkSize = Math.round(sampleRate * this.chunkDurationSeconds);
|
|
7326
|
-
console.debug("SequenceAudioFloat32ChunkerOutStream: chunkSize: "
|
|
8434
|
+
//console.debug("SequenceAudioFloat32ChunkerOutStream: chunkSize: "+this.chunkSize);
|
|
7327
8435
|
this.sequenceAudioFloat32OutStream.setFormat(channels, sampleRate);
|
|
7328
8436
|
}
|
|
7329
8437
|
nextStream() {
|
|
@@ -7530,7 +8638,8 @@ class ChunkManager {
|
|
|
7530
8638
|
}
|
|
7531
8639
|
}
|
|
7532
8640
|
let BasicRecorder = class BasicRecorder {
|
|
7533
|
-
constructor(dialog, sessionService, uploader, config) {
|
|
8641
|
+
constructor(changeDetectorRef, dialog, sessionService, uploader, config) {
|
|
8642
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
7534
8643
|
this.dialog = dialog;
|
|
7535
8644
|
this.sessionService = sessionService;
|
|
7536
8645
|
this.uploader = uploader;
|
|
@@ -7545,6 +8654,7 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7545
8654
|
this._selectedDeviceId = undefined;
|
|
7546
8655
|
this._channelCount = 2;
|
|
7547
8656
|
this._session = null;
|
|
8657
|
+
this._recordingFile = null;
|
|
7548
8658
|
this.startedDate = null;
|
|
7549
8659
|
this.uploadProgress = 100;
|
|
7550
8660
|
this.uploadStatus = 'ok';
|
|
@@ -7552,6 +8662,7 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7552
8662
|
this.peakLevelInDb = MIN_DB_LEVEL;
|
|
7553
8663
|
this.displayAudioClip = null;
|
|
7554
8664
|
this.audioFetchSubscription = null;
|
|
8665
|
+
this.audioFetching = false;
|
|
7555
8666
|
this.destroyed = false;
|
|
7556
8667
|
this.navigationDisabled = true;
|
|
7557
8668
|
// Default: Disabled chunked upload
|
|
@@ -7646,6 +8757,28 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7646
8757
|
this.ac.audioOutStream = outStream;
|
|
7647
8758
|
}
|
|
7648
8759
|
}
|
|
8760
|
+
showRecording() {
|
|
8761
|
+
this._controlAudioPlayer.stop();
|
|
8762
|
+
if (this.displayAudioClip) {
|
|
8763
|
+
let dap = this.displayAudioClip;
|
|
8764
|
+
let adh = dap.audioDataHolder;
|
|
8765
|
+
if (adh) {
|
|
8766
|
+
this.levelMeasure.calcBufferLevelInfos(adh, LEVEL_BAR_INTERVALL_SECONDS).then((levelInfos) => {
|
|
8767
|
+
dap.levelInfos = levelInfos;
|
|
8768
|
+
this.changeDetectorRef.detectChanges();
|
|
8769
|
+
});
|
|
8770
|
+
}
|
|
8771
|
+
this.playStartAction.disabled = false;
|
|
8772
|
+
}
|
|
8773
|
+
else {
|
|
8774
|
+
this.playStartAction.disabled = true;
|
|
8775
|
+
// Collapse audio signal display if open
|
|
8776
|
+
if (!this.audioSignalCollapsed) {
|
|
8777
|
+
this.audioSignalCollapsed = true;
|
|
8778
|
+
}
|
|
8779
|
+
}
|
|
8780
|
+
this.changeDetectorRef.detectChanges();
|
|
8781
|
+
}
|
|
7649
8782
|
start() {
|
|
7650
8783
|
this.statusAlertType = 'info';
|
|
7651
8784
|
this.statusMsg = 'Starting session...';
|
|
@@ -7866,9 +8999,9 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7866
8999
|
}
|
|
7867
9000
|
this.transportActions.startAction.disabled = true;
|
|
7868
9001
|
}
|
|
7869
|
-
postRecording(wavFile, recUrl) {
|
|
9002
|
+
postRecording(wavFile, recUrl, rf) {
|
|
7870
9003
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
7871
|
-
let ul = new Upload(wavBlob, recUrl);
|
|
9004
|
+
let ul = new Upload(wavBlob, recUrl, rf);
|
|
7872
9005
|
this.uploader.queueUpload(ul);
|
|
7873
9006
|
}
|
|
7874
9007
|
postAudioStreamStart() {
|
|
@@ -7904,42 +9037,334 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7904
9037
|
if (this.config && this.config.apiEndPoint) {
|
|
7905
9038
|
apiEndPoint = this.config.apiEndPoint;
|
|
7906
9039
|
}
|
|
7907
|
-
if (apiEndPoint !== '') {
|
|
7908
|
-
apiEndPoint = apiEndPoint + '/';
|
|
9040
|
+
if (apiEndPoint !== '') {
|
|
9041
|
+
apiEndPoint = apiEndPoint + '/';
|
|
9042
|
+
}
|
|
9043
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
9044
|
+
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/concatChunksRequest';
|
|
9045
|
+
let fd = new FormData();
|
|
9046
|
+
fd.set('uuid', this.rfUuid);
|
|
9047
|
+
fd.set('chunkCount', chunkCount.toString());
|
|
9048
|
+
let ul = new Upload(fd, recUrl, this._recordingFile);
|
|
9049
|
+
this.uploader.queueUpload(ul);
|
|
9050
|
+
console.debug("Queued for upload: " + this._recordingFile);
|
|
9051
|
+
}
|
|
9052
|
+
else {
|
|
9053
|
+
console.error("Recording file UUID not set!");
|
|
9054
|
+
}
|
|
9055
|
+
}
|
|
9056
|
+
closed() {
|
|
9057
|
+
this.statusAlertType = 'info';
|
|
9058
|
+
this.statusMsg = 'Session closed.';
|
|
9059
|
+
}
|
|
9060
|
+
error(msg = 'An unknown error occured during recording.', advice = 'Please retry.') {
|
|
9061
|
+
this.statusMsg = 'ERROR: Recording.';
|
|
9062
|
+
this.statusAlertType = 'error';
|
|
9063
|
+
this.dialog.open(MessageDialog, {
|
|
9064
|
+
data: {
|
|
9065
|
+
type: 'error',
|
|
9066
|
+
title: 'Recording error',
|
|
9067
|
+
msg: msg,
|
|
9068
|
+
advice: advice
|
|
9069
|
+
}
|
|
9070
|
+
});
|
|
9071
|
+
}
|
|
9072
|
+
};
|
|
9073
|
+
// Enable only for developemnt/debug purposes of array audio buffers !!
|
|
9074
|
+
BasicRecorder.FORCE_ARRRAY_AUDIO_BUFFER = false;
|
|
9075
|
+
BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS = 30;
|
|
9076
|
+
BasicRecorder = __decorate([
|
|
9077
|
+
__param(4, Inject(SPEECHRECORDER_CONFIG))
|
|
9078
|
+
], BasicRecorder);
|
|
9079
|
+
|
|
9080
|
+
class AudioDataHolder {
|
|
9081
|
+
constructor(_buffer, _arrayBuffer = null) {
|
|
9082
|
+
this._buffer = _buffer;
|
|
9083
|
+
this._arrayBuffer = _arrayBuffer;
|
|
9084
|
+
this._numberOfChannels = 0;
|
|
9085
|
+
this._sampleRate = 0;
|
|
9086
|
+
this._frameLen = 0;
|
|
9087
|
+
this._duration = 0;
|
|
9088
|
+
if (this._buffer && this._arrayBuffer) {
|
|
9089
|
+
throw Error('Only one of either audio buffer or array audio buffer must be set!');
|
|
9090
|
+
}
|
|
9091
|
+
if (this._buffer || this._arrayBuffer) {
|
|
9092
|
+
if (this._buffer) {
|
|
9093
|
+
this._numberOfChannels = this._buffer.numberOfChannels;
|
|
9094
|
+
this._sampleRate = this._buffer.sampleRate;
|
|
9095
|
+
this._frameLen = this._buffer.length;
|
|
9096
|
+
this._duration = this._frameLen / this._sampleRate;
|
|
9097
|
+
}
|
|
9098
|
+
else if (this._arrayBuffer) {
|
|
9099
|
+
this._numberOfChannels = this._arrayBuffer.channelCount;
|
|
9100
|
+
this._sampleRate = this._arrayBuffer.sampleRate;
|
|
9101
|
+
this._frameLen = this._arrayBuffer.frameLen;
|
|
9102
|
+
this._duration = this._frameLen / this._sampleRate;
|
|
9103
|
+
}
|
|
9104
|
+
}
|
|
9105
|
+
else {
|
|
9106
|
+
throw Error(AudioDataHolder.ONE_OF_MUST_BE_SET_ERR_MSG);
|
|
9107
|
+
}
|
|
9108
|
+
}
|
|
9109
|
+
get duration() {
|
|
9110
|
+
return this._duration;
|
|
9111
|
+
}
|
|
9112
|
+
get sampleRate() {
|
|
9113
|
+
return this._sampleRate;
|
|
9114
|
+
}
|
|
9115
|
+
get numberOfChannels() {
|
|
9116
|
+
return this._numberOfChannels;
|
|
9117
|
+
}
|
|
9118
|
+
get frameLen() {
|
|
9119
|
+
return this._frameLen;
|
|
9120
|
+
}
|
|
9121
|
+
sampleCounts() {
|
|
9122
|
+
return this._numberOfChannels * this._frameLen;
|
|
9123
|
+
}
|
|
9124
|
+
frames(framePos, frameLen, bufs) {
|
|
9125
|
+
let read = 0;
|
|
9126
|
+
if (this._buffer) {
|
|
9127
|
+
let toRead = frameLen;
|
|
9128
|
+
if (this._buffer.length < framePos + frameLen) {
|
|
9129
|
+
toRead = this._buffer.length - framePos;
|
|
9130
|
+
}
|
|
9131
|
+
for (let ch = 0; ch < bufs.length; ch++) {
|
|
9132
|
+
let chData = this._buffer.getChannelData(ch);
|
|
9133
|
+
for (let i = 0; i < toRead; i++) {
|
|
9134
|
+
bufs[ch][i] = chData[framePos + i];
|
|
9135
|
+
}
|
|
9136
|
+
}
|
|
9137
|
+
read = toRead;
|
|
9138
|
+
}
|
|
9139
|
+
else if (this._arrayBuffer) {
|
|
9140
|
+
read = this._arrayBuffer.frames(framePos, frameLen, bufs);
|
|
9141
|
+
}
|
|
9142
|
+
return read;
|
|
9143
|
+
}
|
|
9144
|
+
audioInputStream() {
|
|
9145
|
+
if (this._buffer) {
|
|
9146
|
+
return new AudioBufferInputStream(this._buffer);
|
|
9147
|
+
}
|
|
9148
|
+
if (this._arrayBuffer) {
|
|
9149
|
+
return new ArrayAudioBufferInputStream(this._arrayBuffer);
|
|
9150
|
+
}
|
|
9151
|
+
throw Error(AudioDataHolder.ONE_OF_MUST_BE_SET_ERR_MSG);
|
|
9152
|
+
}
|
|
9153
|
+
get buffer() {
|
|
9154
|
+
return this._buffer;
|
|
9155
|
+
}
|
|
9156
|
+
get arrayBuffer() {
|
|
9157
|
+
return this._arrayBuffer;
|
|
9158
|
+
}
|
|
9159
|
+
}
|
|
9160
|
+
AudioDataHolder.ONE_OF_MUST_BE_SET_ERR_MSG = 'One of either audio buffer or array audio buffer must be set!';
|
|
9161
|
+
class AudioBufferInputStream {
|
|
9162
|
+
constructor(audioBuffer) {
|
|
9163
|
+
this.audioBuffer = audioBuffer;
|
|
9164
|
+
this.framePos = 0;
|
|
9165
|
+
}
|
|
9166
|
+
close() {
|
|
9167
|
+
}
|
|
9168
|
+
skipFrames(n) {
|
|
9169
|
+
this.framePos += n;
|
|
9170
|
+
}
|
|
9171
|
+
read(buffers) {
|
|
9172
|
+
let read = 0;
|
|
9173
|
+
let toRead = buffers[0].length;
|
|
9174
|
+
if (this.framePos + toRead > this.audioBuffer.length) {
|
|
9175
|
+
toRead = this.audioBuffer.length - this.framePos;
|
|
9176
|
+
}
|
|
9177
|
+
for (let ch = 0; ch < buffers.length; ch++) {
|
|
9178
|
+
for (let i = 0; i < toRead; i++) {
|
|
9179
|
+
buffers[ch][i] = this.audioBuffer.getChannelData(ch)[this.framePos + i];
|
|
9180
|
+
}
|
|
9181
|
+
}
|
|
9182
|
+
read = toRead;
|
|
9183
|
+
this.framePos += toRead;
|
|
9184
|
+
return read;
|
|
9185
|
+
}
|
|
9186
|
+
}
|
|
9187
|
+
|
|
9188
|
+
class BasicRecFilesCache {
|
|
9189
|
+
constructor() {
|
|
9190
|
+
//public static readonly DEFAULT_MAX_SAMPLES=30*48000; // TEST 30 seconds
|
|
9191
|
+
this._sampleCount = 0;
|
|
9192
|
+
this.maxSampleCount = SprItemsCache.DEFAULT_MAX_SAMPLES;
|
|
9193
|
+
this.currentRecordingFile = null;
|
|
9194
|
+
}
|
|
9195
|
+
}
|
|
9196
|
+
BasicRecFilesCache.DEBUG = false;
|
|
9197
|
+
BasicRecFilesCache.DEFAULT_MAX_SAMPLES = 10 * 60 * 48000; // 20 Minutes mono 48kHz
|
|
9198
|
+
class SprItemsCache extends BasicRecFilesCache {
|
|
9199
|
+
constructor() {
|
|
9200
|
+
super(...arguments);
|
|
9201
|
+
this._items = new Array();
|
|
9202
|
+
}
|
|
9203
|
+
get items() {
|
|
9204
|
+
return this._items;
|
|
9205
|
+
}
|
|
9206
|
+
addItem(item) {
|
|
9207
|
+
this._items.push(item);
|
|
9208
|
+
}
|
|
9209
|
+
getItem(index) {
|
|
9210
|
+
return this._items[index];
|
|
9211
|
+
}
|
|
9212
|
+
length() {
|
|
9213
|
+
return this._items.length;
|
|
9214
|
+
}
|
|
9215
|
+
tryExpire(toBeExpiredRf) {
|
|
9216
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9217
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " try expire:");
|
|
9218
|
+
if (!toBeExpiredRf.equals(this.currentRecordingFile)) {
|
|
9219
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9220
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " not current file...");
|
|
9221
|
+
if (toBeExpiredRf.serverPersisted) {
|
|
9222
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9223
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " is server persisted...");
|
|
9224
|
+
// expire recording files first stored to the cache
|
|
9225
|
+
let expiredAudio = RecordingFileUtils.expireAudioData(toBeExpiredRf);
|
|
9226
|
+
if (expiredAudio) {
|
|
9227
|
+
this._sampleCount -= expiredAudio.sampleCounts();
|
|
9228
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9229
|
+
console.debug("Rec. files cache: Expired: " + toBeExpiredRf.toString() + ". Cache samples now: " + this._sampleCount);
|
|
9230
|
+
}
|
|
9231
|
+
}
|
|
9232
|
+
else {
|
|
9233
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9234
|
+
console.debug("Rec. files cache: #" + toBeExpiredRf.toString() + " not yet persisted on server.");
|
|
7909
9235
|
}
|
|
7910
|
-
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
7911
|
-
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/concatChunksRequest';
|
|
7912
|
-
let fd = new FormData();
|
|
7913
|
-
fd.set('uuid', this.rfUuid);
|
|
7914
|
-
fd.set('chunkCount', chunkCount.toString());
|
|
7915
|
-
let ul = new Upload(fd, recUrl);
|
|
7916
|
-
this.uploader.queueUpload(ul);
|
|
7917
9236
|
}
|
|
7918
9237
|
else {
|
|
7919
|
-
|
|
9238
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9239
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " is current file.");
|
|
9240
|
+
}
|
|
9241
|
+
}
|
|
9242
|
+
expire() {
|
|
9243
|
+
// expire corrected versions first
|
|
9244
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9245
|
+
console.debug("Rec. files cache: Expire? current: " + this._sampleCount + ", max: " + this.maxSampleCount);
|
|
9246
|
+
if (this._sampleCount > this.maxSampleCount) {
|
|
9247
|
+
// expire older versions of an item first
|
|
9248
|
+
for (let ii = 0; ii < this._items.length; ii++) {
|
|
9249
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9250
|
+
break;
|
|
9251
|
+
}
|
|
9252
|
+
let it = this._items[ii];
|
|
9253
|
+
let itRfs = it.recs;
|
|
9254
|
+
if (itRfs && itRfs.length > 1) {
|
|
9255
|
+
for (let rfi = 0; rfi < itRfs.length - 1; rfi++) {
|
|
9256
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9257
|
+
break;
|
|
9258
|
+
}
|
|
9259
|
+
let toBeExpiredRf = itRfs[rfi];
|
|
9260
|
+
this.tryExpire(toBeExpiredRf);
|
|
9261
|
+
}
|
|
9262
|
+
}
|
|
9263
|
+
}
|
|
9264
|
+
// if that's not sufficient expire audio data of latest versions as well
|
|
9265
|
+
for (let ii = 0; ii < this._items.length; ii++) {
|
|
9266
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9267
|
+
break;
|
|
9268
|
+
}
|
|
9269
|
+
let it = this._items[ii];
|
|
9270
|
+
let itRfs = it.recs;
|
|
9271
|
+
if (itRfs && itRfs.length > 0) {
|
|
9272
|
+
for (let rfi = 0; rfi < itRfs.length; rfi++) {
|
|
9273
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9274
|
+
break;
|
|
9275
|
+
}
|
|
9276
|
+
let toBeExpiredRf = itRfs[rfi];
|
|
9277
|
+
this.tryExpire(toBeExpiredRf);
|
|
9278
|
+
}
|
|
9279
|
+
}
|
|
9280
|
+
}
|
|
7920
9281
|
}
|
|
7921
9282
|
}
|
|
7922
|
-
|
|
7923
|
-
this.
|
|
7924
|
-
|
|
9283
|
+
addSprRecFile(item, sprRecFile) {
|
|
9284
|
+
this.expire();
|
|
9285
|
+
if (!item.recs) {
|
|
9286
|
+
item.recs = new Array();
|
|
9287
|
+
}
|
|
9288
|
+
item.recs.push(sprRecFile);
|
|
9289
|
+
this._sampleCount += RecordingFileUtils.sampleCount(sprRecFile);
|
|
9290
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9291
|
+
console.debug("Rec. files cache: Added. Cache samples: " + this._sampleCount);
|
|
7925
9292
|
}
|
|
7926
|
-
|
|
7927
|
-
this.
|
|
7928
|
-
|
|
7929
|
-
|
|
7930
|
-
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
9293
|
+
setSprRecFileAudioData(sprRecFile, adh) {
|
|
9294
|
+
this.expire();
|
|
9295
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9296
|
+
console.debug("Rec. files cache: Set audio data after expire. Cache samples: " + this._sampleCount);
|
|
9297
|
+
let currSampleCnt = RecordingFileUtils.sampleCount(sprRecFile);
|
|
9298
|
+
this._sampleCount -= currSampleCnt;
|
|
9299
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9300
|
+
console.debug("Rec. files cache: Set audio data subtracted curr sample count: " + currSampleCnt + ". Cache samples: " + this._sampleCount);
|
|
9301
|
+
RecordingFileUtils.setAudioData(sprRecFile, adh);
|
|
9302
|
+
let newSampleCnt = RecordingFileUtils.sampleCount(sprRecFile);
|
|
9303
|
+
this._sampleCount += newSampleCnt;
|
|
9304
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9305
|
+
console.debug("Rec. files cache: Set audio data added new sample count: " + newSampleCnt + ". Cache samples: " + this._sampleCount);
|
|
9306
|
+
let fl = adh === null || adh === void 0 ? void 0 : adh.frameLen;
|
|
9307
|
+
if (fl) {
|
|
9308
|
+
sprRecFile.frames = fl;
|
|
9309
|
+
}
|
|
9310
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9311
|
+
console.debug("Rec. files cache: Set audio data. Cache samples: " + this._sampleCount);
|
|
9312
|
+
}
|
|
9313
|
+
}
|
|
9314
|
+
class RecFilesCache extends BasicRecFilesCache {
|
|
9315
|
+
constructor() {
|
|
9316
|
+
super(...arguments);
|
|
9317
|
+
this._recFiles = new Array();
|
|
9318
|
+
}
|
|
9319
|
+
get recFiles() {
|
|
9320
|
+
return this._recFiles;
|
|
9321
|
+
}
|
|
9322
|
+
getRecFile(index) {
|
|
9323
|
+
return this._recFiles[index];
|
|
9324
|
+
}
|
|
9325
|
+
length() {
|
|
9326
|
+
return this._recFiles.length;
|
|
9327
|
+
}
|
|
9328
|
+
expire() {
|
|
9329
|
+
if (this._sampleCount > this.maxSampleCount) {
|
|
9330
|
+
// audio recorder list is sorted: lower index is newer
|
|
9331
|
+
for (let rfI = this._recFiles.length - 1; rfI >= 0; rfI--) {
|
|
9332
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9333
|
+
break;
|
|
9334
|
+
}
|
|
9335
|
+
let toBeExpiredRf = this._recFiles[rfI];
|
|
9336
|
+
if (toBeExpiredRf.serverPersisted) {
|
|
9337
|
+
// expire recording files first stored to the cache
|
|
9338
|
+
let expiredAudio = RecordingFileUtils.expireAudioData(toBeExpiredRf);
|
|
9339
|
+
if (expiredAudio) {
|
|
9340
|
+
this._sampleCount -= expiredAudio.sampleCounts();
|
|
9341
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9342
|
+
console.debug("Rec. files cache: Expired #" + rfI + ". Cache samples: " + this._sampleCount);
|
|
9343
|
+
}
|
|
9344
|
+
}
|
|
9345
|
+
else {
|
|
9346
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9347
|
+
console.debug("Rec. files cache: #" + rfI + " not yet server persisted.");
|
|
9348
|
+
}
|
|
7935
9349
|
}
|
|
7936
|
-
}
|
|
9350
|
+
}
|
|
7937
9351
|
}
|
|
7938
|
-
|
|
7939
|
-
|
|
7940
|
-
|
|
7941
|
-
|
|
7942
|
-
|
|
9352
|
+
addRecFile(recFile) {
|
|
9353
|
+
this.expire();
|
|
9354
|
+
this._recFiles.push(recFile);
|
|
9355
|
+
this._sampleCount += RecordingFileUtils.sampleCount(recFile);
|
|
9356
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9357
|
+
console.debug("Rec. files cache: Added. Cache samples: " + this._sampleCount);
|
|
9358
|
+
}
|
|
9359
|
+
setRecFileAudioData(recFile, adh) {
|
|
9360
|
+
this.expire();
|
|
9361
|
+
this._sampleCount -= RecordingFileUtils.sampleCount(recFile);
|
|
9362
|
+
RecordingFileUtils.setAudioData(recFile, adh);
|
|
9363
|
+
this._sampleCount += RecordingFileUtils.sampleCount(recFile);
|
|
9364
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9365
|
+
console.debug("Rec. files cache: Set audio data. Cache samples: " + this._sampleCount);
|
|
9366
|
+
}
|
|
9367
|
+
}
|
|
7943
9368
|
|
|
7944
9369
|
/**
|
|
7945
9370
|
* Created by klausj on 17.06.2017.
|
|
@@ -8032,16 +9457,65 @@ class RecordingService {
|
|
|
8032
9457
|
let recUrl = recFilesUrl + '/' + encItemcode + '/' + version;
|
|
8033
9458
|
return this.audioRequest(recUrl);
|
|
8034
9459
|
}
|
|
9460
|
+
fetchRecordingFileAudioBuffer(aCtx, projectName, recordingFile) {
|
|
9461
|
+
let wobs = new Observable(observer => {
|
|
9462
|
+
let recFileId = recordingFile.recordingFileId;
|
|
9463
|
+
if (!recFileId) {
|
|
9464
|
+
recFileId = recordingFile.uuid;
|
|
9465
|
+
}
|
|
9466
|
+
if (recordingFile.session && recFileId) {
|
|
9467
|
+
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
9468
|
+
obs.subscribe({
|
|
9469
|
+
next: resp => {
|
|
9470
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9471
|
+
if (resp.body) {
|
|
9472
|
+
aCtx.decodeAudioData(resp.body, ab => {
|
|
9473
|
+
observer.next(ab);
|
|
9474
|
+
observer.complete();
|
|
9475
|
+
}, error => {
|
|
9476
|
+
observer.error(error);
|
|
9477
|
+
observer.complete();
|
|
9478
|
+
});
|
|
9479
|
+
}
|
|
9480
|
+
else {
|
|
9481
|
+
observer.error('Fetching audio file: response has no body');
|
|
9482
|
+
}
|
|
9483
|
+
},
|
|
9484
|
+
error: (error) => {
|
|
9485
|
+
if (error.status == 404) {
|
|
9486
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9487
|
+
observer.next(null);
|
|
9488
|
+
observer.complete();
|
|
9489
|
+
}
|
|
9490
|
+
else {
|
|
9491
|
+
// all other states are errors
|
|
9492
|
+
observer.error(error);
|
|
9493
|
+
observer.complete();
|
|
9494
|
+
}
|
|
9495
|
+
}
|
|
9496
|
+
});
|
|
9497
|
+
}
|
|
9498
|
+
else {
|
|
9499
|
+
observer.error();
|
|
9500
|
+
}
|
|
9501
|
+
});
|
|
9502
|
+
return wobs;
|
|
9503
|
+
}
|
|
8035
9504
|
fetchAndApplyRecordingFile(aCtx, projectName, recordingFile) {
|
|
8036
9505
|
let wobs = new Observable(observer => {
|
|
8037
|
-
|
|
8038
|
-
|
|
9506
|
+
let recFileId = recordingFile.recordingFileId;
|
|
9507
|
+
if (!recFileId) {
|
|
9508
|
+
recFileId = recordingFile.uuid;
|
|
9509
|
+
}
|
|
9510
|
+
if (recordingFile.session && recFileId) {
|
|
9511
|
+
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
8039
9512
|
obs.subscribe(resp => {
|
|
8040
9513
|
//console.log("Fetched audio file. HTTP response status: "+resp.status+", type: "+resp.type+", byte length: "+ resp.body.byteLength);
|
|
8041
9514
|
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
8042
9515
|
if (resp.body) {
|
|
8043
9516
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
8044
|
-
|
|
9517
|
+
let adh = new AudioDataHolder(ab, null);
|
|
9518
|
+
RecordingFileUtils.setAudioData(recordingFile, adh);
|
|
8045
9519
|
if (this.debugDelay > 0) {
|
|
8046
9520
|
window.setTimeout(() => {
|
|
8047
9521
|
observer.next(recordingFile);
|
|
@@ -8079,6 +9553,47 @@ class RecordingService {
|
|
|
8079
9553
|
});
|
|
8080
9554
|
return wobs;
|
|
8081
9555
|
}
|
|
9556
|
+
fetchSprRecordingFileAudioBuffer(aCtx, projectName, recordingFile) {
|
|
9557
|
+
let wobs = new Observable(observer => {
|
|
9558
|
+
if (recordingFile.session) {
|
|
9559
|
+
let obs = this.fetchSprAudiofile(projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
9560
|
+
obs.subscribe({
|
|
9561
|
+
next: resp => {
|
|
9562
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9563
|
+
if (resp.body) {
|
|
9564
|
+
aCtx.decodeAudioData(resp.body, ab => {
|
|
9565
|
+
//RecordingFileUtils.setAudioData(recordingFile,new AudioDataHolder(ab,null));
|
|
9566
|
+
observer.next(ab);
|
|
9567
|
+
observer.complete();
|
|
9568
|
+
}, error => {
|
|
9569
|
+
observer.error(error);
|
|
9570
|
+
observer.complete();
|
|
9571
|
+
});
|
|
9572
|
+
}
|
|
9573
|
+
else {
|
|
9574
|
+
observer.error('Fetching audio file: response has no body');
|
|
9575
|
+
}
|
|
9576
|
+
},
|
|
9577
|
+
error: (error) => {
|
|
9578
|
+
if (error.status == 404) {
|
|
9579
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9580
|
+
observer.next(null);
|
|
9581
|
+
observer.complete();
|
|
9582
|
+
}
|
|
9583
|
+
else {
|
|
9584
|
+
// all other states are errors
|
|
9585
|
+
observer.error(error);
|
|
9586
|
+
observer.complete();
|
|
9587
|
+
}
|
|
9588
|
+
}
|
|
9589
|
+
});
|
|
9590
|
+
}
|
|
9591
|
+
else {
|
|
9592
|
+
observer.error();
|
|
9593
|
+
}
|
|
9594
|
+
});
|
|
9595
|
+
return wobs;
|
|
9596
|
+
}
|
|
8082
9597
|
fetchAndApplySprRecordingFile(aCtx, projectName, recordingFile) {
|
|
8083
9598
|
let wobs = new Observable(observer => {
|
|
8084
9599
|
if (recordingFile.session) {
|
|
@@ -8088,7 +9603,7 @@ class RecordingService {
|
|
|
8088
9603
|
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
8089
9604
|
if (resp.body) {
|
|
8090
9605
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
8091
|
-
recordingFile
|
|
9606
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(ab, null));
|
|
8092
9607
|
if (this.debugDelay > 0) {
|
|
8093
9608
|
window.setTimeout(() => {
|
|
8094
9609
|
observer.next(recordingFile);
|
|
@@ -8133,7 +9648,8 @@ class RecordingService {
|
|
|
8133
9648
|
// Do not use Promise version, which does not work with Safari 13
|
|
8134
9649
|
if (resp.body) {
|
|
8135
9650
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
8136
|
-
let
|
|
9651
|
+
let adh = new AudioDataHolder(ab, null);
|
|
9652
|
+
let rf = new SprRecordingFile(sessId, itemcode, version, adh);
|
|
8137
9653
|
if (this.debugDelay > 0) {
|
|
8138
9654
|
window.setTimeout(() => {
|
|
8139
9655
|
observer.next(rf);
|
|
@@ -8253,14 +9769,9 @@ const DEFAULT_PRE_REC_DELAY = 1000;
|
|
|
8253
9769
|
const DEFAULT_POST_REC_DELAY = 500;
|
|
8254
9770
|
class SessionManager extends BasicRecorder {
|
|
8255
9771
|
constructor(changeDetectorRef, renderer, dialog, sessionService, recFileService, uploader, config) {
|
|
8256
|
-
super(dialog, sessionService, uploader, config);
|
|
8257
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
9772
|
+
super(changeDetectorRef, dialog, sessionService, uploader, config);
|
|
8258
9773
|
this.renderer = renderer;
|
|
8259
|
-
this.dialog = dialog;
|
|
8260
|
-
this.sessionService = sessionService;
|
|
8261
9774
|
this.recFileService = recFileService;
|
|
8262
|
-
this.uploader = uploader;
|
|
8263
|
-
this.config = config;
|
|
8264
9775
|
this.enableUploadRecordings = true;
|
|
8265
9776
|
this.enableDownloadRecordings = false;
|
|
8266
9777
|
this.status = 0 /* BLOCKED */;
|
|
@@ -8294,7 +9805,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8294
9805
|
};
|
|
8295
9806
|
}
|
|
8296
9807
|
ngOnDestroy() {
|
|
8297
|
-
console.debug("Com destroy, disable wake lock.")
|
|
9808
|
+
//console.debug("Com destroy, disable wake lock.")
|
|
8298
9809
|
this.disableWakeLockCond();
|
|
8299
9810
|
this.destroyed = true;
|
|
8300
9811
|
// TODO stop capture /playback
|
|
@@ -8425,7 +9936,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8425
9936
|
progressPercentValue() {
|
|
8426
9937
|
let v = 100;
|
|
8427
9938
|
if (this.items) {
|
|
8428
|
-
v = this.promptIndex * 100 / (this.items.length - 1);
|
|
9939
|
+
v = this.promptIndex * 100 / (this.items.length() - 1);
|
|
8429
9940
|
}
|
|
8430
9941
|
return v;
|
|
8431
9942
|
}
|
|
@@ -8439,9 +9950,6 @@ class SessionManager extends BasicRecorder {
|
|
|
8439
9950
|
return ((this._session != null) && (this._session.type === 'TEST_DEF_A') && (this.audioDevices != null) && this.audioDevices.length > 0);
|
|
8440
9951
|
}
|
|
8441
9952
|
set controlAudioPlayer(controlAudioPlayer) {
|
|
8442
|
-
if (this._controlAudioPlayer) {
|
|
8443
|
-
//this._controlAudioPlayer.listener=null;
|
|
8444
|
-
}
|
|
8445
9953
|
this._controlAudioPlayer = controlAudioPlayer;
|
|
8446
9954
|
if (this._controlAudioPlayer) {
|
|
8447
9955
|
this._controlAudioPlayer.listener = this;
|
|
@@ -8526,6 +10034,8 @@ class SessionManager extends BasicRecorder {
|
|
|
8526
10034
|
this.autorecording = true;
|
|
8527
10035
|
}
|
|
8528
10036
|
if (this.ac != null) {
|
|
10037
|
+
// Hide loading hint on livelevel display
|
|
10038
|
+
this.audioFetching = false;
|
|
8529
10039
|
if (!this.ac.opened) {
|
|
8530
10040
|
if (this._selectedDeviceId) {
|
|
8531
10041
|
console.log("Open session with audio device Id: \'" + this._selectedDeviceId + "\' for " + this._channelCount + " channels");
|
|
@@ -8542,7 +10052,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8542
10052
|
}
|
|
8543
10053
|
loadScript() {
|
|
8544
10054
|
this.promptItemCount = 0;
|
|
8545
|
-
this.items = new
|
|
10055
|
+
this.items = new SprItemsCache();
|
|
8546
10056
|
let ln = 0;
|
|
8547
10057
|
//TODO randomize not supported
|
|
8548
10058
|
for (let si = 0; si < this._script.sections.length; si++) {
|
|
@@ -8556,7 +10066,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8556
10066
|
let pi = pis[piSectIdx];
|
|
8557
10067
|
let promptAsStr = PromptitemUtil.toPlainTextString(pi);
|
|
8558
10068
|
let it = new Item$1(promptAsStr, section.training, (!pi.type || pi.type === 'recording'));
|
|
8559
|
-
this.items.
|
|
10069
|
+
this.items.addItem(it);
|
|
8560
10070
|
ln++;
|
|
8561
10071
|
}
|
|
8562
10072
|
}
|
|
@@ -8597,10 +10107,10 @@ class SessionManager extends BasicRecorder {
|
|
|
8597
10107
|
}
|
|
8598
10108
|
downloadRecording() {
|
|
8599
10109
|
if (this.displayRecFile) {
|
|
8600
|
-
let ab = this.displayRecFile.
|
|
10110
|
+
let ab = this.displayRecFile.audioDataHolder;
|
|
8601
10111
|
let ww = new WavWriter();
|
|
8602
|
-
if (ab) {
|
|
8603
|
-
let wavFile = ww.writeAsync(ab, (wavFile) => {
|
|
10112
|
+
if (ab === null || ab === void 0 ? void 0 : ab.buffer) {
|
|
10113
|
+
let wavFile = ww.writeAsync(ab.buffer, (wavFile) => {
|
|
8604
10114
|
let blob = new Blob([wavFile], { type: 'audio/wav' });
|
|
8605
10115
|
let rfUrl = URL.createObjectURL(blob);
|
|
8606
10116
|
let dataDnlLnk = this.renderer.createElement('a');
|
|
@@ -8623,7 +10133,10 @@ class SessionManager extends BasicRecorder {
|
|
|
8623
10133
|
set displayRecFile(displayRecFile) {
|
|
8624
10134
|
this._displayRecFile = displayRecFile;
|
|
8625
10135
|
if (this._displayRecFile) {
|
|
8626
|
-
|
|
10136
|
+
if (this.items) {
|
|
10137
|
+
this.items.currentRecordingFile = this._displayRecFile;
|
|
10138
|
+
}
|
|
10139
|
+
let ab = this._displayRecFile.audioDataHolder;
|
|
8627
10140
|
if (ab) {
|
|
8628
10141
|
this.displayAudioClip = new AudioClip(ab);
|
|
8629
10142
|
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
@@ -8631,27 +10144,46 @@ class SessionManager extends BasicRecorder {
|
|
|
8631
10144
|
else {
|
|
8632
10145
|
// clear for now ...
|
|
8633
10146
|
this.displayAudioClip = null;
|
|
8634
|
-
this.controlAudioPlayer
|
|
10147
|
+
if (this.controlAudioPlayer) {
|
|
10148
|
+
this.controlAudioPlayer.audioClip = null;
|
|
10149
|
+
}
|
|
8635
10150
|
if (this._controlAudioPlayer && this._session) {
|
|
8636
10151
|
//... and try to fetch from server
|
|
8637
|
-
this.
|
|
8638
|
-
|
|
8639
|
-
|
|
8640
|
-
|
|
8641
|
-
|
|
8642
|
-
|
|
8643
|
-
|
|
10152
|
+
this.audioFetching = true;
|
|
10153
|
+
let rf = this._displayRecFile;
|
|
10154
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this._controlAudioPlayer.context, this._session.project, rf).subscribe({
|
|
10155
|
+
next: (ab) => {
|
|
10156
|
+
this.audioFetching = false;
|
|
10157
|
+
let fabDh = null;
|
|
10158
|
+
if (ab) {
|
|
10159
|
+
if (rf && this.items) {
|
|
10160
|
+
if (SessionManager.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
10161
|
+
let aab = ArrayAudioBuffer.fromAudioBuffer(ab);
|
|
10162
|
+
fabDh = new AudioDataHolder(null, aab);
|
|
10163
|
+
}
|
|
10164
|
+
else {
|
|
10165
|
+
fabDh = new AudioDataHolder(ab);
|
|
10166
|
+
}
|
|
10167
|
+
this.items.setSprRecFileAudioData(rf, fabDh);
|
|
10168
|
+
}
|
|
10169
|
+
}
|
|
10170
|
+
else {
|
|
10171
|
+
// Should actually be handled by the error resolver
|
|
10172
|
+
this.statusMsg = 'Recording file could not be loaded.';
|
|
10173
|
+
this.statusAlertType = 'error';
|
|
10174
|
+
}
|
|
10175
|
+
if (fabDh) {
|
|
10176
|
+
// this.displayAudioClip could have been changed meanwhile, but the recorder unsubcribes before changing the item. Therefore there should be no risk to set to wrong item
|
|
10177
|
+
this.displayAudioClip = new AudioClip(fabDh);
|
|
10178
|
+
}
|
|
10179
|
+
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
10180
|
+
this.showRecording();
|
|
10181
|
+
}, error: err => {
|
|
10182
|
+
console.error("Could not load recording file from server: " + err);
|
|
10183
|
+
this.audioFetching = false;
|
|
10184
|
+
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
8644
10185
|
this.statusAlertType = 'error';
|
|
8645
10186
|
}
|
|
8646
|
-
if (fab) {
|
|
8647
|
-
this.displayAudioClip = new AudioClip(fab);
|
|
8648
|
-
}
|
|
8649
|
-
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
8650
|
-
this.showRecording();
|
|
8651
|
-
}, err => {
|
|
8652
|
-
console.error("Could not load recording file from server: " + err);
|
|
8653
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
8654
|
-
this.statusAlertType = 'error';
|
|
8655
10187
|
});
|
|
8656
10188
|
}
|
|
8657
10189
|
else {
|
|
@@ -8662,31 +10194,14 @@ class SessionManager extends BasicRecorder {
|
|
|
8662
10194
|
}
|
|
8663
10195
|
else {
|
|
8664
10196
|
this.displayAudioClip = null;
|
|
8665
|
-
this.controlAudioPlayer
|
|
10197
|
+
if (this.controlAudioPlayer) {
|
|
10198
|
+
this.controlAudioPlayer.audioClip = null;
|
|
10199
|
+
}
|
|
8666
10200
|
}
|
|
8667
10201
|
}
|
|
8668
10202
|
get displayRecFile() {
|
|
8669
10203
|
return this._displayRecFile;
|
|
8670
10204
|
}
|
|
8671
|
-
showRecording() {
|
|
8672
|
-
this.controlAudioPlayer.stop();
|
|
8673
|
-
if (this.displayAudioClip) {
|
|
8674
|
-
let dap = this.displayAudioClip;
|
|
8675
|
-
this.levelMeasure.calcBufferLevelInfos(dap.buffer, LEVEL_BAR_INTERVALL_SECONDS).then((levelInfos) => {
|
|
8676
|
-
dap.levelInfos = levelInfos;
|
|
8677
|
-
this.changeDetectorRef.detectChanges();
|
|
8678
|
-
});
|
|
8679
|
-
this.playStartAction.disabled = false;
|
|
8680
|
-
}
|
|
8681
|
-
else {
|
|
8682
|
-
this.playStartAction.disabled = true;
|
|
8683
|
-
// Collapse audio signal display if open
|
|
8684
|
-
if (!this.audioSignalCollapsed) {
|
|
8685
|
-
this.audioSignalCollapsed = true;
|
|
8686
|
-
}
|
|
8687
|
-
}
|
|
8688
|
-
this.changeDetectorRef.detectChanges();
|
|
8689
|
-
}
|
|
8690
10205
|
isRecordingItem() {
|
|
8691
10206
|
return (this.promptItem != null && this.promptItem.type !== 'nonrecording');
|
|
8692
10207
|
}
|
|
@@ -8701,6 +10216,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8701
10216
|
if (this.audioFetchSubscription) {
|
|
8702
10217
|
this.audioFetchSubscription.unsubscribe();
|
|
8703
10218
|
}
|
|
10219
|
+
this.audioFetching = false;
|
|
8704
10220
|
this.clearPrompt();
|
|
8705
10221
|
let isNonrecording = (this.promptItem.type === 'nonrecording');
|
|
8706
10222
|
if (isNonrecording || !this.section.promptphase || this.section.promptphase === 'IDLE') {
|
|
@@ -8713,7 +10229,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8713
10229
|
}
|
|
8714
10230
|
else {
|
|
8715
10231
|
if (this.items) {
|
|
8716
|
-
let it = this.items
|
|
10232
|
+
let it = this.items.getItem(this.promptIndex);
|
|
8717
10233
|
if (!it.recs) {
|
|
8718
10234
|
it.recs = new Array();
|
|
8719
10235
|
}
|
|
@@ -8774,7 +10290,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8774
10290
|
updateNavigationActions() {
|
|
8775
10291
|
let fwdNxtActionDisabled = true;
|
|
8776
10292
|
if (this.items) {
|
|
8777
|
-
let currRecs = this.items
|
|
10293
|
+
let currRecs = this.items.getItem(this._promptIndex).recs;
|
|
8778
10294
|
fwdNxtActionDisabled = !(currRecs != null && currRecs.length > 0);
|
|
8779
10295
|
}
|
|
8780
10296
|
this.transportActions.fwdNextAction.disabled = this.navigationDisabled || fwdNxtActionDisabled;
|
|
@@ -8788,10 +10304,10 @@ class SessionManager extends BasicRecorder {
|
|
|
8788
10304
|
newPrIdx = 0;
|
|
8789
10305
|
}
|
|
8790
10306
|
if (this.items != null) {
|
|
8791
|
-
let itRecs = this.items
|
|
10307
|
+
let itRecs = this.items.getItem(newPrIdx).recs;
|
|
8792
10308
|
while (itRecs != null && (itRecs.length > 0) && newPrIdx < this.promptItemCount) {
|
|
8793
10309
|
newPrIdx++;
|
|
8794
|
-
itRecs = this.items
|
|
10310
|
+
itRecs = this.items.getItem(newPrIdx).recs;
|
|
8795
10311
|
}
|
|
8796
10312
|
if (!itRecs || itRecs.length == 0) {
|
|
8797
10313
|
this.promptIndex = newPrIdx;
|
|
@@ -8812,6 +10328,23 @@ class SessionManager extends BasicRecorder {
|
|
|
8812
10328
|
}
|
|
8813
10329
|
}
|
|
8814
10330
|
started() {
|
|
10331
|
+
let ic = this.promptItem.itemcode;
|
|
10332
|
+
let rf = null;
|
|
10333
|
+
if (this._session && ic) {
|
|
10334
|
+
let sessId = this._session.sessionId;
|
|
10335
|
+
let cpIdx = this.promptIndex;
|
|
10336
|
+
if (this.items) {
|
|
10337
|
+
let it = this.items.getItem(cpIdx);
|
|
10338
|
+
if (!it.recs) {
|
|
10339
|
+
it.recs = new Array();
|
|
10340
|
+
}
|
|
10341
|
+
rf = new SprRecordingFile(sessId, ic, it.recs.length, null);
|
|
10342
|
+
//it.recs.push(rf);
|
|
10343
|
+
this.items.addSprRecFile(it, rf);
|
|
10344
|
+
this.items.currentRecordingFile = rf;
|
|
10345
|
+
}
|
|
10346
|
+
}
|
|
10347
|
+
this._recordingFile = rf;
|
|
8815
10348
|
this.status = 3 /* PRE_RECORDING */;
|
|
8816
10349
|
super.started();
|
|
8817
10350
|
this.startStopSignalState = 1 /* PRERECORDING */;
|
|
@@ -8938,13 +10471,14 @@ class SessionManager extends BasicRecorder {
|
|
|
8938
10471
|
if (rfd.recording && rfd.recording.itemcode) {
|
|
8939
10472
|
let prIdx = this.promptIndexByItemcode(rfd.recording.itemcode);
|
|
8940
10473
|
if (this.items != null && prIdx !== null) {
|
|
8941
|
-
let it = this.items
|
|
10474
|
+
let it = this.items.getItem(prIdx);
|
|
8942
10475
|
if (it && this._session) {
|
|
8943
|
-
if (!it.recs) {
|
|
8944
|
-
|
|
8945
|
-
}
|
|
10476
|
+
// if (!it.recs) {
|
|
10477
|
+
// it.recs = new Array<SprRecordingFile>();
|
|
10478
|
+
// }
|
|
8946
10479
|
let rf = new SprRecordingFile(this._session.sessionId, rfd.recording.itemcode, rfd.version, null);
|
|
8947
|
-
|
|
10480
|
+
rf.serverPersisted = true;
|
|
10481
|
+
this.items.addSprRecFile(it, rf);
|
|
8948
10482
|
}
|
|
8949
10483
|
else {
|
|
8950
10484
|
//console.debug("WARN: No recording item with code: \"" +rfd.recording.itemcode+ "\" found.");
|
|
@@ -8958,6 +10492,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8958
10492
|
addRecordingFileByPromptIndex(promptIndex, rf) {
|
|
8959
10493
|
}
|
|
8960
10494
|
stopped() {
|
|
10495
|
+
var _a;
|
|
8961
10496
|
this.updateStartActionDisableState();
|
|
8962
10497
|
this.transportActions.stopAction.disabled = true;
|
|
8963
10498
|
this.transportActions.nextAction.disabled = true;
|
|
@@ -8966,22 +10501,24 @@ class SessionManager extends BasicRecorder {
|
|
|
8966
10501
|
this.statusMsg = 'Recorded.';
|
|
8967
10502
|
this.startStopSignalState = 0 /* IDLE */;
|
|
8968
10503
|
let ad = null;
|
|
10504
|
+
let ada = null;
|
|
10505
|
+
let adh = null;
|
|
10506
|
+
let frameLen = 0;
|
|
8969
10507
|
if (this.ac != null) {
|
|
8970
|
-
|
|
8971
|
-
|
|
8972
|
-
|
|
8973
|
-
let rf = null;
|
|
8974
|
-
if (this._session && ic) {
|
|
8975
|
-
let sessId = this._session.sessionId;
|
|
8976
|
-
let cpIdx = this.promptIndex;
|
|
8977
|
-
if (this.items) {
|
|
8978
|
-
let it = this.items[cpIdx];
|
|
8979
|
-
if (!it.recs) {
|
|
8980
|
-
it.recs = new Array();
|
|
8981
|
-
}
|
|
8982
|
-
rf = new SprRecordingFile(sessId, ic, it.recs.length, ad);
|
|
8983
|
-
it.recs.push(rf);
|
|
10508
|
+
if (this.uploadChunkSizeSeconds || SessionManager.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
10509
|
+
ada = this.ac.audioBufferArray();
|
|
10510
|
+
frameLen = ada.frameLen;
|
|
8984
10511
|
}
|
|
10512
|
+
else {
|
|
10513
|
+
ad = this.ac.audioBuffer();
|
|
10514
|
+
frameLen = ad.length;
|
|
10515
|
+
}
|
|
10516
|
+
adh = new AudioDataHolder(ad, ada);
|
|
10517
|
+
}
|
|
10518
|
+
// Use an own reference since the writing of the wave file is asynchronous and this._recordingFile might already contain the next recording
|
|
10519
|
+
let rf = this._recordingFile;
|
|
10520
|
+
if (rf && rf instanceof SprRecordingFile) {
|
|
10521
|
+
(_a = this.items) === null || _a === void 0 ? void 0 : _a.setSprRecFileAudioData(rf, adh);
|
|
8985
10522
|
if (this.enableUploadRecordings && !this.uploadChunkSizeSeconds) {
|
|
8986
10523
|
// TODO use SpeechRecorderconfig resp. RecfileService
|
|
8987
10524
|
// convert asynchronously to 16-bit integer PCM
|
|
@@ -8989,7 +10526,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8989
10526
|
// TODO duplicate conversion for manual download
|
|
8990
10527
|
//console.log("Build wav writer...");
|
|
8991
10528
|
this.processingRecording = true;
|
|
8992
|
-
if (ad
|
|
10529
|
+
if (ad) {
|
|
8993
10530
|
let ww = new WavWriter();
|
|
8994
10531
|
//new REST API URL
|
|
8995
10532
|
let apiEndPoint = '';
|
|
@@ -9002,7 +10539,7 @@ class SessionManager extends BasicRecorder {
|
|
|
9002
10539
|
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
9003
10540
|
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.itemCode;
|
|
9004
10541
|
ww.writeAsync(ad, (wavFile) => {
|
|
9005
|
-
this.postRecording(wavFile, recUrl);
|
|
10542
|
+
this.postRecording(wavFile, recUrl, rf);
|
|
9006
10543
|
this.processingRecording = false;
|
|
9007
10544
|
this.updateWakeLock();
|
|
9008
10545
|
});
|
|
@@ -9013,8 +10550,8 @@ class SessionManager extends BasicRecorder {
|
|
|
9013
10550
|
let complete = true;
|
|
9014
10551
|
if (this.items) {
|
|
9015
10552
|
// search backwards, to gain faster detection of incomplete state
|
|
9016
|
-
for (let ri = this.items.length - 1; ri >= 0; ri--) {
|
|
9017
|
-
let it = this.items
|
|
10553
|
+
for (let ri = this.items.length() - 1; ri >= 0; ri--) {
|
|
10554
|
+
let it = this.items.getItem(ri);
|
|
9018
10555
|
if (it.recording && !it.training && (!it.recs || it.recs.length == 0)) {
|
|
9019
10556
|
complete = false;
|
|
9020
10557
|
break;
|
|
@@ -9079,13 +10616,13 @@ class SessionManager extends BasicRecorder {
|
|
|
9079
10616
|
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
9080
10617
|
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.promptItem.itemcode + '/' + this.rfUuid + '/' + chunkIdx;
|
|
9081
10618
|
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
9082
|
-
this.postRecording(wavFile, recUrl);
|
|
10619
|
+
this.postRecording(wavFile, recUrl, null);
|
|
9083
10620
|
this.processingRecording = false;
|
|
9084
10621
|
});
|
|
9085
10622
|
}
|
|
9086
|
-
postRecording(wavFile, recUrl) {
|
|
10623
|
+
postRecording(wavFile, recUrl, rf) {
|
|
9087
10624
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
9088
|
-
let ul = new Upload(wavBlob, recUrl);
|
|
10625
|
+
let ul = new Upload(wavBlob, recUrl, rf);
|
|
9089
10626
|
this.uploader.queueUpload(ul);
|
|
9090
10627
|
}
|
|
9091
10628
|
stop() {
|
|
@@ -9121,7 +10658,7 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9121
10658
|
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
9122
10659
|
<app-sprprompting [projectName]="projectName"
|
|
9123
10660
|
[startStopSignalState]="startStopSignalState" [promptItem]="promptItem" [showPrompt]="showPrompt"
|
|
9124
|
-
[items]="items"
|
|
10661
|
+
[items]="items?.items"
|
|
9125
10662
|
[transportActions]="transportActions"
|
|
9126
10663
|
[selectedItemIdx]="promptIndex" (onItemSelect)="itemSelect($event)" (onNextItem)="nextItem()" (onPrevItem)="prevItem()"
|
|
9127
10664
|
[audioSignalCollapsed]="audioSignalCollapsed" [displayAudioClip]="displayAudioClip"
|
|
@@ -9135,10 +10672,10 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9135
10672
|
|
|
9136
10673
|
|
|
9137
10674
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}" [ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
9138
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="displayAudioClip?.levelInfos"></audio-levelbar>
|
|
10675
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="displayAudioClip?.levelInfos" [stateLoading]="audioFetching"></audio-levelbar>
|
|
9139
10676
|
<div fxLayout="row">
|
|
9140
10677
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
9141
|
-
[audioLoaded]="displayAudioClip?.
|
|
10678
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
9142
10679
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
9143
10680
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
9144
10681
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -9156,7 +10693,7 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9156
10693
|
<div fxFlex="1 1 30%" fxLayoutAlign="start center">
|
|
9157
10694
|
<app-sprstatusdisplay fxHide.xs [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"></app-sprstatusdisplay>
|
|
9158
10695
|
</div>
|
|
9159
|
-
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="items
|
|
10696
|
+
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="!items || items.length()>1"></app-sprtransport>
|
|
9160
10697
|
<div fxFlex="1 1 30%" fxLayoutAlign="end center" fxLayout="row">
|
|
9161
10698
|
<app-uploadstatus class="ricontrols" fxHide.xs fxLayoutAlign="end center" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
9162
10699
|
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
@@ -9164,7 +10701,7 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9164
10701
|
<app-readystateindicator class="ricontrols" fxLayoutAlign="end center" fxHide.xs [ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
9165
10702
|
</div>
|
|
9166
10703
|
</div>
|
|
9167
|
-
`, isInline: true, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;min-height:0px;overflow:hidden}\n", ".ricontrols{padding:4px;box-sizing:border-box;height:100%}\n", ".dark{background:darkgray}\n", ".controlpanel{align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n"], components: [{ type: WarningBar, selector: "app-warningbar", inputs: ["warningText", "show"] }, { type: Prompting, selector: "app-sprprompting", inputs: ["projectName", "startStopSignalState", "promptItem", "showPrompt", "items", "selectedItemIdx", "transportActions", "enableDownload", "audioSignalCollapsed", "displayAudioClip", "playStartAction", "playSelectionAction", "autoPlayOnSelectToggleAction", "playStopAction"], outputs: ["onItemSelect", "onNextItem", "onPrevItem"] }, { type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos"] }, { type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }, { type: UploadStatus, selector: "app-uploadstatus", inputs: ["value", "awaitNewUpload", "status"] }, { type: WakeLockIndicator, selector: "app-wakelockindicator", inputs: ["screenLocked"] }, { type: ReadyStateIndicator, selector: "app-readystateindicator", inputs: ["ready"] }, { type: StatusDisplay, selector: "app-sprstatusdisplay", inputs: ["statusAlertType", "statusMsg", "statusWaiting"] }, { type: TransportPanel, selector: "app-sprtransport", inputs: ["readonly", "actions", "navigationEnabled", "pausingEnabled"] }], directives: [{ type: i3$1.DefaultShowHideDirective, selector: " [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]", inputs: ["fxShow", "fxShow.print", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.print", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }, { type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i3$1.DefaultStyleDirective, selector: " [ngStyle], [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl], [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl], [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i8.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i8.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }] });
|
|
10704
|
+
`, isInline: true, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;min-height:0px;overflow:hidden}\n", ".ricontrols{padding:4px;box-sizing:border-box;height:100%}\n", ".dark{background:darkgray}\n", ".controlpanel{align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n"], components: [{ type: WarningBar, selector: "app-warningbar", inputs: ["warningText", "show"] }, { type: Prompting, selector: "app-sprprompting", inputs: ["projectName", "startStopSignalState", "promptItem", "showPrompt", "items", "selectedItemIdx", "transportActions", "enableDownload", "audioSignalCollapsed", "displayAudioClip", "playStartAction", "playSelectionAction", "autoPlayOnSelectToggleAction", "playStopAction"], outputs: ["onItemSelect", "onNextItem", "onPrevItem"] }, { type: i7.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "value", "bufferValue", "mode"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos", "stateLoading"] }, { type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }, { type: UploadStatus, selector: "app-uploadstatus", inputs: ["value", "awaitNewUpload", "status"] }, { type: WakeLockIndicator, selector: "app-wakelockindicator", inputs: ["screenLocked"] }, { type: ReadyStateIndicator, selector: "app-readystateindicator", inputs: ["ready"] }, { type: StatusDisplay, selector: "app-sprstatusdisplay", inputs: ["statusAlertType", "statusMsg", "statusWaiting"] }, { type: TransportPanel, selector: "app-sprtransport", inputs: ["readonly", "actions", "navigationEnabled", "pausingEnabled"] }], directives: [{ type: i3$1.DefaultShowHideDirective, selector: " [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]", inputs: ["fxShow", "fxShow.print", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.print", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }, { type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i3$1.DefaultStyleDirective, selector: " [ngStyle], [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl], [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl], [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i8.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i8.DefaultLayoutAlignDirective, selector: " [fxLayoutAlign], [fxLayoutAlign.xs], [fxLayoutAlign.sm], [fxLayoutAlign.md], [fxLayoutAlign.lg], [fxLayoutAlign.xl], [fxLayoutAlign.lt-sm], [fxLayoutAlign.lt-md], [fxLayoutAlign.lt-lg], [fxLayoutAlign.lt-xl], [fxLayoutAlign.gt-xs], [fxLayoutAlign.gt-sm], [fxLayoutAlign.gt-md], [fxLayoutAlign.gt-lg]", inputs: ["fxLayoutAlign", "fxLayoutAlign.xs", "fxLayoutAlign.sm", "fxLayoutAlign.md", "fxLayoutAlign.lg", "fxLayoutAlign.xl", "fxLayoutAlign.lt-sm", "fxLayoutAlign.lt-md", "fxLayoutAlign.lt-lg", "fxLayoutAlign.lt-xl", "fxLayoutAlign.gt-xs", "fxLayoutAlign.gt-sm", "fxLayoutAlign.gt-md", "fxLayoutAlign.gt-lg"] }] });
|
|
9168
10705
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SessionManager, decorators: [{
|
|
9169
10706
|
type: Component,
|
|
9170
10707
|
args: [{
|
|
@@ -9175,7 +10712,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
9175
10712
|
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
9176
10713
|
<app-sprprompting [projectName]="projectName"
|
|
9177
10714
|
[startStopSignalState]="startStopSignalState" [promptItem]="promptItem" [showPrompt]="showPrompt"
|
|
9178
|
-
[items]="items"
|
|
10715
|
+
[items]="items?.items"
|
|
9179
10716
|
[transportActions]="transportActions"
|
|
9180
10717
|
[selectedItemIdx]="promptIndex" (onItemSelect)="itemSelect($event)" (onNextItem)="nextItem()" (onPrevItem)="prevItem()"
|
|
9181
10718
|
[audioSignalCollapsed]="audioSignalCollapsed" [displayAudioClip]="displayAudioClip"
|
|
@@ -9189,10 +10726,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
9189
10726
|
|
|
9190
10727
|
|
|
9191
10728
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}" [ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
9192
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="displayAudioClip?.levelInfos"></audio-levelbar>
|
|
10729
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="displayAudioClip?.levelInfos" [stateLoading]="audioFetching"></audio-levelbar>
|
|
9193
10730
|
<div fxLayout="row">
|
|
9194
10731
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
9195
|
-
[audioLoaded]="displayAudioClip?.
|
|
10732
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
9196
10733
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
9197
10734
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
9198
10735
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -9210,7 +10747,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
9210
10747
|
<div fxFlex="1 1 30%" fxLayoutAlign="start center">
|
|
9211
10748
|
<app-sprstatusdisplay fxHide.xs [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"></app-sprstatusdisplay>
|
|
9212
10749
|
</div>
|
|
9213
|
-
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="items
|
|
10750
|
+
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="!items || items.length()>1"></app-sprtransport>
|
|
9214
10751
|
<div fxFlex="1 1 30%" fxLayoutAlign="end center" fxLayout="row">
|
|
9215
10752
|
<app-uploadstatus class="ricontrols" fxHide.xs fxLayoutAlign="end center" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
9216
10753
|
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
@@ -9503,7 +11040,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
9503
11040
|
this.uploadUpdate(ue);
|
|
9504
11041
|
};
|
|
9505
11042
|
window.addEventListener('beforeunload', (e) => {
|
|
9506
|
-
console.debug("Before page unload event");
|
|
11043
|
+
//console.debug("Before page unload event");
|
|
9507
11044
|
if (this.ready()) {
|
|
9508
11045
|
return;
|
|
9509
11046
|
}
|
|
@@ -9822,14 +11359,15 @@ class AudioDisplayPlayer {
|
|
|
9822
11359
|
if (this.aCtx) {
|
|
9823
11360
|
this.aCtx.decodeAudioData(data, (audioBuffer) => {
|
|
9824
11361
|
//console.debug("Audio Buffer Samplerate: ", audioBuffer.sampleRate)
|
|
9825
|
-
|
|
11362
|
+
let adh = new AudioDataHolder(audioBuffer, null);
|
|
11363
|
+
this.audioClip = new AudioClip(adh);
|
|
9826
11364
|
});
|
|
9827
11365
|
}
|
|
9828
11366
|
}
|
|
9829
|
-
set audioData(
|
|
9830
|
-
this.audioDisplayScrollPane.audioData =
|
|
9831
|
-
if (
|
|
9832
|
-
let clip = new AudioClip(
|
|
11367
|
+
set audioData(audioData) {
|
|
11368
|
+
this.audioDisplayScrollPane.audioData = audioData;
|
|
11369
|
+
if (audioData) {
|
|
11370
|
+
let clip = new AudioClip(audioData);
|
|
9833
11371
|
if (this.ap) {
|
|
9834
11372
|
this.ap.audioClip = clip;
|
|
9835
11373
|
this.playStartAction.disabled = false;
|
|
@@ -9851,7 +11389,7 @@ class AudioDisplayPlayer {
|
|
|
9851
11389
|
let audioData = null;
|
|
9852
11390
|
let sel = null;
|
|
9853
11391
|
if (audioClip) {
|
|
9854
|
-
audioData = audioClip.
|
|
11392
|
+
audioData = audioClip.audioDataHolder;
|
|
9855
11393
|
sel = audioClip.selection;
|
|
9856
11394
|
if (this._audioClip) {
|
|
9857
11395
|
this._audioClip.addSelectionObserver((ac) => {
|
|
@@ -10122,7 +11660,7 @@ class RecordingFileService {
|
|
|
10122
11660
|
// Do not use Promise version, which does not work with Safari 13
|
|
10123
11661
|
if (resp.body) {
|
|
10124
11662
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
10125
|
-
recordingFile
|
|
11663
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(ab));
|
|
10126
11664
|
if (this.debugDelay > 0) {
|
|
10127
11665
|
window.setTimeout(() => {
|
|
10128
11666
|
observer.next(recordingFile);
|
|
@@ -10172,7 +11710,7 @@ class RecordingFileService {
|
|
|
10172
11710
|
if (resp.body) {
|
|
10173
11711
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
10174
11712
|
if (rf) {
|
|
10175
|
-
rf
|
|
11713
|
+
RecordingFileUtils.setAudioData(rf, new AudioDataHolder(ab));
|
|
10176
11714
|
}
|
|
10177
11715
|
else {
|
|
10178
11716
|
observer.error('Recording file object null');
|
|
@@ -10223,7 +11761,8 @@ class RecordingFileService {
|
|
|
10223
11761
|
if (resp.body) {
|
|
10224
11762
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
10225
11763
|
if (rf) {
|
|
10226
|
-
|
|
11764
|
+
let adh = new AudioDataHolder(ab);
|
|
11765
|
+
RecordingFileUtils.setAudioData(rf, adh);
|
|
10227
11766
|
}
|
|
10228
11767
|
else {
|
|
10229
11768
|
observer.error('Recording file object null');
|
|
@@ -10266,7 +11805,7 @@ class RecordingFileService {
|
|
|
10266
11805
|
// append UUID to make request URL unique to avoid localhost server caching
|
|
10267
11806
|
recUrl = recUrl + '.json?requestUUID=' + UUID.generate();
|
|
10268
11807
|
}
|
|
10269
|
-
console.log("Path request URL: "
|
|
11808
|
+
//console.log("Path request URL: "+recUrl)
|
|
10270
11809
|
return this.http.patch(recUrl, { editSampleRate: editSampleRate, editStartFrame: editStartFrame, editEndFrame: editEndFrame }, { withCredentials: this.withCredentials });
|
|
10271
11810
|
}
|
|
10272
11811
|
}
|
|
@@ -10286,6 +11825,7 @@ class RecordingFileMetaComponent {
|
|
|
10286
11825
|
constructor() {
|
|
10287
11826
|
this.sessionId = null;
|
|
10288
11827
|
this._recordingFile = null;
|
|
11828
|
+
this.stateLoading = false;
|
|
10289
11829
|
this.itemCode = null;
|
|
10290
11830
|
this.uuid = null;
|
|
10291
11831
|
}
|
|
@@ -10302,12 +11842,12 @@ class RecordingFileMetaComponent {
|
|
|
10302
11842
|
}
|
|
10303
11843
|
if (this.itemCode) {
|
|
10304
11844
|
this.uuid = null;
|
|
10305
|
-
console.debug("SprRecordingFile: "
|
|
11845
|
+
//console.debug("SprRecordingFile: "+this.itemCode+ " UUID: "+this.uuid)
|
|
10306
11846
|
}
|
|
10307
11847
|
else {
|
|
10308
11848
|
this.itemCode = null;
|
|
10309
11849
|
this.uuid = (_b = this._recordingFile) === null || _b === void 0 ? void 0 : _b.uuid;
|
|
10310
|
-
console.debug("RecordingFile: "
|
|
11850
|
+
//console.debug("RecordingFile: "+this.itemCode+ " UUID: "+this.uuid)
|
|
10311
11851
|
}
|
|
10312
11852
|
}
|
|
10313
11853
|
else {
|
|
@@ -10324,10 +11864,11 @@ class RecordingFileMetaComponent {
|
|
|
10324
11864
|
}
|
|
10325
11865
|
}
|
|
10326
11866
|
RecordingFileMetaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileMetaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10327
|
-
RecordingFileMetaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: RecordingFileMetaComponent, selector: "app-recording-file-meta", inputs: { sessionId: "sessionId", recordingFile: "recordingFile" }, ngImport: i0, template: `
|
|
11867
|
+
RecordingFileMetaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.3.11", type: RecordingFileMetaComponent, selector: "app-recording-file-meta", inputs: { sessionId: "sessionId", stateLoading: "stateLoading", recordingFile: "recordingFile" }, ngImport: i0, template: `
|
|
10328
11868
|
<mat-card>
|
|
10329
11869
|
<mat-card-title>Recording file ID: {{recordingFile?.recordingFileId}}</mat-card-title>
|
|
10330
11870
|
<mat-card-content>
|
|
11871
|
+
<mat-progress-spinner *ngIf="stateLoading" mode="indeterminate" [diameter]="20"></mat-progress-spinner>
|
|
10331
11872
|
<table>
|
|
10332
11873
|
<tr *ngIf="itemCode">
|
|
10333
11874
|
<td>Itemcode:</td>
|
|
@@ -10357,7 +11898,7 @@ RecordingFileMetaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0
|
|
|
10357
11898
|
</table>
|
|
10358
11899
|
</mat-card-content>
|
|
10359
11900
|
</mat-card>
|
|
10360
|
-
`, isInline: true, components: [{ type: i1$4.MatCard, selector: "mat-card", exportAs: ["matCard"] }], directives: [{ type: i1$4.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { type: i1$4.MatCardContent, selector: "mat-card-content, [mat-card-content], [matCardContent]" }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
11901
|
+
`, isInline: true, components: [{ type: i1$4.MatCard, selector: "mat-card", exportAs: ["matCard"] }, { type: i1$3.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }], directives: [{ type: i1$4.MatCardTitle, selector: "mat-card-title, [mat-card-title], [matCardTitle]" }, { type: i1$4.MatCardContent, selector: "mat-card-content, [mat-card-content], [matCardContent]" }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] });
|
|
10361
11902
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileMetaComponent, decorators: [{
|
|
10362
11903
|
type: Component,
|
|
10363
11904
|
args: [{
|
|
@@ -10366,6 +11907,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
10366
11907
|
<mat-card>
|
|
10367
11908
|
<mat-card-title>Recording file ID: {{recordingFile?.recordingFileId}}</mat-card-title>
|
|
10368
11909
|
<mat-card-content>
|
|
11910
|
+
<mat-progress-spinner *ngIf="stateLoading" mode="indeterminate" [diameter]="20"></mat-progress-spinner>
|
|
10369
11911
|
<table>
|
|
10370
11912
|
<tr *ngIf="itemCode">
|
|
10371
11913
|
<td>Itemcode:</td>
|
|
@@ -10400,6 +11942,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
10400
11942
|
}]
|
|
10401
11943
|
}], propDecorators: { sessionId: [{
|
|
10402
11944
|
type: Input
|
|
11945
|
+
}], stateLoading: [{
|
|
11946
|
+
type: Input
|
|
10403
11947
|
}], recordingFile: [{
|
|
10404
11948
|
type: Input
|
|
10405
11949
|
}] } });
|
|
@@ -10542,6 +12086,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10542
12086
|
this.recordingFileVersion = null;
|
|
10543
12087
|
this.routedByQueryParam = false;
|
|
10544
12088
|
this.posInList = null;
|
|
12089
|
+
this.audioFetching = false;
|
|
10545
12090
|
this.naviInfoLoading = false;
|
|
10546
12091
|
this.parentE = this.eRef.nativeElement;
|
|
10547
12092
|
this.firstAction = new Action('First');
|
|
@@ -10713,18 +12258,20 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10713
12258
|
this.updateActions();
|
|
10714
12259
|
let audioContext = AudioContextProvider.audioContextInstance();
|
|
10715
12260
|
if (audioContext) {
|
|
12261
|
+
this.audioFetching = true;
|
|
10716
12262
|
this.recordingFileService.fetchSprRecordingFile(audioContext, rfId).subscribe(value => {
|
|
12263
|
+
this.audioFetching = false;
|
|
10717
12264
|
this.status = 'Audio file loaded.';
|
|
10718
12265
|
let clip = null;
|
|
10719
12266
|
this.recordingFile = value;
|
|
10720
12267
|
if (this.recordingFile) {
|
|
10721
|
-
let ab = this.recordingFile.
|
|
12268
|
+
let ab = this.recordingFile.audioDataHolder;
|
|
10722
12269
|
if (ab) {
|
|
10723
12270
|
clip = new AudioClip(ab);
|
|
10724
12271
|
let esffsr = null;
|
|
10725
12272
|
let eeffsr = null;
|
|
10726
12273
|
let esr = null;
|
|
10727
|
-
if (clip.
|
|
12274
|
+
if (clip.audioDataHolder != null) {
|
|
10728
12275
|
esr = ab.sampleRate;
|
|
10729
12276
|
if (esr != null) {
|
|
10730
12277
|
esffsr = RecordingFileUtil.editStartFrameForSampleRate(this.recordingFile, esr);
|
|
@@ -10736,8 +12283,8 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10736
12283
|
sel = new Selection(ab.sampleRate, esffsr, eeffsr);
|
|
10737
12284
|
}
|
|
10738
12285
|
else {
|
|
10739
|
-
let ch0 = ab.getChannelData(0);
|
|
10740
|
-
let frameLength =
|
|
12286
|
+
//let ch0 = ab.getChannelData(0);
|
|
12287
|
+
let frameLength = ab.frameLen;
|
|
10741
12288
|
sel = new Selection(esr, esffsr, frameLength);
|
|
10742
12289
|
}
|
|
10743
12290
|
}
|
|
@@ -10751,6 +12298,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10751
12298
|
this.audioClip = clip;
|
|
10752
12299
|
this.loadedRecfile();
|
|
10753
12300
|
}, error1 => {
|
|
12301
|
+
this.audioFetching = false;
|
|
10754
12302
|
this.status = 'Error loading audio file!';
|
|
10755
12303
|
});
|
|
10756
12304
|
}
|
|
@@ -10860,7 +12408,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10860
12408
|
for (let avRfV of avRf) {
|
|
10861
12409
|
os += avRfV.version + '/';
|
|
10862
12410
|
}
|
|
10863
|
-
console.debug(os);
|
|
12411
|
+
//console.debug(os);
|
|
10864
12412
|
}
|
|
10865
12413
|
}
|
|
10866
12414
|
this.updatePos();
|
|
@@ -10876,7 +12424,7 @@ RecordingFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0
|
|
|
10876
12424
|
|
|
10877
12425
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
10878
12426
|
<div class="ctrlview">
|
|
10879
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12427
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
10880
12428
|
|
|
10881
12429
|
<audio-display-control [audioClip]="audioClip"
|
|
10882
12430
|
[playStartAction]="playStartAction"
|
|
@@ -10889,7 +12437,7 @@ RecordingFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0
|
|
|
10889
12437
|
[zoomFitToPanelAction]="zoomFitToPanelAction"></audio-display-control>
|
|
10890
12438
|
<app-recording-file-navi [items]="availRecFiles?.length" [itemPos]="posInList" [version]="recordingFileVersion" [versions]="versions" [firstAction]="firstAction" [prevAction]="prevAction" [nextAction]="nextAction" [lastAction]="lastAction" [selectVersion]="toVersionAction" [naviInfoLoading]="naviInfoLoading"></app-recording-file-navi>
|
|
10891
12439
|
</div>
|
|
10892
|
-
`, isInline: true, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0;overflow:hidden;padding:20px;z-index:5;box-sizing:border-box;background-color:#fff}\n", ".ctrlview{display:flex;flex-direction:row}\n", "audio-display-control{flex:3}\n"], components: [{ type: AudioDisplayScrollPane, selector: "audio-display-scroll-pane", inputs: ["audioClip"], outputs: ["zoomInAction", "zoomOutAction", "zoomSelectedAction", "zoomFitToPanelAction"] }, { type: RecordingFileMetaComponent, selector: "app-recording-file-meta", inputs: ["sessionId", "recordingFile"] }, { type: AudioDisplayControl, selector: "audio-display-control", inputs: ["audioClip", "playStartAction", "playSelectionAction", "playStopAction", "zoomInAction", "zoomOutAction", "zoomFitToPanelAction", "zoomSelectedAction", "autoPlayOnSelectToggleAction"] }, { type: RecordingFileNaviComponent, selector: "app-recording-file-navi", inputs: ["firstAction", "prevAction", "nextAction", "lastAction", "items", "itemPos", "selectVersion", "versions", "version", "naviInfoLoading"] }] });
|
|
12440
|
+
`, isInline: true, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0;overflow:hidden;padding:20px;z-index:5;box-sizing:border-box;background-color:#fff}\n", ".ctrlview{display:flex;flex-direction:row}\n", "audio-display-control{flex:3}\n"], components: [{ type: AudioDisplayScrollPane, selector: "audio-display-scroll-pane", inputs: ["audioClip"], outputs: ["zoomInAction", "zoomOutAction", "zoomSelectedAction", "zoomFitToPanelAction"] }, { type: RecordingFileMetaComponent, selector: "app-recording-file-meta", inputs: ["sessionId", "stateLoading", "recordingFile"] }, { type: AudioDisplayControl, selector: "audio-display-control", inputs: ["audioClip", "playStartAction", "playSelectionAction", "playStopAction", "zoomInAction", "zoomOutAction", "zoomFitToPanelAction", "zoomSelectedAction", "autoPlayOnSelectToggleAction"] }, { type: RecordingFileNaviComponent, selector: "app-recording-file-navi", inputs: ["firstAction", "prevAction", "nextAction", "lastAction", "items", "itemPos", "selectVersion", "versions", "version", "naviInfoLoading"] }] });
|
|
10893
12441
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileViewComponent, decorators: [{
|
|
10894
12442
|
type: Component,
|
|
10895
12443
|
args: [{
|
|
@@ -10898,7 +12446,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
10898
12446
|
|
|
10899
12447
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
10900
12448
|
<div class="ctrlview">
|
|
10901
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12449
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
10902
12450
|
|
|
10903
12451
|
<audio-display-control [audioClip]="audioClip"
|
|
10904
12452
|
[playStartAction]="playStartAction"
|
|
@@ -10992,7 +12540,7 @@ class RecordingFileUI extends RecordingFileViewComponent {
|
|
|
10992
12540
|
applySelection() {
|
|
10993
12541
|
var _a;
|
|
10994
12542
|
if (this.audioClip) {
|
|
10995
|
-
let ab = this.audioClip.
|
|
12543
|
+
let ab = this.audioClip.audioDataHolder;
|
|
10996
12544
|
let s = this.audioClip.selection;
|
|
10997
12545
|
if (ab && ((_a = this.recordingFile) === null || _a === void 0 ? void 0 : _a.recordingFileId)) {
|
|
10998
12546
|
let sr = null;
|
|
@@ -11030,7 +12578,7 @@ RecordingFileUI.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
|
|
|
11030
12578
|
|
|
11031
12579
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
11032
12580
|
<div class="ctrlview">
|
|
11033
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12581
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
11034
12582
|
<audio-display-control [audioClip]="audioClip"
|
|
11035
12583
|
[playStartAction]="playStartAction"
|
|
11036
12584
|
[playSelectionAction]="playSelectionAction"
|
|
@@ -11044,7 +12592,7 @@ RecordingFileUI.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
|
|
|
11044
12592
|
</div>
|
|
11045
12593
|
|
|
11046
12594
|
<button mat-raised-button color="accent" (click)="applySelection()" [disabled]="editSaved">{{this.applyButtonText()}}</button>
|
|
11047
|
-
`, isInline: true, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0;overflow:hidden;padding:20px;z-index:5;box-sizing:border-box;background-color:#fff}\n", ".ctrlview{display:flex;flex-direction:row}\n", "audio-display-control{flex:3}\n"], components: [{ type: AudioDisplayScrollPane, selector: "audio-display-scroll-pane", inputs: ["audioClip"], outputs: ["zoomInAction", "zoomOutAction", "zoomSelectedAction", "zoomFitToPanelAction"] }, { type: RecordingFileMetaComponent, selector: "app-recording-file-meta", inputs: ["sessionId", "recordingFile"] }, { type: AudioDisplayControl, selector: "audio-display-control", inputs: ["audioClip", "playStartAction", "playSelectionAction", "playStopAction", "zoomInAction", "zoomOutAction", "zoomFitToPanelAction", "zoomSelectedAction", "autoPlayOnSelectToggleAction"] }, { type: RecordingFileNaviComponent, selector: "app-recording-file-navi", inputs: ["firstAction", "prevAction", "nextAction", "lastAction", "items", "itemPos", "selectVersion", "versions", "version", "naviInfoLoading"] }, { type: i3$2.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }] });
|
|
12595
|
+
`, isInline: true, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0;overflow:hidden;padding:20px;z-index:5;box-sizing:border-box;background-color:#fff}\n", ".ctrlview{display:flex;flex-direction:row}\n", "audio-display-control{flex:3}\n"], components: [{ type: AudioDisplayScrollPane, selector: "audio-display-scroll-pane", inputs: ["audioClip"], outputs: ["zoomInAction", "zoomOutAction", "zoomSelectedAction", "zoomFitToPanelAction"] }, { type: RecordingFileMetaComponent, selector: "app-recording-file-meta", inputs: ["sessionId", "stateLoading", "recordingFile"] }, { type: AudioDisplayControl, selector: "audio-display-control", inputs: ["audioClip", "playStartAction", "playSelectionAction", "playStopAction", "zoomInAction", "zoomOutAction", "zoomFitToPanelAction", "zoomSelectedAction", "autoPlayOnSelectToggleAction"] }, { type: RecordingFileNaviComponent, selector: "app-recording-file-navi", inputs: ["firstAction", "prevAction", "nextAction", "lastAction", "items", "itemPos", "selectVersion", "versions", "version", "naviInfoLoading"] }, { type: i3$2.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }] });
|
|
11048
12596
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileUI, decorators: [{
|
|
11049
12597
|
type: Component,
|
|
11050
12598
|
args: [{
|
|
@@ -11055,7 +12603,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
11055
12603
|
|
|
11056
12604
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
11057
12605
|
<div class="ctrlview">
|
|
11058
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12606
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
11059
12607
|
<audio-display-control [audioClip]="audioClip"
|
|
11060
12608
|
[playStartAction]="playStartAction"
|
|
11061
12609
|
[playSelectionAction]="playSelectionAction"
|
|
@@ -11112,7 +12660,8 @@ class MediaUtils {
|
|
|
11112
12660
|
|
|
11113
12661
|
class RecordingList {
|
|
11114
12662
|
constructor() {
|
|
11115
|
-
|
|
12663
|
+
//private recordingList:Array<RecordingFile>=new Array<RecordingFile>();
|
|
12664
|
+
this.recordingList = new RecFilesCache();
|
|
11116
12665
|
//cols=['index','length','samples','samplerate','action'];
|
|
11117
12666
|
this.cols = ['index', 'startedDate', 'length', 'action'];
|
|
11118
12667
|
this.selectDisabled = false;
|
|
@@ -11124,7 +12673,7 @@ class RecordingList {
|
|
|
11124
12673
|
this.buildDataSource();
|
|
11125
12674
|
}
|
|
11126
12675
|
buildDataSource() {
|
|
11127
|
-
this.recordingList.sort((a, b) => {
|
|
12676
|
+
this.recordingList.recFiles.sort((a, b) => {
|
|
11128
12677
|
let cmp = 0;
|
|
11129
12678
|
let aD = null;
|
|
11130
12679
|
let bD = null;
|
|
@@ -11145,25 +12694,36 @@ class RecordingList {
|
|
|
11145
12694
|
}
|
|
11146
12695
|
return cmp;
|
|
11147
12696
|
});
|
|
11148
|
-
this.recordingListDataSource.data = this.recordingList;
|
|
12697
|
+
this.recordingListDataSource.data = this.recordingList.recFiles;
|
|
11149
12698
|
}
|
|
11150
|
-
|
|
11151
|
-
this.recordingList.
|
|
12699
|
+
addRecFile(rf) {
|
|
12700
|
+
this.recordingList.addRecFile(rf);
|
|
11152
12701
|
this.buildDataSource();
|
|
11153
12702
|
}
|
|
12703
|
+
setRecFileAudioData(recFile, adh) {
|
|
12704
|
+
this.recordingList.setRecFileAudioData(recFile, adh);
|
|
12705
|
+
}
|
|
11154
12706
|
selectRecordingFile(rf) {
|
|
12707
|
+
this.recordingList.currentRecordingFile = rf;
|
|
11155
12708
|
this.selectedRecordingFileChanged.emit(rf);
|
|
11156
12709
|
}
|
|
11157
12710
|
selectTop() {
|
|
11158
|
-
if (this.recordingList.length > 0) {
|
|
11159
|
-
this.selectRecordingFile(this.recordingList[0]);
|
|
12711
|
+
if (this.recordingList.recFiles.length > 0) {
|
|
12712
|
+
this.selectRecordingFile(this.recordingList.recFiles[0]);
|
|
11160
12713
|
}
|
|
11161
12714
|
}
|
|
11162
12715
|
lengthTimeFormatted(rf) {
|
|
11163
12716
|
var _a;
|
|
11164
12717
|
let str = '--:--:--';
|
|
11165
|
-
|
|
11166
|
-
|
|
12718
|
+
let tl = null;
|
|
12719
|
+
if (rf.timeLength) {
|
|
12720
|
+
tl = rf.timeLength;
|
|
12721
|
+
}
|
|
12722
|
+
else if (rf.frames && rf.audioDataHolder) {
|
|
12723
|
+
tl = rf.frames / ((_a = rf.audioDataHolder) === null || _a === void 0 ? void 0 : _a.sampleRate);
|
|
12724
|
+
}
|
|
12725
|
+
if (tl) {
|
|
12726
|
+
str = MediaUtils.toMediaTime(tl);
|
|
11167
12727
|
}
|
|
11168
12728
|
return str;
|
|
11169
12729
|
}
|
|
@@ -11249,8 +12809,11 @@ class RecorderCombiPane {
|
|
|
11249
12809
|
}
|
|
11250
12810
|
ngAfterViewInit() {
|
|
11251
12811
|
}
|
|
11252
|
-
|
|
11253
|
-
this.recordingListComp.
|
|
12812
|
+
addRecFile(rf) {
|
|
12813
|
+
this.recordingListComp.addRecFile(rf);
|
|
12814
|
+
}
|
|
12815
|
+
setRecFileAudioData(recFile, adh) {
|
|
12816
|
+
this.recordingListComp.setRecFileAudioData(recFile, adh);
|
|
11254
12817
|
}
|
|
11255
12818
|
selectRecordingFile(rf) {
|
|
11256
12819
|
this.selectedRecordingFileChanged.emit(rf);
|
|
@@ -11323,15 +12886,11 @@ class Item {
|
|
|
11323
12886
|
}
|
|
11324
12887
|
class AudioRecorder extends BasicRecorder {
|
|
11325
12888
|
constructor(changeDetectorRef, renderer, route, dialog, sessionService, recFileService, uploader, config) {
|
|
11326
|
-
super(dialog, sessionService, uploader, config);
|
|
11327
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
12889
|
+
super(changeDetectorRef, dialog, sessionService, uploader, config);
|
|
11328
12890
|
this.renderer = renderer;
|
|
11329
12891
|
this.route = route;
|
|
11330
|
-
this.dialog = dialog;
|
|
11331
|
-
this.sessionService = sessionService;
|
|
11332
12892
|
this.recFileService = recFileService;
|
|
11333
12893
|
this.uploader = uploader;
|
|
11334
|
-
this.config = config;
|
|
11335
12894
|
this._project = null;
|
|
11336
12895
|
this.projectName = null;
|
|
11337
12896
|
this.enableUploadRecordings = true;
|
|
@@ -11514,13 +13073,15 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11514
13073
|
if (rfs) {
|
|
11515
13074
|
if (rfs instanceof Array) {
|
|
11516
13075
|
rfs.forEach((rf) => {
|
|
13076
|
+
// the list comes from the server, asssuem all recording files as server persisted
|
|
13077
|
+
rf.serverPersisted = true;
|
|
11517
13078
|
if (rf.startedDate) {
|
|
11518
13079
|
rf._startedAsDateObj = new Date(rf.startedDate);
|
|
11519
13080
|
}
|
|
11520
13081
|
if (rf.date) {
|
|
11521
13082
|
rf._dateAsDateObj = new Date(rf.date);
|
|
11522
13083
|
}
|
|
11523
|
-
this.recorderCombiPane.
|
|
13084
|
+
this.recorderCombiPane.addRecFile(rf);
|
|
11524
13085
|
});
|
|
11525
13086
|
}
|
|
11526
13087
|
else {
|
|
@@ -11574,6 +13135,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11574
13135
|
return this._project;
|
|
11575
13136
|
}
|
|
11576
13137
|
selectRecordingFile(rf) {
|
|
13138
|
+
this.audioFetching = false;
|
|
11577
13139
|
this.displayRecFile = rf;
|
|
11578
13140
|
}
|
|
11579
13141
|
uploadUpdate(ue) {
|
|
@@ -11595,9 +13157,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11595
13157
|
this.changeDetectorRef.detectChanges();
|
|
11596
13158
|
}
|
|
11597
13159
|
set controlAudioPlayer(controlAudioPlayer) {
|
|
11598
|
-
if (this._controlAudioPlayer) {
|
|
11599
|
-
//this._controlAudioPlayer.listener=null;
|
|
11600
|
-
}
|
|
11601
13160
|
this._controlAudioPlayer = controlAudioPlayer;
|
|
11602
13161
|
if (this._controlAudioPlayer) {
|
|
11603
13162
|
this._controlAudioPlayer.listener = this;
|
|
@@ -11677,6 +13236,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11677
13236
|
this.displayAudioClip = null;
|
|
11678
13237
|
this.showRecording();
|
|
11679
13238
|
if (this.ac) {
|
|
13239
|
+
this.audioFetching = false;
|
|
11680
13240
|
if (!this.ac.opened) {
|
|
11681
13241
|
if (this._selectedDeviceId) {
|
|
11682
13242
|
console.log("Open session with audio device Id: \'" + this._selectedDeviceId + "\' for " + this._channelCount + " channels");
|
|
@@ -11693,10 +13253,10 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11693
13253
|
}
|
|
11694
13254
|
downloadRecording() {
|
|
11695
13255
|
if (this.displayRecFile) {
|
|
11696
|
-
let ab = this.displayRecFile.
|
|
13256
|
+
let ab = this.displayRecFile.audioDataHolder;
|
|
11697
13257
|
let ww = new WavWriter();
|
|
11698
|
-
if (ab) {
|
|
11699
|
-
let wavFile = ww.writeAsync(ab, (wavFile) => {
|
|
13258
|
+
if (ab === null || ab === void 0 ? void 0 : ab.buffer) {
|
|
13259
|
+
let wavFile = ww.writeAsync(ab.buffer, (wavFile) => {
|
|
11700
13260
|
let blob = new Blob([wavFile], { type: 'audio/wav' });
|
|
11701
13261
|
let rfUrl = URL.createObjectURL(blob);
|
|
11702
13262
|
let dataDnlLnk = this.renderer.createElement('a');
|
|
@@ -11719,35 +13279,50 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11719
13279
|
set displayRecFile(displayRecFile) {
|
|
11720
13280
|
this._displayRecFile = displayRecFile;
|
|
11721
13281
|
if (this._displayRecFile) {
|
|
11722
|
-
let
|
|
11723
|
-
if (
|
|
11724
|
-
this.displayAudioClip = new AudioClip(
|
|
13282
|
+
let adh = this._displayRecFile.audioDataHolder;
|
|
13283
|
+
if (adh) {
|
|
13284
|
+
this.displayAudioClip = new AudioClip(adh);
|
|
13285
|
+
console.debug(" set recording file: display audio clip set");
|
|
11725
13286
|
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
11726
13287
|
}
|
|
11727
13288
|
else {
|
|
11728
13289
|
// clear for now ...
|
|
11729
13290
|
this.displayAudioClip = null;
|
|
13291
|
+
console.debug("set recording file: display audio clip null");
|
|
11730
13292
|
this.controlAudioPlayer.audioClip = null;
|
|
11731
13293
|
if (this._controlAudioPlayer && this._session) {
|
|
11732
13294
|
//... and try to fetch from server
|
|
11733
|
-
this.
|
|
11734
|
-
|
|
11735
|
-
|
|
11736
|
-
|
|
11737
|
-
|
|
11738
|
-
|
|
11739
|
-
|
|
13295
|
+
this.audioFetching = true;
|
|
13296
|
+
let rf = this._displayRecFile;
|
|
13297
|
+
let clip = this.displayAudioClip;
|
|
13298
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileAudioBuffer(this._controlAudioPlayer.context, this._session.project, rf).subscribe({
|
|
13299
|
+
next: ab => {
|
|
13300
|
+
this.audioFetching = false;
|
|
13301
|
+
let fabDh = null;
|
|
13302
|
+
if (ab) {
|
|
13303
|
+
if (rf) {
|
|
13304
|
+
fabDh = new AudioDataHolder(ab);
|
|
13305
|
+
this.recorderCombiPane.setRecFileAudioData(rf, fabDh);
|
|
13306
|
+
}
|
|
13307
|
+
}
|
|
13308
|
+
else {
|
|
13309
|
+
console.error('Recording file could not be loaded.');
|
|
13310
|
+
this.statusMsg = 'Recording file could not be loaded.';
|
|
13311
|
+
this.statusAlertType = 'error';
|
|
13312
|
+
}
|
|
13313
|
+
if (fabDh) {
|
|
13314
|
+
// this.displayAudioClip could have been changed meanwhile, but the recorder unsubcribes before changing the item. Therefore there should be no risk to set to wrong item
|
|
13315
|
+
this.displayAudioClip = new AudioClip(fabDh);
|
|
13316
|
+
//console.debug("set recording file: display audio clip from fetched audio buffer");
|
|
13317
|
+
}
|
|
13318
|
+
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
13319
|
+
this.showRecording();
|
|
13320
|
+
}, error: err => {
|
|
13321
|
+
console.error("Could not load recording file from server: " + err);
|
|
13322
|
+
this.audioFetching = false;
|
|
13323
|
+
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
11740
13324
|
this.statusAlertType = 'error';
|
|
11741
13325
|
}
|
|
11742
|
-
if (fab) {
|
|
11743
|
-
this.displayAudioClip = new AudioClip(fab);
|
|
11744
|
-
}
|
|
11745
|
-
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
11746
|
-
this.showRecording();
|
|
11747
|
-
}, err => {
|
|
11748
|
-
console.error("Could not load recording file from server: " + err);
|
|
11749
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
11750
|
-
this.statusAlertType = 'error';
|
|
11751
13326
|
});
|
|
11752
13327
|
}
|
|
11753
13328
|
else {
|
|
@@ -11757,6 +13332,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11757
13332
|
}
|
|
11758
13333
|
}
|
|
11759
13334
|
else {
|
|
13335
|
+
console.debug("recording file null");
|
|
11760
13336
|
this.displayAudioClip = null;
|
|
11761
13337
|
this.controlAudioPlayer.audioClip = null;
|
|
11762
13338
|
}
|
|
@@ -11765,25 +13341,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11765
13341
|
get displayRecFile() {
|
|
11766
13342
|
return this._displayRecFile;
|
|
11767
13343
|
}
|
|
11768
|
-
showRecording() {
|
|
11769
|
-
this.controlAudioPlayer.stop();
|
|
11770
|
-
if (this.displayAudioClip) {
|
|
11771
|
-
let dap = this.displayAudioClip;
|
|
11772
|
-
this.levelMeasure.calcBufferLevelInfos(dap.buffer, LEVEL_BAR_INTERVALL_SECONDS).then((levelInfos) => {
|
|
11773
|
-
dap.levelInfos = levelInfos;
|
|
11774
|
-
this.changeDetectorRef.detectChanges();
|
|
11775
|
-
});
|
|
11776
|
-
this.playStartAction.disabled = false;
|
|
11777
|
-
}
|
|
11778
|
-
else {
|
|
11779
|
-
this.playStartAction.disabled = true;
|
|
11780
|
-
// Collapse audio signal display if open
|
|
11781
|
-
if (!this.audioSignalCollapsed) {
|
|
11782
|
-
this.audioSignalCollapsed = true;
|
|
11783
|
-
}
|
|
11784
|
-
}
|
|
11785
|
-
this.changeDetectorRef.detectChanges();
|
|
11786
|
-
}
|
|
11787
13344
|
updateStartActionDisableState() {
|
|
11788
13345
|
this.transportActions.startAction.disabled = !(this.ac);
|
|
11789
13346
|
}
|
|
@@ -11827,6 +13384,19 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11827
13384
|
super.started();
|
|
11828
13385
|
this.statusAlertType = 'info';
|
|
11829
13386
|
this.statusMsg = 'Recording...';
|
|
13387
|
+
if (!this.rfUuid) {
|
|
13388
|
+
this.rfUuid = UUID.generate();
|
|
13389
|
+
}
|
|
13390
|
+
let sessId = 0;
|
|
13391
|
+
if (this._session) {
|
|
13392
|
+
sessId = this._session.sessionId;
|
|
13393
|
+
}
|
|
13394
|
+
let rf = new RecordingFile(this.rfUuid, sessId, null);
|
|
13395
|
+
rf._startedAsDateObj = this.startedDate;
|
|
13396
|
+
if (rf._startedAsDateObj) {
|
|
13397
|
+
rf.startedDate = rf._startedAsDateObj.toString();
|
|
13398
|
+
}
|
|
13399
|
+
this._recordingFile = rf;
|
|
11830
13400
|
let maxRecordingTimeMs = MAX_RECORDING_TIME_MS;
|
|
11831
13401
|
this.maxRecTimerId = window.setTimeout(() => {
|
|
11832
13402
|
this.stopRecordingMaxRec();
|
|
@@ -11863,68 +13433,75 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11863
13433
|
this.transportActions.pauseAction.disabled = true;
|
|
11864
13434
|
this.statusAlertType = 'info';
|
|
11865
13435
|
this.statusMsg = 'Recorded.';
|
|
11866
|
-
let ad;
|
|
13436
|
+
let ad = null;
|
|
13437
|
+
let ada = null;
|
|
13438
|
+
let adh = null;
|
|
13439
|
+
let frameLen = 0;
|
|
11867
13440
|
if (this.ac) {
|
|
11868
|
-
|
|
13441
|
+
if (this.uploadChunkSizeSeconds || AudioRecorder.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
13442
|
+
ada = this.ac.audioBufferArray();
|
|
13443
|
+
frameLen = ada.frameLen;
|
|
13444
|
+
}
|
|
13445
|
+
else {
|
|
13446
|
+
ad = this.ac.audioBuffer();
|
|
13447
|
+
frameLen = ad.length;
|
|
13448
|
+
}
|
|
13449
|
+
adh = new AudioDataHolder(ad, ada);
|
|
11869
13450
|
let sessId = 0;
|
|
11870
13451
|
if (this._session) {
|
|
11871
13452
|
sessId = this._session.sessionId;
|
|
11872
13453
|
}
|
|
11873
|
-
if (
|
|
11874
|
-
this.
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
13454
|
+
if (this._recordingFile) {
|
|
13455
|
+
// Use an own reference since the writing of the wave file is asynchronous and this._recordingFile might already contain the next recording
|
|
13456
|
+
let rf = this._recordingFile;
|
|
13457
|
+
RecordingFileUtils.setAudioData(rf, adh);
|
|
13458
|
+
this.recorderCombiPane.addRecFile(rf);
|
|
13459
|
+
// Upload if upload enabled and not in chunked upload mode
|
|
13460
|
+
if (this.enableUploadRecordings && !this.uploadChunkSizeSeconds && rf != null && ad != null) {
|
|
13461
|
+
let apiEndPoint = '';
|
|
13462
|
+
if (this.config && this.config.apiEndPoint) {
|
|
13463
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
13464
|
+
}
|
|
13465
|
+
if (apiEndPoint !== '') {
|
|
13466
|
+
apiEndPoint = apiEndPoint + '/';
|
|
13467
|
+
}
|
|
13468
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
13469
|
+
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.uuid;
|
|
13470
|
+
// convert asynchronously to 16-bit integer PCM
|
|
13471
|
+
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
13472
|
+
// TODO duplicate conversion for manual download
|
|
13473
|
+
this.processingRecording = true;
|
|
13474
|
+
let ww = new WavWriter();
|
|
13475
|
+
ww.writeAsync(ad, (wavFile) => {
|
|
13476
|
+
this.postRecordingMultipart(wavFile, recUrl, rf);
|
|
13477
|
+
this.processingRecording = false;
|
|
13478
|
+
this.updateWakeLock();
|
|
13479
|
+
this.changeDetectorRef.detectChanges();
|
|
13480
|
+
});
|
|
11892
13481
|
}
|
|
11893
|
-
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11894
|
-
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.uuid;
|
|
11895
|
-
// convert asynchronously to 16-bit integer PCM
|
|
11896
|
-
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
11897
|
-
// TODO duplicate conversion for manual download
|
|
11898
|
-
this.processingRecording = true;
|
|
11899
|
-
let ww = new WavWriter();
|
|
11900
|
-
ww.writeAsync(ad, (wavFile) => {
|
|
11901
|
-
this.postRecordingMultipart(wavFile, rf.uuid, rf.session, rf._startedAsDateObj, recUrl);
|
|
11902
|
-
this.processingRecording = false;
|
|
11903
|
-
this.updateWakeLock();
|
|
11904
|
-
this.changeDetectorRef.detectChanges();
|
|
11905
|
-
});
|
|
11906
13482
|
}
|
|
11907
13483
|
}
|
|
13484
|
+
this.displayRecFile = this._recordingFile;
|
|
11908
13485
|
this.status = 1 /* IDLE */;
|
|
11909
13486
|
this.navigationDisabled = false;
|
|
11910
13487
|
this.updateNavigationActions();
|
|
11911
13488
|
this.updateWakeLock();
|
|
11912
13489
|
this.changeDetectorRef.detectChanges();
|
|
11913
13490
|
}
|
|
11914
|
-
postRecordingMultipart(wavFile,
|
|
13491
|
+
postRecordingMultipart(wavFile, recUrl, rf) {
|
|
11915
13492
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
11916
13493
|
let fd = new FormData();
|
|
11917
|
-
if (uuid) {
|
|
11918
|
-
fd.set('uuid', uuid);
|
|
13494
|
+
if (rf.uuid) {
|
|
13495
|
+
fd.set('uuid', rf.uuid);
|
|
11919
13496
|
}
|
|
11920
|
-
if (
|
|
11921
|
-
fd.set('sessionId',
|
|
13497
|
+
if (rf.session !== null) {
|
|
13498
|
+
fd.set('sessionId', rf.session.toString());
|
|
11922
13499
|
}
|
|
11923
|
-
if (
|
|
11924
|
-
fd.set('startedDate',
|
|
13500
|
+
if (rf._startedAsDateObj) {
|
|
13501
|
+
fd.set('startedDate', rf._startedAsDateObj.toJSON());
|
|
11925
13502
|
}
|
|
11926
13503
|
fd.set('audio', wavBlob);
|
|
11927
|
-
let ul = new Upload(fd, recUrl);
|
|
13504
|
+
let ul = new Upload(fd, recUrl, rf);
|
|
11928
13505
|
this.uploader.queueUpload(ul);
|
|
11929
13506
|
}
|
|
11930
13507
|
postChunkAudioBuffer(audioBuffer, chunkIdx) {
|
|
@@ -11941,8 +13518,9 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11941
13518
|
}
|
|
11942
13519
|
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11943
13520
|
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/' + chunkIdx;
|
|
13521
|
+
let rf = this._recordingFile;
|
|
11944
13522
|
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
11945
|
-
this.postRecording(wavFile, recUrl);
|
|
13523
|
+
this.postRecording(wavFile, recUrl, rf);
|
|
11946
13524
|
this.processingRecording = false;
|
|
11947
13525
|
});
|
|
11948
13526
|
}
|
|
@@ -11991,11 +13569,11 @@ AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
|
|
|
11991
13569
|
|
|
11992
13570
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}"
|
|
11993
13571
|
[ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
11994
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()"
|
|
13572
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [stateLoading]="audioFetching"
|
|
11995
13573
|
[displayLevelInfos]="displayAudioClip?.levelInfos"></audio-levelbar>
|
|
11996
13574
|
<div fxLayout="row">
|
|
11997
13575
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
11998
|
-
[audioLoaded]="displayAudioClip?.
|
|
13576
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
11999
13577
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
12000
13578
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
12001
13579
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -12034,7 +13612,7 @@ AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
|
|
|
12034
13612
|
[ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
12035
13613
|
</div>
|
|
12036
13614
|
</div>
|
|
12037
|
-
`, isInline: true, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;height:100%;min-height:0px;overflow:hidden}\n", ".ricontrols{padding:4px;box-sizing:border-box;height:100%}\n", ".dark{background:darkgray}\n", ".controlpanel{align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n", ".startstop{width:100%;text-align:center;align-content:center;align-items:center}\n", ".bigbutton{min-width:70px;min-height:50px;font-size:50px;border-radius:20px}\n"], components: [{ type: WarningBar, selector: "app-warningbar", inputs: ["warningText", "show"] }, { type: RecorderCombiPane, selector: "app-recordercombipane", inputs: ["selectDisabled", "selectedRecordingFile", "audioSignalCollapsed", "displayAudioClip", "playStartAction", "playSelectionAction", "autoPlayOnSelectToggleAction", "playStopAction"], outputs: ["selectedRecordingFileChanged"] }, { type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos"] }, { type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }, { type: UploadStatus, selector: "app-uploadstatus", inputs: ["value", "awaitNewUpload", "status"] }, { type: WakeLockIndicator, selector: "app-wakelockindicator", inputs: ["screenLocked"] }, { type: ReadyStateIndicator, selector: "app-readystateindicator", inputs: ["ready"] }, { type: StatusDisplay, selector: "app-sprstatusdisplay", inputs: ["statusAlertType", "statusMsg", "statusWaiting"] }, { type: i3$2.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i3$1.DefaultStyleDirective, selector: " [ngStyle], [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl], [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl], [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i8.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3$1.DefaultShowHideDirective, selector: " [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]", inputs: ["fxShow", "fxShow.print", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.print", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }] });
|
|
13615
|
+
`, isInline: true, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;height:100%;min-height:0px;overflow:hidden}\n", ".ricontrols{padding:4px;box-sizing:border-box;height:100%}\n", ".dark{background:darkgray}\n", ".controlpanel{align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n", ".startstop{width:100%;text-align:center;align-content:center;align-items:center}\n", ".bigbutton{min-width:70px;min-height:50px;font-size:50px;border-radius:20px}\n"], components: [{ type: WarningBar, selector: "app-warningbar", inputs: ["warningText", "show"] }, { type: RecorderCombiPane, selector: "app-recordercombipane", inputs: ["selectDisabled", "selectedRecordingFile", "audioSignalCollapsed", "displayAudioClip", "playStartAction", "playSelectionAction", "autoPlayOnSelectToggleAction", "playStopAction"], outputs: ["selectedRecordingFileChanged"] }, { type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos", "stateLoading"] }, { type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: ["audioSignalCollapsed", "enableDownload", "peakDbLvl", "agc", "audioLoaded", "playStartAction", "playStopAction", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }, { type: UploadStatus, selector: "app-uploadstatus", inputs: ["value", "awaitNewUpload", "status"] }, { type: WakeLockIndicator, selector: "app-wakelockindicator", inputs: ["screenLocked"] }, { type: ReadyStateIndicator, selector: "app-readystateindicator", inputs: ["ready"] }, { type: StatusDisplay, selector: "app-sprstatusdisplay", inputs: ["statusAlertType", "statusMsg", "statusWaiting"] }, { type: i3$2.MatButton, selector: "button[mat-button], button[mat-raised-button], button[mat-icon-button], button[mat-fab], button[mat-mini-fab], button[mat-stroked-button], button[mat-flat-button]", inputs: ["disabled", "disableRipple", "color"], exportAs: ["matButton"] }, { type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i8.DefaultLayoutDirective, selector: " [fxLayout], [fxLayout.xs], [fxLayout.sm], [fxLayout.md], [fxLayout.lg], [fxLayout.xl], [fxLayout.lt-sm], [fxLayout.lt-md], [fxLayout.lt-lg], [fxLayout.lt-xl], [fxLayout.gt-xs], [fxLayout.gt-sm], [fxLayout.gt-md], [fxLayout.gt-lg]", inputs: ["fxLayout", "fxLayout.xs", "fxLayout.sm", "fxLayout.md", "fxLayout.lg", "fxLayout.xl", "fxLayout.lt-sm", "fxLayout.lt-md", "fxLayout.lt-lg", "fxLayout.lt-xl", "fxLayout.gt-xs", "fxLayout.gt-sm", "fxLayout.gt-md", "fxLayout.gt-lg"] }, { type: i3$1.DefaultStyleDirective, selector: " [ngStyle], [ngStyle.xs], [ngStyle.sm], [ngStyle.md], [ngStyle.lg], [ngStyle.xl], [ngStyle.lt-sm], [ngStyle.lt-md], [ngStyle.lt-lg], [ngStyle.lt-xl], [ngStyle.gt-xs], [ngStyle.gt-sm], [ngStyle.gt-md], [ngStyle.gt-lg]", inputs: ["ngStyle", "ngStyle.xs", "ngStyle.sm", "ngStyle.md", "ngStyle.lg", "ngStyle.xl", "ngStyle.lt-sm", "ngStyle.lt-md", "ngStyle.lt-lg", "ngStyle.lt-xl", "ngStyle.gt-xs", "ngStyle.gt-sm", "ngStyle.gt-md", "ngStyle.gt-lg"] }, { type: i4.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { type: i8.DefaultFlexDirective, selector: " [fxFlex], [fxFlex.xs], [fxFlex.sm], [fxFlex.md], [fxFlex.lg], [fxFlex.xl], [fxFlex.lt-sm], [fxFlex.lt-md], [fxFlex.lt-lg], [fxFlex.lt-xl], [fxFlex.gt-xs], [fxFlex.gt-sm], [fxFlex.gt-md], [fxFlex.gt-lg]", inputs: ["fxFlex", "fxFlex.xs", "fxFlex.sm", "fxFlex.md", "fxFlex.lg", "fxFlex.xl", "fxFlex.lt-sm", "fxFlex.lt-md", "fxFlex.lt-lg", "fxFlex.lt-xl", "fxFlex.gt-xs", "fxFlex.gt-sm", "fxFlex.gt-md", "fxFlex.gt-lg"] }, { type: i4.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { type: i3$1.DefaultShowHideDirective, selector: " [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]", inputs: ["fxShow", "fxShow.print", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.print", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }] });
|
|
12038
13616
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AudioRecorder, decorators: [{
|
|
12039
13617
|
type: Component,
|
|
12040
13618
|
args: [{
|
|
@@ -12057,11 +13635,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
12057
13635
|
|
|
12058
13636
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}"
|
|
12059
13637
|
[ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
12060
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()"
|
|
13638
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [stateLoading]="audioFetching"
|
|
12061
13639
|
[displayLevelInfos]="displayAudioClip?.levelInfos"></audio-levelbar>
|
|
12062
13640
|
<div fxLayout="row">
|
|
12063
13641
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
12064
|
-
[audioLoaded]="displayAudioClip?.
|
|
13642
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
12065
13643
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
12066
13644
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
12067
13645
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -12341,20 +13919,20 @@ class SpeechrecorderngModule {
|
|
|
12341
13919
|
}
|
|
12342
13920
|
SpeechrecorderngModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
12343
13921
|
SpeechrecorderngModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, declarations: [AudioSignal, Sonagram, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, Progress, SimpleTrafficLight, Recinstructions, Prompter, PromptContainer, PromptingContainer, Prompting, StatusDisplay,
|
|
12344
|
-
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder], imports: [i1$1.RouterModule, FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule], exports: [MessageDialog, SpeechrecorderngComponent, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, AudioRecorder] });
|
|
12345
|
-
SpeechrecorderngModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, providers: [SessionService, ProjectService, ScriptService, RecordingService, RecordingFileService, SpeechRecorderUploader], imports: [[RouterModule.forChild(SPR_ROUTES), FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule]] });
|
|
13922
|
+
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder], imports: [i1$1.RouterModule, FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule, MatMenuModule], exports: [MessageDialog, SpeechrecorderngComponent, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, AudioRecorder] });
|
|
13923
|
+
SpeechrecorderngModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, providers: [SessionService, ProjectService, ScriptService, RecordingService, RecordingFileService, SpeechRecorderUploader], imports: [[RouterModule.forChild(SPR_ROUTES), FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule, MatMenuModule]] });
|
|
12346
13924
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, decorators: [{
|
|
12347
13925
|
type: NgModule,
|
|
12348
13926
|
args: [{
|
|
12349
13927
|
declarations: [AudioSignal, Sonagram, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, Progress, SimpleTrafficLight, Recinstructions, Prompter, PromptContainer, PromptingContainer, Prompting, StatusDisplay,
|
|
12350
13928
|
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder],
|
|
12351
13929
|
exports: [MessageDialog, SpeechrecorderngComponent, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, AudioRecorder],
|
|
12352
|
-
imports: [RouterModule.forChild(SPR_ROUTES), FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule],
|
|
13930
|
+
imports: [RouterModule.forChild(SPR_ROUTES), FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule, MatMenuModule],
|
|
12353
13931
|
providers: [SessionService, ProjectService, ScriptService, RecordingService, RecordingFileService, SpeechRecorderUploader]
|
|
12354
13932
|
}]
|
|
12355
13933
|
}] });
|
|
12356
13934
|
|
|
12357
|
-
const VERSION = '
|
|
13935
|
+
const VERSION = '3.0.0';
|
|
12358
13936
|
|
|
12359
13937
|
/*
|
|
12360
13938
|
* Public API Surface of speechrecorderng
|