speechrecorderng 2.25.2 → 3.0.1
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 +12 -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 +17 -3
- 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 +63 -7
- package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +96 -7
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +119 -106
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +34 -7
- 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 +195 -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 +123 -101
- 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 +2355 -753
- package/fesm2015/speechrecorderng.mjs.map +1 -1
- package/fesm2020/speechrecorderng.mjs +2338 -746
- 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 +8 -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 +4 -2
- 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 +16 -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 +10 -5
- 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 +33 -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,42 @@ 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 equals(recordinFile, otherRecordingFile) {
|
|
2299
|
+
if (recordinFile && otherRecordingFile) {
|
|
2300
|
+
if (otherRecordingFile === recordinFile) {
|
|
2301
|
+
return true;
|
|
2302
|
+
}
|
|
2303
|
+
if (otherRecordingFile.uuid === recordinFile.uuid) {
|
|
2304
|
+
return true;
|
|
2305
|
+
}
|
|
2306
|
+
}
|
|
2307
|
+
return false;
|
|
2308
|
+
}
|
|
2309
|
+
static setAudioData(rf, audioDataHolder) {
|
|
2310
|
+
rf.audioDataHolder = audioDataHolder;
|
|
2311
|
+
if (audioDataHolder) {
|
|
2312
|
+
rf.frames = audioDataHolder.frameLen;
|
|
2313
|
+
rf.timeLength = audioDataHolder.duration;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
static sampleCount(rf) {
|
|
2317
|
+
if (rf.audioDataHolder) {
|
|
2318
|
+
return rf.audioDataHolder.sampleCounts();
|
|
2319
|
+
}
|
|
2320
|
+
else {
|
|
2321
|
+
return 0;
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
static expireAudioData(rf) {
|
|
2325
|
+
let rv = rf.audioDataHolder;
|
|
2326
|
+
rf.audioDataHolder = null;
|
|
2327
|
+
return rv;
|
|
2328
|
+
}
|
|
1522
2329
|
}
|
|
1523
2330
|
|
|
1524
2331
|
// state of an upload
|
|
@@ -1569,7 +2376,8 @@ class UploaderStatusChangeEvent {
|
|
|
1569
2376
|
}
|
|
1570
2377
|
}
|
|
1571
2378
|
class Upload {
|
|
1572
|
-
constructor(blob, url) {
|
|
2379
|
+
constructor(blob, url, serverPersistable = null) {
|
|
2380
|
+
this.serverPersistable = serverPersistable;
|
|
1573
2381
|
this.toString = () => {
|
|
1574
2382
|
let s = `Upload: Status: ${this.status}, URL: ${this._url}`;
|
|
1575
2383
|
if (this._data instanceof Blob) {
|
|
@@ -1590,6 +2398,17 @@ class Upload {
|
|
|
1590
2398
|
get data() {
|
|
1591
2399
|
return this._data;
|
|
1592
2400
|
}
|
|
2401
|
+
done() {
|
|
2402
|
+
this.status = UploadStatus$1.DONE;
|
|
2403
|
+
//console.debug("Single upload done.");
|
|
2404
|
+
if (this.serverPersistable) {
|
|
2405
|
+
this.serverPersistable.serverPersisted = true;
|
|
2406
|
+
//console.debug("Single upload set server persisted: "+this.serverPersistable);
|
|
2407
|
+
}
|
|
2408
|
+
else {
|
|
2409
|
+
//console.debug("Server persistable not set.");
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
1593
2412
|
}
|
|
1594
2413
|
class Uploader {
|
|
1595
2414
|
constructor(http, withCredentials = false) {
|
|
@@ -1628,7 +2447,7 @@ class Uploader {
|
|
|
1628
2447
|
return si;
|
|
1629
2448
|
}
|
|
1630
2449
|
uploadDone(ul) {
|
|
1631
|
-
ul.
|
|
2450
|
+
ul.done();
|
|
1632
2451
|
// remove upload from queue
|
|
1633
2452
|
for (let i = 0; i < this.que.length; i++) {
|
|
1634
2453
|
if (this.que[i] === ul) {
|
|
@@ -2063,15 +2882,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
2063
2882
|
}], ctorParameters: function () { return []; } });
|
|
2064
2883
|
|
|
2065
2884
|
class AudioClip {
|
|
2066
|
-
constructor(
|
|
2885
|
+
constructor(_audioDataHolder) {
|
|
2886
|
+
this._audioDataHolder = _audioDataHolder;
|
|
2067
2887
|
this._selection = null;
|
|
2888
|
+
this._levelInfos = null;
|
|
2068
2889
|
this.selectionObservers = new Array();
|
|
2069
|
-
this._buffer = buffer;
|
|
2070
2890
|
}
|
|
2071
|
-
get
|
|
2072
|
-
return this.
|
|
2891
|
+
get audioDataHolder() {
|
|
2892
|
+
return this._audioDataHolder;
|
|
2073
2893
|
}
|
|
2074
|
-
;
|
|
2075
2894
|
get selection() {
|
|
2076
2895
|
return this._selection;
|
|
2077
2896
|
}
|
|
@@ -2086,6 +2905,12 @@ class AudioClip {
|
|
|
2086
2905
|
selObs(this);
|
|
2087
2906
|
}
|
|
2088
2907
|
}
|
|
2908
|
+
get levelInfos() {
|
|
2909
|
+
return this._levelInfos;
|
|
2910
|
+
}
|
|
2911
|
+
set levelInfos(value) {
|
|
2912
|
+
this._levelInfos = value;
|
|
2913
|
+
}
|
|
2089
2914
|
addSelectionObserver(selectionObserver, init = false) {
|
|
2090
2915
|
let obsAlreadyInList = this.selectionObservers.find((obs) => (obs === selectionObserver));
|
|
2091
2916
|
if (!obsAlreadyInList) {
|
|
@@ -2168,19 +2993,32 @@ class ViewSelection {
|
|
|
2168
2993
|
class BasicAudioCanvasLayerComponent extends CanvasLayerComponent {
|
|
2169
2994
|
constructor() {
|
|
2170
2995
|
super(...arguments);
|
|
2171
|
-
|
|
2996
|
+
//protected _audioData: AudioBuffer|null=null;
|
|
2997
|
+
//protected _arrayAudioData: ArrayAudioBuffer|null=null;
|
|
2998
|
+
this._audioDataHolder = null;
|
|
2172
2999
|
this._bgColor = 'white';
|
|
2173
3000
|
this._selectColor = 'rgba(0%,0%,100%,25%)';
|
|
2174
3001
|
}
|
|
3002
|
+
frameLength() {
|
|
3003
|
+
let frameLength = null;
|
|
3004
|
+
// if (this._audioData && this._audioData.numberOfChannels > 0) {
|
|
3005
|
+
// let ch0 = this._audioData.getChannelData(0);
|
|
3006
|
+
// frameLength = ch0.length;
|
|
3007
|
+
//
|
|
3008
|
+
// }else if(this._arrayAudioData){
|
|
3009
|
+
// frameLength=this._arrayAudioData.frameLen;
|
|
3010
|
+
// }
|
|
3011
|
+
return frameLength;
|
|
3012
|
+
}
|
|
2175
3013
|
/**
|
|
2176
3014
|
* Returns pixel position depending on current zoom setting.
|
|
2177
3015
|
* @param framePos audio frame (sample) position
|
|
2178
3016
|
*/
|
|
2179
3017
|
frameToXPixelPosition(framePos) {
|
|
3018
|
+
var _a;
|
|
2180
3019
|
let pixelPos = null;
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
let frameLength = ch0.length;
|
|
3020
|
+
let frameLength = (_a = this._audioDataHolder) === null || _a === void 0 ? void 0 : _a.frameLen;
|
|
3021
|
+
if (frameLength !== undefined) {
|
|
2184
3022
|
let vw;
|
|
2185
3023
|
if (this.bounds) {
|
|
2186
3024
|
vw = this.bounds.dimension.width;
|
|
@@ -2209,10 +3047,10 @@ class BasicAudioCanvasLayerComponent extends CanvasLayerComponent {
|
|
|
2209
3047
|
}
|
|
2210
3048
|
}
|
|
2211
3049
|
viewPortXPixelToFramePosition(xViewPortPixelPos) {
|
|
3050
|
+
var _a;
|
|
2212
3051
|
let vpXramePos = null;
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
let frameLength = ch0.length;
|
|
3052
|
+
let frameLength = (_a = this._audioDataHolder) === null || _a === void 0 ? void 0 : _a.frameLen;
|
|
3053
|
+
if (frameLength !== undefined) {
|
|
2216
3054
|
let vw;
|
|
2217
3055
|
if (this.bounds) {
|
|
2218
3056
|
vw = this.bounds.dimension.width;
|
|
@@ -2389,8 +3227,8 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2389
3227
|
if (viewSel) {
|
|
2390
3228
|
let frameStart = this.viewPortXPixelToFramePosition(viewSel.startX);
|
|
2391
3229
|
let frameEnd = this.viewPortXPixelToFramePosition(viewSel.endX);
|
|
2392
|
-
if (this.
|
|
2393
|
-
ns = new Selection(this.
|
|
3230
|
+
if (this._audioDataHolder && frameStart != null && frameEnd != null) {
|
|
3231
|
+
ns = new Selection(this._audioDataHolder.sampleRate, frameStart, frameEnd);
|
|
2394
3232
|
}
|
|
2395
3233
|
}
|
|
2396
3234
|
this.selectingEventEmitter.emit(ns);
|
|
@@ -2400,8 +3238,8 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2400
3238
|
if (viewSel) {
|
|
2401
3239
|
let frameStart = this.viewPortXPixelToFramePosition(viewSel.startX);
|
|
2402
3240
|
let frameEnd = this.viewPortXPixelToFramePosition(viewSel.endX);
|
|
2403
|
-
if (this.
|
|
2404
|
-
ns = new Selection(this.
|
|
3241
|
+
if (this._audioDataHolder && frameStart != null && frameEnd != null) {
|
|
3242
|
+
ns = new Selection(this._audioDataHolder.sampleRate, frameStart, frameEnd);
|
|
2405
3243
|
}
|
|
2406
3244
|
}
|
|
2407
3245
|
this.selectedEventEmitter.emit(ns);
|
|
@@ -2482,7 +3320,7 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2482
3320
|
g.lineTo(xViewPortPixelpos, h);
|
|
2483
3321
|
g.closePath();
|
|
2484
3322
|
g.stroke();
|
|
2485
|
-
if (this.
|
|
3323
|
+
if (this._audioDataHolder) {
|
|
2486
3324
|
g.font = '14px sans-serif';
|
|
2487
3325
|
g.fillStyle = 'yellow';
|
|
2488
3326
|
g.fillText(framePos.toString(), xViewPortPixelpos + 2, 50);
|
|
@@ -2494,6 +3332,7 @@ class AudioCanvasLayerComponent extends BasicAudioCanvasLayerComponent {
|
|
|
2494
3332
|
}
|
|
2495
3333
|
}
|
|
2496
3334
|
}
|
|
3335
|
+
AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD = 10 * 60 * 48000; // Use streaming/chunking if audio clip has more than this number of samples
|
|
2497
3336
|
AudioCanvasLayerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AudioCanvasLayerComponent, deps: null, target: i0.ɵɵFactoryTarget.Directive });
|
|
2498
3337
|
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 });
|
|
2499
3338
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AudioCanvasLayerComponent, decorators: [{
|
|
@@ -2528,7 +3367,7 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2528
3367
|
this._playFramePosition = null;
|
|
2529
3368
|
this.worker = null;
|
|
2530
3369
|
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
2531
|
-
this.
|
|
3370
|
+
this._audioDataHolder = null;
|
|
2532
3371
|
this._bgColor = 'black';
|
|
2533
3372
|
this._selectColor = 'rgba(255,255,0,0.8)';
|
|
2534
3373
|
}
|
|
@@ -2581,25 +3420,26 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2581
3420
|
*/
|
|
2582
3421
|
workerFunction() {
|
|
2583
3422
|
addEventListener('message', ({ data }) => {
|
|
2584
|
-
let audioData = data.audioData;
|
|
2585
|
-
let
|
|
2586
|
-
let
|
|
2587
|
-
let
|
|
2588
|
-
let vw = data.vw;
|
|
2589
|
-
let chs = data.chs;
|
|
2590
|
-
let
|
|
3423
|
+
let audioData = data.audioData; // audio data part required to render view port
|
|
3424
|
+
let auOffset = data.audioDataOffset;
|
|
3425
|
+
let l = data.l; // left pixel position of view port
|
|
3426
|
+
let w = data.w; // width of viewport
|
|
3427
|
+
let vw = data.vw; // total width of (virtual) audio view (not viewport width)
|
|
3428
|
+
let chs = data.chs; // number of channels
|
|
3429
|
+
let dataFrameLength = data.audioDataFrameLength; // frame length of audio data part required for view port
|
|
3430
|
+
let frameLength = data.frameLength; // total frame length (of audio clip)
|
|
3431
|
+
//console.debug("W: left: "+l+", w:"+w+", vw: "+vw+", chs: "+chs+", frameLength: "+frameLength);
|
|
2591
3432
|
let psMinMax = new Float32Array(0);
|
|
2592
|
-
if (audioData && w >= 0 && vw > 0) {
|
|
3433
|
+
if (audioData && audioData.length > 0 && w >= 0 && vw > 0) {
|
|
2593
3434
|
let framesPerPixel = frameLength / vw;
|
|
2594
|
-
let y = 0;
|
|
2595
3435
|
let pointsLen = w * chs;
|
|
2596
3436
|
// one for min one for max
|
|
2597
3437
|
let arrLen = pointsLen * 2;
|
|
2598
3438
|
psMinMax = new Float32Array(arrLen);
|
|
2599
3439
|
let chFramePos = 0;
|
|
3440
|
+
let chFrameLength = audioData.length / chs;
|
|
2600
3441
|
for (let ch = 0; ch < chs; ch++) {
|
|
2601
|
-
|
|
2602
|
-
chFramePos = ch * frameLength;
|
|
3442
|
+
chFramePos = ch * chFrameLength;
|
|
2603
3443
|
for (let pii = 0; pii < w; pii++) {
|
|
2604
3444
|
let virtPii = l + pii;
|
|
2605
3445
|
let pMin = Infinity;
|
|
@@ -2609,24 +3449,28 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2609
3449
|
for (let ai = 0; ai < framesPerPixel; ai++) {
|
|
2610
3450
|
let framePos = pixelFramePos + ai;
|
|
2611
3451
|
let a = 0;
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
3452
|
+
let bufPos = framePos - auOffset;
|
|
3453
|
+
//let bufPos=framePos;
|
|
3454
|
+
if (bufPos >= 0 && bufPos < audioData.length) {
|
|
3455
|
+
a = audioData[bufPos];
|
|
3456
|
+
//console.debug("W: ch: "+ch+", pixelFramePos: "+pixelFramePos+", framePos: "+framePos+", auOffset: "+auOffset+", bufPos: "+bufPos+", audioData.length: "+audioData.length+", a: "+a);
|
|
3457
|
+
if (a < pMin) {
|
|
3458
|
+
pMin = a;
|
|
3459
|
+
}
|
|
3460
|
+
if (a > pMax) {
|
|
3461
|
+
pMax = a;
|
|
3462
|
+
}
|
|
2620
3463
|
}
|
|
2621
3464
|
}
|
|
2622
3465
|
let psMinPos = ch * w + pii;
|
|
2623
3466
|
psMinMax[psMinPos] = pMin;
|
|
2624
3467
|
let psMaxPos = pointsLen + psMinPos;
|
|
2625
3468
|
psMinMax[psMaxPos] = pMax;
|
|
3469
|
+
//console.debug("psMinMax["+psMinPos+"]="+pMin+",psMinMax["+psMaxPos+"]="+pMax);
|
|
2626
3470
|
}
|
|
2627
3471
|
}
|
|
2628
3472
|
}
|
|
2629
|
-
postMessage({ psMinMax: psMinMax, l: data.l,
|
|
3473
|
+
postMessage({ psMinMax: psMinMax, l: data.l, w: data.w, chs: data.chs, eod: data.eod }, [psMinMax.buffer]);
|
|
2630
3474
|
});
|
|
2631
3475
|
}
|
|
2632
3476
|
startDraw(clear = true) {
|
|
@@ -2654,41 +3498,143 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2654
3498
|
if (this.bounds && this.bounds.dimension) {
|
|
2655
3499
|
let w = Math.round(this.bounds.dimension.width);
|
|
2656
3500
|
let h = Math.round(this.bounds.dimension.height);
|
|
2657
|
-
if (this.
|
|
3501
|
+
if (this._audioDataHolder && w > 0 && h > 0) {
|
|
2658
3502
|
//this.wo = new Worker('./audiosignal.worker.js',{type: 'module'});
|
|
2659
3503
|
this.worker = new Worker(this.workerURL);
|
|
2660
3504
|
//this.wo = new Worker('worker/audiosignal.worker.ts');
|
|
2661
3505
|
//let Worker = require('worker!../../../workers/uploader/main');
|
|
2662
|
-
let chs = this.
|
|
2663
|
-
let
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
let
|
|
2668
|
-
|
|
2669
|
-
|
|
2670
|
-
|
|
2671
|
-
//let
|
|
3506
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
3507
|
+
let leftPos = Math.round(this.bounds.position.left);
|
|
3508
|
+
let renderPos = leftPos;
|
|
3509
|
+
let vw = Math.round(this.virtualDimension.width);
|
|
3510
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
3511
|
+
let framesPerPixel = Math.ceil(frameLength / vw);
|
|
3512
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
3513
|
+
//let arrayAudioBuffer=this._audioDataHolder.arrayBuffer;
|
|
3514
|
+
let arrAbBuf;
|
|
3515
|
+
//let ais:ArrayAudioBufferInputStream|null=null;
|
|
3516
|
+
//let aisBuf:Float32Array[]|null=null;
|
|
3517
|
+
let psMinMax = null;
|
|
2672
3518
|
if (this.worker) {
|
|
2673
3519
|
this.worker.onmessage = (me) => {
|
|
2674
|
-
|
|
2675
|
-
|
|
2676
|
-
|
|
2677
|
-
|
|
3520
|
+
if (me.data.eod === true) {
|
|
3521
|
+
let psMinMaxTmp;
|
|
3522
|
+
if (psMinMax) {
|
|
3523
|
+
psMinMaxTmp = psMinMax;
|
|
3524
|
+
}
|
|
3525
|
+
else {
|
|
3526
|
+
psMinMaxTmp = me.data.psMinMax;
|
|
3527
|
+
}
|
|
3528
|
+
this.drawRendered(leftPos, w, h, chs, psMinMaxTmp);
|
|
3529
|
+
if (this.worker) {
|
|
3530
|
+
this.worker.terminate();
|
|
3531
|
+
}
|
|
3532
|
+
this.worker = null;
|
|
3533
|
+
}
|
|
3534
|
+
else if (this._audioDataHolder && arrAbBuf) {
|
|
3535
|
+
let rw = me.data.w;
|
|
3536
|
+
let rPointsLen = chs * rw;
|
|
3537
|
+
let pointsLen = chs * w;
|
|
3538
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3539
|
+
if (psMinMax) {
|
|
3540
|
+
let rBasePos = ch * rw;
|
|
3541
|
+
let basePos = ch * w;
|
|
3542
|
+
let rPosMin = rBasePos;
|
|
3543
|
+
let rPosMax = rPointsLen + rPosMin;
|
|
3544
|
+
let posMin = basePos + (renderPos - leftPos);
|
|
3545
|
+
let posMax = pointsLen + posMin;
|
|
3546
|
+
psMinMax[posMin] = me.data.psMinMax[rPosMin];
|
|
3547
|
+
//console.debug('Min: ('+pos+'): '+me.data.psMinMax[0]);
|
|
3548
|
+
psMinMax[posMax] = me.data.psMinMax[rPosMax];
|
|
3549
|
+
// console.debug('Max: ('+(pointsLen+pos)+'): '+me.data.psMinMax[1]);
|
|
3550
|
+
//console.debug("psMinMax["+posMin+"]="+me.data.psMinMax[rPosMin]+" (rPosMin="+rPosMin+"),psMinMax["+posMax+"]="+me.data.psMinMax[rPosMax]);
|
|
3551
|
+
}
|
|
3552
|
+
}
|
|
3553
|
+
let eod = false;
|
|
3554
|
+
renderPos++;
|
|
3555
|
+
let ad;
|
|
3556
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw);
|
|
3557
|
+
if (renderPos < leftPos + w) {
|
|
3558
|
+
let read = this._audioDataHolder.frames(leftFramePos, framesPerPixel, arrAbBuf);
|
|
3559
|
+
//console.debug("First read frame: "+arrAbBuf[0][0]);
|
|
3560
|
+
ad = new Float32Array(chs * framesPerPixel);
|
|
3561
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3562
|
+
ad.set(arrAbBuf[ch], ch * framesPerPixel);
|
|
3563
|
+
}
|
|
3564
|
+
eod = (read <= 0);
|
|
3565
|
+
}
|
|
3566
|
+
else {
|
|
3567
|
+
ad = new Float32Array();
|
|
3568
|
+
eod = true;
|
|
3569
|
+
}
|
|
3570
|
+
let adBuf = ad.buffer;
|
|
3571
|
+
if (this.worker) {
|
|
3572
|
+
this.worker.postMessage({
|
|
3573
|
+
l: renderPos,
|
|
3574
|
+
w: me.data.w,
|
|
3575
|
+
h: h,
|
|
3576
|
+
vw: vw,
|
|
3577
|
+
chs: chs,
|
|
3578
|
+
frameLength: frameLength,
|
|
3579
|
+
audioData: ad,
|
|
3580
|
+
audioDataOffset: leftFramePos,
|
|
3581
|
+
eod: eod
|
|
3582
|
+
}, [adBuf]);
|
|
3583
|
+
}
|
|
2678
3584
|
}
|
|
2679
|
-
this.worker = null;
|
|
2680
3585
|
};
|
|
2681
3586
|
}
|
|
2682
|
-
|
|
2683
|
-
|
|
2684
|
-
|
|
2685
|
-
|
|
2686
|
-
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
|
|
3587
|
+
if (audioBuffer && audioBuffer.length * audioBuffer.numberOfChannels < AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD) {
|
|
3588
|
+
// Render whole clip at once
|
|
3589
|
+
arrAbBuf = null;
|
|
3590
|
+
psMinMax = null;
|
|
3591
|
+
let ad = new Float32Array(chs * frameLength);
|
|
3592
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3593
|
+
ad.set(audioBuffer.getChannelData(ch), ch * frameLength);
|
|
3594
|
+
}
|
|
3595
|
+
this.worker.postMessage({
|
|
3596
|
+
l: leftPos,
|
|
3597
|
+
w: w,
|
|
3598
|
+
vw: vw,
|
|
3599
|
+
chs: chs,
|
|
3600
|
+
frameLength: frameLength,
|
|
3601
|
+
audioData: ad,
|
|
3602
|
+
audioDataOffset: 0,
|
|
3603
|
+
eod: true
|
|
3604
|
+
}, [ad.buffer]);
|
|
3605
|
+
}
|
|
3606
|
+
else {
|
|
3607
|
+
// Render pixel by pixel
|
|
3608
|
+
if (w > 0) {
|
|
3609
|
+
if (framesPerPixel > 0) {
|
|
3610
|
+
let rw = 1;
|
|
3611
|
+
//ais = new ArrayAudioBufferInputStream(arrayAudioBuffer);
|
|
3612
|
+
arrAbBuf = new Array(chs);
|
|
3613
|
+
psMinMax = new Float32Array(chs * w * 2);
|
|
3614
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3615
|
+
arrAbBuf[ch] = new Float32Array(framesPerPixel);
|
|
3616
|
+
}
|
|
3617
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw);
|
|
3618
|
+
let auOffset = leftFramePos; // should always be 0
|
|
3619
|
+
//let read=arrayAudioBuffer.frames(leftFramePos,framesPerPixel,arrAbBuf);
|
|
3620
|
+
let read = this._audioDataHolder.frames(leftFramePos, framesPerPixel, arrAbBuf);
|
|
3621
|
+
let ad = new Float32Array(chs * framesPerPixel);
|
|
3622
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3623
|
+
ad.set(arrAbBuf[ch], ch * framesPerPixel);
|
|
3624
|
+
}
|
|
3625
|
+
this.worker.postMessage({
|
|
3626
|
+
l: renderPos,
|
|
3627
|
+
w: rw,
|
|
3628
|
+
vw: vw,
|
|
3629
|
+
chs: chs,
|
|
3630
|
+
frameLength: frameLength,
|
|
3631
|
+
audioData: ad,
|
|
3632
|
+
audioDataOffset: auOffset,
|
|
3633
|
+
eod: (read <= 0)
|
|
3634
|
+
}, [ad.buffer]);
|
|
3635
|
+
}
|
|
3636
|
+
}
|
|
3637
|
+
}
|
|
2692
3638
|
}
|
|
2693
3639
|
else {
|
|
2694
3640
|
let g = this.signalCanvas.getContext("2d");
|
|
@@ -2698,42 +3644,42 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2698
3644
|
}
|
|
2699
3645
|
}
|
|
2700
3646
|
}
|
|
2701
|
-
drawRendered(
|
|
3647
|
+
drawRendered(left, w, h, chs, psMinMax) {
|
|
2702
3648
|
this.drawBg();
|
|
2703
|
-
this.signalCanvas.style.left =
|
|
2704
|
-
this.signalCanvas.width =
|
|
2705
|
-
this.signalCanvas.height =
|
|
3649
|
+
this.signalCanvas.style.left = left.toString() + 'px';
|
|
3650
|
+
this.signalCanvas.width = w;
|
|
3651
|
+
this.signalCanvas.height = h;
|
|
2706
3652
|
let g = this.signalCanvas.getContext("2d");
|
|
2707
3653
|
if (g) {
|
|
2708
|
-
g.clearRect(0, 0,
|
|
3654
|
+
g.clearRect(0, 0, w, h);
|
|
2709
3655
|
//g.fillStyle = "black";
|
|
2710
3656
|
//g.fillRect(0, 0, me.data.w, me.data.h);
|
|
2711
|
-
let pointsLen =
|
|
3657
|
+
let pointsLen = w * chs;
|
|
2712
3658
|
// one for min one for max
|
|
2713
3659
|
let arrLen = pointsLen * 2;
|
|
2714
|
-
if (this.
|
|
3660
|
+
if (this._audioDataHolder) {
|
|
2715
3661
|
let std = Date.now();
|
|
2716
|
-
let chH =
|
|
3662
|
+
let chH = h / chs;
|
|
2717
3663
|
let y = 0;
|
|
2718
|
-
for (let ch = 0; ch <
|
|
3664
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
2719
3665
|
let x = 0;
|
|
2720
|
-
let psMinPos = ch *
|
|
3666
|
+
let psMinPos = ch * w;
|
|
2721
3667
|
let psMaxPos = pointsLen + psMinPos;
|
|
2722
3668
|
g.fillStyle = 'green';
|
|
2723
3669
|
g.strokeStyle = 'green';
|
|
2724
3670
|
// draw audio signal as single polygon
|
|
2725
3671
|
g.beginPath();
|
|
2726
|
-
g.moveTo(0, y + (chH / 2) +
|
|
2727
|
-
for (let pii = 0; pii <
|
|
2728
|
-
let psMax =
|
|
3672
|
+
g.moveTo(0, y + (chH / 2) + psMinMax[psMaxPos] * chH / 2);
|
|
3673
|
+
for (let pii = 0; pii < w; pii++) {
|
|
3674
|
+
let psMax = psMinMax[psMaxPos + pii];
|
|
2729
3675
|
let pv = psMax * chH / 2;
|
|
2730
3676
|
let yd = y + (chH / 2) - pv;
|
|
2731
3677
|
//console.log("LineTo: : "+pii+" "+yd)
|
|
2732
3678
|
g.lineTo(pii, yd);
|
|
2733
3679
|
}
|
|
2734
|
-
let revPixelStart =
|
|
3680
|
+
let revPixelStart = w - 1;
|
|
2735
3681
|
for (let pii = revPixelStart; pii >= 0; pii--) {
|
|
2736
|
-
let psMin =
|
|
3682
|
+
let psMin = psMinMax[psMinPos + pii];
|
|
2737
3683
|
let pv = psMin * chH / 2;
|
|
2738
3684
|
let yd = y + (chH / 2) - pv;
|
|
2739
3685
|
//console.log("LineTo: : "+pii+" "+yd)
|
|
@@ -2757,13 +3703,23 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2757
3703
|
g.clearRect(0, 0, w, h);
|
|
2758
3704
|
//g.fillStyle = "black";
|
|
2759
3705
|
//g.fillRect(0, 0, w, h);
|
|
2760
|
-
if (this.
|
|
3706
|
+
if (this._audioDataHolder) {
|
|
2761
3707
|
let std = Date.now();
|
|
2762
|
-
let chs = this.
|
|
3708
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
2763
3709
|
let chH = h / chs;
|
|
2764
|
-
let frameLength = this.
|
|
3710
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
2765
3711
|
let framesPerPixel = frameLength / w;
|
|
2766
3712
|
let y = 0;
|
|
3713
|
+
let ais = null;
|
|
3714
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
3715
|
+
let aisBuffer = null;
|
|
3716
|
+
if (!audioBuffer) {
|
|
3717
|
+
ais = this._audioDataHolder.audioInputStream();
|
|
3718
|
+
aisBuffer = new Array(chs);
|
|
3719
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3720
|
+
aisBuffer[ch] = new Float32Array(framesPerPixel);
|
|
3721
|
+
}
|
|
3722
|
+
}
|
|
2767
3723
|
for (let ch = 0; ch < chs; ch++) {
|
|
2768
3724
|
let x = 0;
|
|
2769
3725
|
let psMin = new Float32Array(w);
|
|
@@ -2772,20 +3728,33 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2772
3728
|
for (let pii = 0; pii < w; pii++) {
|
|
2773
3729
|
let pMin = 0;
|
|
2774
3730
|
let pMax = 0;
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
|
|
2778
|
-
|
|
2779
|
-
|
|
2780
|
-
pMin
|
|
3731
|
+
if (audioBuffer) {
|
|
3732
|
+
// calculate pixel min/max amplitude
|
|
3733
|
+
for (let ai = 0; ai < framesPerPixel; ai++) {
|
|
3734
|
+
//let framePos=(pii*framesPerPixel)+ai;
|
|
3735
|
+
let a = audioBuffer.getChannelData(ch)[framePos++];
|
|
3736
|
+
if (a < pMin) {
|
|
3737
|
+
pMin = a;
|
|
3738
|
+
}
|
|
3739
|
+
if (a > pMax) {
|
|
3740
|
+
pMax = a;
|
|
3741
|
+
}
|
|
2781
3742
|
}
|
|
2782
|
-
|
|
2783
|
-
|
|
3743
|
+
}
|
|
3744
|
+
else if (ais && aisBuffer) {
|
|
3745
|
+
let r = ais.read(aisBuffer);
|
|
3746
|
+
for (let ai = 0; ai < r; ai++) {
|
|
3747
|
+
let a = aisBuffer[ch][ai];
|
|
3748
|
+
if (a < pMin) {
|
|
3749
|
+
pMin = a;
|
|
3750
|
+
}
|
|
3751
|
+
if (a > pMax) {
|
|
3752
|
+
pMax = a;
|
|
3753
|
+
}
|
|
2784
3754
|
}
|
|
2785
3755
|
}
|
|
2786
3756
|
psMin[pii] = pMin;
|
|
2787
3757
|
psMax[pii] = pMax;
|
|
2788
|
-
//console.log("Min: ", pMin, " max: ", pMax);
|
|
2789
3758
|
}
|
|
2790
3759
|
g.fillStyle = 'green';
|
|
2791
3760
|
g.strokeStyle = 'green';
|
|
@@ -2810,12 +3779,11 @@ class AudioSignal extends AudioCanvasLayerComponent {
|
|
|
2810
3779
|
g.stroke();
|
|
2811
3780
|
y += chH;
|
|
2812
3781
|
}
|
|
2813
|
-
//this.drawPlayPosition();
|
|
2814
3782
|
}
|
|
2815
3783
|
}
|
|
2816
3784
|
}
|
|
2817
3785
|
setData(audioData) {
|
|
2818
|
-
this.
|
|
3786
|
+
this._audioDataHolder = audioData;
|
|
2819
3787
|
this.playFramePosition = 0;
|
|
2820
3788
|
}
|
|
2821
3789
|
}
|
|
@@ -3184,7 +4152,7 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3184
4152
|
this._playFramePosition = null;
|
|
3185
4153
|
this.dftSize = DEFAULT_DFT_SIZE;
|
|
3186
4154
|
this.worker = null;
|
|
3187
|
-
this.
|
|
4155
|
+
this._audioDataHolder = null;
|
|
3188
4156
|
this.markers = new Array();
|
|
3189
4157
|
this.dft = new DFTFloat32(this.dftSize);
|
|
3190
4158
|
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
@@ -3237,7 +4205,7 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3237
4205
|
g.lineTo(xViewPortPixelpos, h);
|
|
3238
4206
|
g.closePath();
|
|
3239
4207
|
g.stroke();
|
|
3240
|
-
if (this.
|
|
4208
|
+
if (this._audioDataHolder) {
|
|
3241
4209
|
let framePosRound = this.viewPortXPixelToFramePosition(xViewPortPixelpos);
|
|
3242
4210
|
if (framePosRound != null) {
|
|
3243
4211
|
g.font = '14px sans-serif';
|
|
@@ -3501,11 +4469,21 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3501
4469
|
}
|
|
3502
4470
|
GaussianWindow.DEFAULT_SIGMA = 0.3;
|
|
3503
4471
|
self.onmessage = function (msg) {
|
|
4472
|
+
//console.debug("Sonagram render thread");
|
|
3504
4473
|
let l = msg.data.l;
|
|
3505
4474
|
let w = msg.data.w;
|
|
3506
4475
|
let h = msg.data.h;
|
|
3507
4476
|
let vw = msg.data.vw;
|
|
3508
4477
|
let chs = msg.data.chs;
|
|
4478
|
+
let audioDataOffset = 0;
|
|
4479
|
+
let adOffset = msg.data.audioDataOffset;
|
|
4480
|
+
if (adOffset) {
|
|
4481
|
+
audioDataOffset = adOffset;
|
|
4482
|
+
}
|
|
4483
|
+
let maxPsd = null;
|
|
4484
|
+
if (msg.data.maxPsd !== undefined) {
|
|
4485
|
+
maxPsd = msg.data.maxPsd;
|
|
4486
|
+
}
|
|
3509
4487
|
let audioData = new Array(chs);
|
|
3510
4488
|
for (let ch = 0; ch < chs; ch++) {
|
|
3511
4489
|
audioData[ch] = new Float32Array(msg.data['audioData'][ch]);
|
|
@@ -3521,16 +4499,17 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3521
4499
|
}
|
|
3522
4500
|
let imgData = new Uint8ClampedArray(arrSize);
|
|
3523
4501
|
//console.log("Render method:");
|
|
3524
|
-
|
|
4502
|
+
//console.debug("Created imgData arrSize: "+arrSize+" ", w, "x", h);
|
|
4503
|
+
let calcMaxPsd = -Infinity;
|
|
4504
|
+
if (arrSize > 0) {
|
|
3525
4505
|
let chH = Math.round(h / chs);
|
|
3526
4506
|
let framesPerPixel = frameLength / vw;
|
|
3527
|
-
//console.
|
|
4507
|
+
//console.debug("Render: ", w, "x", h);
|
|
3528
4508
|
let b = new Float32Array(dftSize);
|
|
3529
4509
|
let sona = new Array(chs);
|
|
3530
|
-
let
|
|
3531
|
-
let p = 0;
|
|
4510
|
+
//let p = 0;
|
|
3532
4511
|
for (let ch = 0; ch < chs; ch++) {
|
|
3533
|
-
p = ch * frameLength;
|
|
4512
|
+
//p = ch * frameLength;
|
|
3534
4513
|
let chDataLen = audioData[ch].length;
|
|
3535
4514
|
let x = 0;
|
|
3536
4515
|
// initialize DFT array buffer
|
|
@@ -3547,8 +4526,13 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3547
4526
|
// initialize for negative sample positions and out of bounds positions
|
|
3548
4527
|
let chDat = 0;
|
|
3549
4528
|
// Set audio sample if available
|
|
3550
|
-
|
|
3551
|
-
|
|
4529
|
+
let adp = samplePos - audioDataOffset;
|
|
4530
|
+
if (adp >= 0 && adp < chDataLen) {
|
|
4531
|
+
chDat = audioData[ch][adp];
|
|
4532
|
+
//console.debug("Audio data: "+chDat);
|
|
4533
|
+
}
|
|
4534
|
+
else {
|
|
4535
|
+
//console.debug("Sample buf pos oob: adp: "+adp+", chDataLen: "+chDataLen+", samplePos: "+samplePos+", i: "+i);
|
|
3552
4536
|
}
|
|
3553
4537
|
// apply Window
|
|
3554
4538
|
b[i] = chDat * wf.getScale(i);
|
|
@@ -3558,63 +4542,78 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3558
4542
|
// Get maximum value of spectral energy
|
|
3559
4543
|
for (let s = 0; s < dftBands; s++) {
|
|
3560
4544
|
let psd = (2 * Math.pow(spectr[s], 2)) / dftBands;
|
|
3561
|
-
if (psd >
|
|
3562
|
-
|
|
4545
|
+
if (psd > calcMaxPsd) {
|
|
4546
|
+
calcMaxPsd = psd;
|
|
3563
4547
|
}
|
|
3564
4548
|
}
|
|
3565
4549
|
// Set render model data for this pixel
|
|
3566
4550
|
sona[ch][pii] = spectr;
|
|
3567
4551
|
}
|
|
3568
4552
|
}
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
scaledVal =
|
|
3589
|
-
|
|
3590
|
-
scaledVal
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
rgbVal =
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
|
|
3602
|
-
|
|
4553
|
+
if (!msg.data.norender) {
|
|
4554
|
+
if (!maxPsd) {
|
|
4555
|
+
maxPsd = calcMaxPsd;
|
|
4556
|
+
}
|
|
4557
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4558
|
+
for (let pii = 0; pii < w; pii++) {
|
|
4559
|
+
let allBlack = true;
|
|
4560
|
+
for (let y = 0; y < chH; y++) {
|
|
4561
|
+
let freqIdx = Math.round(y * dftBands / chH);
|
|
4562
|
+
// calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
4563
|
+
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
4564
|
+
let val = sona[ch][pii][freqIdx];
|
|
4565
|
+
let psd = (2 * Math.pow(val, 2)) / dftBands;
|
|
4566
|
+
// Calculate logarithmic value
|
|
4567
|
+
//let psdLog = ips.dsp.DSPUtils.toLevelInDB(psd / maxPsd);
|
|
4568
|
+
let linearLevel = psd / maxPsd;
|
|
4569
|
+
let psdLog = 10 * Math.log(linearLevel) / Math.log(10);
|
|
4570
|
+
// Fixed dynamic Range value of 70dB for now
|
|
4571
|
+
let dynRangeInDb = 70;
|
|
4572
|
+
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
4573
|
+
// are the following checks necessary for clamped array ?
|
|
4574
|
+
if (scaledVal > 1.0)
|
|
4575
|
+
scaledVal = 1;
|
|
4576
|
+
if (scaledVal < 0.0) {
|
|
4577
|
+
scaledVal = 0;
|
|
4578
|
+
}
|
|
4579
|
+
let rgbVal = Math.round(255 * scaledVal);
|
|
4580
|
+
if (rgbVal < 0) {
|
|
4581
|
+
// System.out.println("Neg RGB val: "+rgbVal);
|
|
4582
|
+
rgbVal = 0;
|
|
4583
|
+
}
|
|
4584
|
+
if (rgbVal > 255) {
|
|
4585
|
+
rgbVal = 255;
|
|
4586
|
+
}
|
|
4587
|
+
rgbVal = 255 - rgbVal;
|
|
4588
|
+
if (rgbVal > 0) {
|
|
4589
|
+
allBlack = false;
|
|
4590
|
+
}
|
|
4591
|
+
let py = chH - y;
|
|
4592
|
+
let dataPos = ((((ch * chH) + py) * w) + pii) * 4;
|
|
4593
|
+
imgData[dataPos + 0] = rgbVal; //R
|
|
4594
|
+
imgData[dataPos + 1] = rgbVal; //G
|
|
4595
|
+
imgData[dataPos + 2] = rgbVal; //B
|
|
4596
|
+
imgData[dataPos + 3] = 255; //A (alpha: fully opaque)
|
|
4597
|
+
//console.debug("Rendered: py: "+py+", rgbval: "+rgbVal);
|
|
4598
|
+
// example 1x1, 2chs
|
|
4599
|
+
// ch0x0y0R,ch0x0y0G,ch0x0y0B,ch0x0y0A,
|
|
4600
|
+
// ch0x1y0R,ch0x1y0G,ch0x1y0B,ch0x1y0A,
|
|
4601
|
+
// ch0x0y0R,ch0x0y0G,ch0x0y0B,ch0x0y0A,
|
|
4602
|
+
// ch0x1y1R,ch0x1y1G,ch0x1y1B,ch0x1y1A,
|
|
4603
|
+
// ch1x0y0R,ch1x0y0G,ch1x0y0B,ch1x0y0A,
|
|
4604
|
+
// ch1x1y0R,ch1x1y0G,ch1x1y0B,ch1x1y0A,
|
|
4605
|
+
// ch1x0y0R,ch1x0y0G,ch1x0y0B,ch1x0y0A,
|
|
4606
|
+
// ch1x1y1R,ch1x1y1G,ch1x1y1B,ch1x1y1A
|
|
3603
4607
|
}
|
|
3604
|
-
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
imgData[dataPos + 1] = rgbVal; //G
|
|
3608
|
-
imgData[dataPos + 2] = rgbVal; //B
|
|
3609
|
-
imgData[dataPos + 3] = 255; //A (alpha: fully opaque)
|
|
4608
|
+
// if (allBlack) {
|
|
4609
|
+
// console.log("Black: ", pii, " ", ch);
|
|
4610
|
+
// }
|
|
3610
4611
|
}
|
|
3611
|
-
// if (allBlack) {
|
|
3612
|
-
// console.log("Black: ", pii, " ", ch);
|
|
3613
|
-
// }
|
|
3614
4612
|
}
|
|
3615
4613
|
}
|
|
3616
4614
|
}
|
|
3617
|
-
|
|
4615
|
+
//console.debug("Render thread post message imgData: "+imgData.length)
|
|
4616
|
+
postMessage({ imgData: imgData, l: l, w: msg.data.w, h: msg.data.h, vw: vw, maxPsd: calcMaxPsd, terminate: msg.data.terminate }, [imgData.buffer]);
|
|
3618
4617
|
};
|
|
3619
4618
|
}
|
|
3620
4619
|
startDraw(clear = true) {
|
|
@@ -3644,42 +4643,190 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3644
4643
|
if (this.bounds) {
|
|
3645
4644
|
let w = Math.round(this.bounds.dimension.width);
|
|
3646
4645
|
let h = Math.round(this.bounds.dimension.height);
|
|
3647
|
-
if (this.
|
|
4646
|
+
if (this._audioDataHolder && w > 0 && h > 0) {
|
|
3648
4647
|
this.worker = new Worker(this.workerURL);
|
|
3649
4648
|
//this.wo = new Worker('./worker/sonagram.worker', { type: `module` });
|
|
3650
|
-
let chs = this.
|
|
3651
|
-
let
|
|
3652
|
-
let
|
|
3653
|
-
|
|
3654
|
-
|
|
3655
|
-
|
|
3656
|
-
|
|
3657
|
-
let
|
|
4649
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
4650
|
+
let vw = Math.round(this.virtualDimension.width);
|
|
4651
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
4652
|
+
let framesPerPixel = Math.ceil(frameLength / vw);
|
|
4653
|
+
let leftPos = Math.round(this.bounds.position.left);
|
|
4654
|
+
let renderPos = leftPos;
|
|
4655
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
4656
|
+
//let arrayAudioBuffer=this._audioDataHolder.arrayBuffer;
|
|
4657
|
+
let arrAbBuf;
|
|
4658
|
+
let imgData;
|
|
4659
|
+
let maxPsd = -Infinity;
|
|
4660
|
+
let norender = true;
|
|
3658
4661
|
if (this.worker) {
|
|
3659
4662
|
this.worker.onmessage = (me) => {
|
|
3660
|
-
|
|
3661
|
-
|
|
3662
|
-
|
|
4663
|
+
if (true === me.data.terminate) {
|
|
4664
|
+
let drawImgData;
|
|
4665
|
+
if (imgData) {
|
|
4666
|
+
drawImgData = imgData;
|
|
4667
|
+
}
|
|
4668
|
+
else {
|
|
4669
|
+
drawImgData = me.data.imgData;
|
|
4670
|
+
}
|
|
4671
|
+
this.drawRendered(w, h, drawImgData);
|
|
4672
|
+
if (this.worker) {
|
|
4673
|
+
this.worker.terminate();
|
|
4674
|
+
}
|
|
4675
|
+
this.worker = null;
|
|
4676
|
+
}
|
|
4677
|
+
else {
|
|
4678
|
+
// set rendered vertical values of one pixel of timescale
|
|
4679
|
+
//let dataPos = renderPos * h * 4;
|
|
4680
|
+
if (norender) {
|
|
4681
|
+
if (me.data.maxPsd > maxPsd) {
|
|
4682
|
+
maxPsd = me.data.maxPsd;
|
|
4683
|
+
//console.debug("new maxPsd: "+maxPsd);
|
|
4684
|
+
}
|
|
4685
|
+
}
|
|
4686
|
+
else {
|
|
4687
|
+
let chH = Math.round(h / chs);
|
|
4688
|
+
let idp = me.data.l - leftPos;
|
|
4689
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4690
|
+
for (let y = 0; y < chH; y++) {
|
|
4691
|
+
let py = chH - y;
|
|
4692
|
+
let dataPos = ((((ch * chH) + py) * w) + idp) * 4;
|
|
4693
|
+
let mePos = ((ch * chH) + py) * 4;
|
|
4694
|
+
//let lastPos = dataPos + me.data.imgData.length;
|
|
4695
|
+
//if (lastPos < imgData.length) {
|
|
4696
|
+
// set one pixel
|
|
4697
|
+
imgData[dataPos] = me.data.imgData[mePos];
|
|
4698
|
+
imgData[dataPos + 1] = me.data.imgData[mePos + 1];
|
|
4699
|
+
imgData[dataPos + 2] = me.data.imgData[mePos + 2];
|
|
4700
|
+
imgData[dataPos + 3] = me.data.imgData[mePos + 3];
|
|
4701
|
+
//} else {
|
|
4702
|
+
//console.error("Out of range: " + dataPos + "+" + me.data.imgData.length + ">=" + imgData.length);
|
|
4703
|
+
// }
|
|
4704
|
+
}
|
|
4705
|
+
}
|
|
4706
|
+
}
|
|
4707
|
+
if (this._audioDataHolder && arrAbBuf && this.worker) {
|
|
4708
|
+
// proceed with next pixel
|
|
4709
|
+
renderPos++;
|
|
4710
|
+
//console.debug("Render pos: "+renderPos);
|
|
4711
|
+
let terminate = false;
|
|
4712
|
+
let windowEnd = renderPos >= leftPos + w;
|
|
4713
|
+
if (windowEnd) {
|
|
4714
|
+
if (norender) {
|
|
4715
|
+
// phase two: rendering
|
|
4716
|
+
norender = false;
|
|
4717
|
+
// start from beginning
|
|
4718
|
+
renderPos = leftPos;
|
|
4719
|
+
//console.debug("now rendering: maxPsd: "+maxPsd);
|
|
4720
|
+
}
|
|
4721
|
+
else {
|
|
4722
|
+
// terminate render phase
|
|
4723
|
+
terminate = true;
|
|
4724
|
+
}
|
|
4725
|
+
}
|
|
4726
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw) - this.dftSize / 2;
|
|
4727
|
+
if (leftFramePos < 0) {
|
|
4728
|
+
leftFramePos = 0;
|
|
4729
|
+
}
|
|
4730
|
+
let ada = new Array(chs);
|
|
4731
|
+
//console.debug("Render pos: "+renderPos+" leftFramePos: "+leftFramePos);
|
|
4732
|
+
if (!terminate) {
|
|
4733
|
+
if (this._audioDataHolder) {
|
|
4734
|
+
let read = this._audioDataHolder.frames(leftFramePos, this.dftSize, arrAbBuf);
|
|
4735
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4736
|
+
// Need a copy here for the worker, otherwise this.audioData is not accessible after posting to the worker
|
|
4737
|
+
ada[ch] = arrAbBuf[ch].buffer.slice(0);
|
|
4738
|
+
}
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
else {
|
|
4742
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4743
|
+
ada[ch] = new ArrayBuffer(0);
|
|
4744
|
+
}
|
|
4745
|
+
}
|
|
4746
|
+
this.worker.postMessage({
|
|
4747
|
+
audioData: ada,
|
|
4748
|
+
audioDataOffset: leftFramePos,
|
|
4749
|
+
l: renderPos,
|
|
4750
|
+
w: me.data.w,
|
|
4751
|
+
h: h,
|
|
4752
|
+
vw: vw,
|
|
4753
|
+
chs: chs,
|
|
4754
|
+
frameLength: frameLength,
|
|
4755
|
+
dftSize: this.dftSize,
|
|
4756
|
+
maxPsd: maxPsd,
|
|
4757
|
+
norender: norender,
|
|
4758
|
+
terminate: terminate
|
|
4759
|
+
}, ada);
|
|
4760
|
+
}
|
|
3663
4761
|
}
|
|
3664
|
-
this.worker = null;
|
|
3665
4762
|
};
|
|
3666
4763
|
}
|
|
3667
|
-
if (
|
|
3668
|
-
let
|
|
3669
|
-
|
|
3670
|
-
|
|
4764
|
+
if (audioBuffer && audioBuffer.length * audioBuffer.numberOfChannels < AudioCanvasLayerComponent.ENABLE_STREAMING_NUMBER_OF_SAMPLES_THRESHOLD) {
|
|
4765
|
+
let ada = new Array(chs);
|
|
4766
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4767
|
+
// Need a copy here for the worker, otherwise this.audioData is not accessible after posting to the worker
|
|
4768
|
+
ada[ch] = audioBuffer.getChannelData(ch).buffer.slice(0);
|
|
4769
|
+
}
|
|
4770
|
+
let start = Date.now();
|
|
4771
|
+
if (this.markerCanvas) {
|
|
4772
|
+
let g = this.markerCanvas.getContext("2d");
|
|
4773
|
+
if (g) {
|
|
4774
|
+
g.fillText("Rendering...", 10, 20);
|
|
4775
|
+
}
|
|
4776
|
+
}
|
|
4777
|
+
this.worker.postMessage({
|
|
4778
|
+
audioData: ada,
|
|
4779
|
+
l: leftPos,
|
|
4780
|
+
w: w,
|
|
4781
|
+
h: h,
|
|
4782
|
+
vw: Math.round(this.virtualDimension.width),
|
|
4783
|
+
chs: chs,
|
|
4784
|
+
frameLength: frameLength,
|
|
4785
|
+
dftSize: this.dftSize,
|
|
4786
|
+
terminate: true
|
|
4787
|
+
}, ada);
|
|
4788
|
+
}
|
|
4789
|
+
else {
|
|
4790
|
+
if (w > 0) {
|
|
4791
|
+
if (framesPerPixel > 0) {
|
|
4792
|
+
let arrSize = w * h * 4;
|
|
4793
|
+
if (arrSize < 0) {
|
|
4794
|
+
arrSize = 0;
|
|
4795
|
+
}
|
|
4796
|
+
imgData = new Uint8ClampedArray(arrSize);
|
|
4797
|
+
let rw = 1;
|
|
4798
|
+
//ais = new ArrayAudioBufferInputStream(arrayAudioBuffer);
|
|
4799
|
+
arrAbBuf = new Array(chs);
|
|
4800
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4801
|
+
arrAbBuf[ch] = new Float32Array(this.dftSize);
|
|
4802
|
+
}
|
|
4803
|
+
let leftFramePos = Math.floor(frameLength * renderPos / vw) - this.dftSize / 2;
|
|
4804
|
+
let framesToRead = this.dftSize;
|
|
4805
|
+
if (leftFramePos < 0) {
|
|
4806
|
+
//framesToRead=this.dftSize+leftFramePos;
|
|
4807
|
+
leftFramePos = 0;
|
|
4808
|
+
}
|
|
4809
|
+
let read = this._audioDataHolder.frames(leftFramePos, framesToRead, arrAbBuf);
|
|
4810
|
+
let ad = new Float32Array(chs * framesToRead);
|
|
4811
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4812
|
+
ad.set(arrAbBuf[ch], ch * framesToRead);
|
|
4813
|
+
}
|
|
4814
|
+
this.worker.postMessage({
|
|
4815
|
+
l: renderPos,
|
|
4816
|
+
w: rw,
|
|
4817
|
+
h: h,
|
|
4818
|
+
vw: vw,
|
|
4819
|
+
chs: chs,
|
|
4820
|
+
frameLength: frameLength,
|
|
4821
|
+
audioData: ad,
|
|
4822
|
+
audioDataOffset: leftFramePos,
|
|
4823
|
+
dftSize: this.dftSize,
|
|
4824
|
+
norender: norender,
|
|
4825
|
+
terminate: false
|
|
4826
|
+
}, [ad.buffer]);
|
|
4827
|
+
}
|
|
3671
4828
|
}
|
|
3672
4829
|
}
|
|
3673
|
-
this.worker.postMessage({
|
|
3674
|
-
audioData: ada,
|
|
3675
|
-
l: Math.round(this.bounds.position.left),
|
|
3676
|
-
w: w,
|
|
3677
|
-
h: h,
|
|
3678
|
-
vw: Math.round(this.virtualDimension.width),
|
|
3679
|
-
chs: chs,
|
|
3680
|
-
frameLength: frameLength,
|
|
3681
|
-
dftSize: this.dftSize
|
|
3682
|
-
}, ada);
|
|
3683
4830
|
}
|
|
3684
4831
|
else {
|
|
3685
4832
|
let g = this.sonagramCanvas.getContext("2d");
|
|
@@ -3689,17 +4836,17 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3689
4836
|
}
|
|
3690
4837
|
}
|
|
3691
4838
|
}
|
|
3692
|
-
drawRendered(
|
|
4839
|
+
drawRendered(w, h, imgData) {
|
|
3693
4840
|
if (this.sonagramCanvas) {
|
|
3694
|
-
this.sonagramCanvas.width =
|
|
3695
|
-
this.sonagramCanvas.height =
|
|
4841
|
+
this.sonagramCanvas.width = w;
|
|
4842
|
+
this.sonagramCanvas.height = h;
|
|
3696
4843
|
let g = this.sonagramCanvas.getContext("2d");
|
|
3697
4844
|
if (g) {
|
|
3698
|
-
let imgDataArr =
|
|
3699
|
-
if (
|
|
3700
|
-
let
|
|
3701
|
-
|
|
3702
|
-
g.putImageData(
|
|
4845
|
+
let imgDataArr = imgData;
|
|
4846
|
+
if (w > 0 && h > 0) {
|
|
4847
|
+
let gImgData = g.createImageData(w, h);
|
|
4848
|
+
gImgData.data.set(imgDataArr);
|
|
4849
|
+
g.putImageData(gImgData, 0, 0);
|
|
3703
4850
|
}
|
|
3704
4851
|
}
|
|
3705
4852
|
}
|
|
@@ -3715,91 +4862,95 @@ class Sonagram extends AudioCanvasLayerComponent {
|
|
|
3715
4862
|
g.clearRect(0, 0, w, h);
|
|
3716
4863
|
g.fillStyle = "white";
|
|
3717
4864
|
g.fillRect(0, 0, w, h);
|
|
3718
|
-
if (this.
|
|
4865
|
+
if (this._audioDataHolder) {
|
|
3719
4866
|
let spectSize = Math.floor(this.dftSize / 2);
|
|
3720
|
-
let chs = this.
|
|
4867
|
+
let chs = this._audioDataHolder.numberOfChannels;
|
|
3721
4868
|
let chH = h / chs;
|
|
3722
|
-
let frameLength = this.
|
|
4869
|
+
let frameLength = this._audioDataHolder.frameLen;
|
|
3723
4870
|
let framesPerPixel = frameLength / w;
|
|
3724
4871
|
let y = 0;
|
|
3725
|
-
|
|
3726
|
-
let
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
|
|
3730
|
-
|
|
3731
|
-
let
|
|
3732
|
-
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
framePos =
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
sona[ch][pii] = spectr;
|
|
3745
|
-
// @ts-ignore
|
|
3746
|
-
let pMax = Math.max.apply(null, spectr);
|
|
3747
|
-
if (pMax > max) {
|
|
3748
|
-
max = pMax;
|
|
3749
|
-
}
|
|
3750
|
-
for (let s = 0; s < spectSize; s++) {
|
|
3751
|
-
let psd = (2 * Math.pow(spectr[s], 2)) / spectSize;
|
|
3752
|
-
if (psd > maxPsd) {
|
|
3753
|
-
maxPsd = psd;
|
|
4872
|
+
let audioBuffer = this._audioDataHolder.buffer;
|
|
4873
|
+
let arrayAudioBuffer = this._audioDataHolder.arrayBuffer;
|
|
4874
|
+
if (audioBuffer) {
|
|
4875
|
+
let b = new Float32Array(this.dftSize);
|
|
4876
|
+
let sona = new Array(chs);
|
|
4877
|
+
let max = 0;
|
|
4878
|
+
let maxPsd = -Infinity;
|
|
4879
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4880
|
+
let x = 0;
|
|
4881
|
+
sona[ch] = new Array(w);
|
|
4882
|
+
let chData = audioBuffer.getChannelData(ch);
|
|
4883
|
+
// TODO center buffer
|
|
4884
|
+
let framePos = 0;
|
|
4885
|
+
for (let pii = 0; pii < w; pii++) {
|
|
4886
|
+
framePos = Math.round(pii * framesPerPixel);
|
|
4887
|
+
// calculate DFT at pixel position
|
|
4888
|
+
for (let i = 0; i < this.dftSize; i++) {
|
|
4889
|
+
let chDat = chData[framePos + i];
|
|
4890
|
+
b[i] = chDat;
|
|
3754
4891
|
}
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
3758
|
-
|
|
3759
|
-
|
|
3760
|
-
|
|
3761
|
-
let framePos = 0;
|
|
3762
|
-
for (let pii = 0; pii < w; pii++) {
|
|
3763
|
-
framePos = pii * framesPerPixel;
|
|
3764
|
-
for (let y = 0; y < h; y++) {
|
|
3765
|
-
let freqIdx = Math.round(y * spectSize / h);
|
|
3766
|
-
// calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
3767
|
-
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
3768
|
-
let val = sona[ch][pii][freqIdx];
|
|
3769
|
-
let psd = (2 * Math.pow(val, 2)) / spectSize;
|
|
3770
|
-
// Calculate logarithmic
|
|
3771
|
-
let psdLog = DSPUtils.toLevelInDB(psd / maxPsd);
|
|
3772
|
-
let dynRangeInDb = 70;
|
|
3773
|
-
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
3774
|
-
if (scaledVal > 1)
|
|
3775
|
-
scaledVal = 1;
|
|
3776
|
-
if (scaledVal < 0) {
|
|
3777
|
-
scaledVal = 0;
|
|
4892
|
+
let spectr = this.dft.processRealMagnitude(b);
|
|
4893
|
+
sona[ch][pii] = spectr;
|
|
4894
|
+
// @ts-ignore
|
|
4895
|
+
let pMax = Math.max.apply(null, spectr);
|
|
4896
|
+
if (pMax > max) {
|
|
4897
|
+
max = pMax;
|
|
3778
4898
|
}
|
|
3779
|
-
let
|
|
3780
|
-
|
|
3781
|
-
|
|
3782
|
-
|
|
4899
|
+
for (let s = 0; s < spectSize; s++) {
|
|
4900
|
+
let psd = (2 * Math.pow(spectr[s], 2)) / spectSize;
|
|
4901
|
+
if (psd > maxPsd) {
|
|
4902
|
+
maxPsd = psd;
|
|
4903
|
+
}
|
|
3783
4904
|
}
|
|
3784
|
-
|
|
3785
|
-
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
//console.log("max: ", max);
|
|
4908
|
+
maxPsd = (2 * Math.pow(max, 2)) / spectSize;
|
|
4909
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
4910
|
+
let framePos = 0;
|
|
4911
|
+
for (let pii = 0; pii < w; pii++) {
|
|
4912
|
+
framePos = pii * framesPerPixel;
|
|
4913
|
+
for (let y = 0; y < h; y++) {
|
|
4914
|
+
let freqIdx = Math.round(y * spectSize / h);
|
|
4915
|
+
// calculate the one sided power spectral density PSD (f, t) in Pa2/Hz
|
|
4916
|
+
// PSD(f) proportional to 2|X(f)|2 / (t2 - t1)
|
|
4917
|
+
let val = sona[ch][pii][freqIdx];
|
|
4918
|
+
let psd = (2 * Math.pow(val, 2)) / spectSize;
|
|
4919
|
+
// Calculate logarithmic
|
|
4920
|
+
let psdLog = DSPUtils.toLevelInDB(psd / maxPsd);
|
|
4921
|
+
let dynRangeInDb = 70;
|
|
4922
|
+
let scaledVal = (psdLog + dynRangeInDb) / dynRangeInDb;
|
|
4923
|
+
if (scaledVal > 1)
|
|
4924
|
+
scaledVal = 1;
|
|
4925
|
+
if (scaledVal < 0) {
|
|
4926
|
+
scaledVal = 0;
|
|
4927
|
+
}
|
|
4928
|
+
let rgbVal = (255 * scaledVal);
|
|
4929
|
+
if (rgbVal < 0) {
|
|
4930
|
+
// System.out.println("Neg RGB val: "+rgbVal);
|
|
4931
|
+
rgbVal = 0;
|
|
4932
|
+
}
|
|
4933
|
+
if (rgbVal > 255) {
|
|
4934
|
+
rgbVal = 255;
|
|
4935
|
+
}
|
|
4936
|
+
rgbVal = 255 - rgbVal;
|
|
4937
|
+
let colorStr = CSSUtils.toColorString(rgbVal, rgbVal, rgbVal);
|
|
4938
|
+
g.fillStyle = colorStr;
|
|
4939
|
+
g.fillRect(pii, chH - y, 1, 1);
|
|
3786
4940
|
}
|
|
3787
|
-
rgbVal = 255 - rgbVal;
|
|
3788
|
-
let colorStr = CSSUtils.toColorString(rgbVal, rgbVal, rgbVal);
|
|
3789
|
-
g.fillStyle = colorStr;
|
|
3790
|
-
g.fillRect(pii, chH - y, 1, 1);
|
|
3791
4941
|
}
|
|
3792
4942
|
}
|
|
4943
|
+
this.drawPlayPosition();
|
|
4944
|
+
}
|
|
4945
|
+
else if (arrayAudioBuffer) {
|
|
4946
|
+
throw Error("Redraw with array audio buffer not supported.");
|
|
3793
4947
|
}
|
|
3794
|
-
this.drawPlayPosition();
|
|
3795
4948
|
}
|
|
3796
4949
|
}
|
|
3797
4950
|
}
|
|
3798
4951
|
setData(audioData) {
|
|
3799
|
-
this.
|
|
4952
|
+
this._audioDataHolder = audioData;
|
|
3800
4953
|
this.playFramePosition = 0;
|
|
3801
|
-
//this.redraw();
|
|
3802
|
-
//this.startRender();
|
|
3803
4954
|
}
|
|
3804
4955
|
}
|
|
3805
4956
|
Sonagram.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: Sonagram, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
@@ -4024,13 +5175,13 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4024
5175
|
}
|
|
4025
5176
|
currentXZoom() {
|
|
4026
5177
|
let xz = this._xZoom;
|
|
4027
|
-
if (xz == null && this.
|
|
5178
|
+
if (xz == null && this._audioDataHolder) {
|
|
4028
5179
|
let ow = this.ce.offsetWidth;
|
|
4029
5180
|
if (ow < 1) {
|
|
4030
5181
|
// at least one pixel width to avoid x-zoom zero values
|
|
4031
5182
|
ow = 1;
|
|
4032
5183
|
}
|
|
4033
|
-
xz = ow / this.
|
|
5184
|
+
xz = ow / this._audioDataHolder.duration;
|
|
4034
5185
|
}
|
|
4035
5186
|
return xz;
|
|
4036
5187
|
}
|
|
@@ -4109,9 +5260,10 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4109
5260
|
this._layout(false, false);
|
|
4110
5261
|
}
|
|
4111
5262
|
layout(clear = true) {
|
|
5263
|
+
var _a;
|
|
4112
5264
|
if (this.ce && this.dc) {
|
|
4113
5265
|
const clientW = this.ce.clientWidth;
|
|
4114
|
-
if (this.
|
|
5266
|
+
if (this._audioDataHolder) {
|
|
4115
5267
|
if (this._fixFitToPanel) {
|
|
4116
5268
|
// Set the virtual canvas width to the visible width
|
|
4117
5269
|
if (this.ce.style.width != '100%') {
|
|
@@ -4122,7 +5274,7 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4122
5274
|
else {
|
|
4123
5275
|
if (this._xZoom) {
|
|
4124
5276
|
// Set the virtual canvas width according to the value of the user selected xZoom value
|
|
4125
|
-
const newClW = Math.round(this._xZoom * this.
|
|
5277
|
+
const newClW = Math.round(this._xZoom * ((_a = this._audioDataHolder) === null || _a === void 0 ? void 0 : _a.duration));
|
|
4126
5278
|
this.ce.style.width = newClW + 'px';
|
|
4127
5279
|
}
|
|
4128
5280
|
else {
|
|
@@ -4134,22 +5286,22 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4134
5286
|
this._layout(clear, true);
|
|
4135
5287
|
}
|
|
4136
5288
|
}
|
|
4137
|
-
set audioData(
|
|
5289
|
+
set audioData(audioDataHolder) {
|
|
4138
5290
|
this._audioClip = null;
|
|
4139
|
-
this.
|
|
4140
|
-
this.as.setData(
|
|
4141
|
-
this.so.setData(
|
|
5291
|
+
this._audioDataHolder = audioDataHolder;
|
|
5292
|
+
this.as.setData(audioDataHolder);
|
|
5293
|
+
this.so.setData(audioDataHolder);
|
|
4142
5294
|
this.layout();
|
|
4143
5295
|
}
|
|
4144
5296
|
get audioData() {
|
|
4145
|
-
return this.
|
|
5297
|
+
return this._audioDataHolder;
|
|
4146
5298
|
}
|
|
4147
5299
|
set audioClip(audioClip) {
|
|
4148
5300
|
this._audioClip = audioClip;
|
|
4149
5301
|
let audioData = null;
|
|
4150
5302
|
let sel = null;
|
|
4151
5303
|
if (audioClip) {
|
|
4152
|
-
audioData = audioClip.
|
|
5304
|
+
audioData = audioClip.audioDataHolder;
|
|
4153
5305
|
if (this._audioClip) {
|
|
4154
5306
|
this._audioClip.addSelectionObserver((clip) => {
|
|
4155
5307
|
this.selection = clip.selection;
|
|
@@ -4157,9 +5309,9 @@ class AudioClipUIContainer extends BasicAudioCanvasLayerComponent {
|
|
|
4157
5309
|
}
|
|
4158
5310
|
sel = audioClip.selection;
|
|
4159
5311
|
}
|
|
4160
|
-
this.
|
|
4161
|
-
this.as.setData(this.
|
|
4162
|
-
this.so.setData(this.
|
|
5312
|
+
this._audioDataHolder = audioData;
|
|
5313
|
+
this.as.setData(this._audioDataHolder);
|
|
5314
|
+
this.so.setData(this._audioDataHolder);
|
|
4163
5315
|
this.selecting = null;
|
|
4164
5316
|
this.selection = sel;
|
|
4165
5317
|
this.layout();
|
|
@@ -4351,7 +5503,7 @@ class AudioDisplayScrollPane {
|
|
|
4351
5503
|
let audioData = null;
|
|
4352
5504
|
let sel = null;
|
|
4353
5505
|
if (audioClip) {
|
|
4354
|
-
audioData = audioClip.
|
|
5506
|
+
audioData = audioClip.audioDataHolder;
|
|
4355
5507
|
sel = audioClip.selection;
|
|
4356
5508
|
audioClip.addSelectionObserver((clip) => {
|
|
4357
5509
|
this.zoomSelectedAction.disabled = (clip.selection == null);
|
|
@@ -4622,17 +5774,17 @@ class AudioDisplay {
|
|
|
4622
5774
|
console.log("Play started");
|
|
4623
5775
|
this.status = 'Playing...';
|
|
4624
5776
|
}
|
|
4625
|
-
set audioData(
|
|
4626
|
-
this.audioDisplayScrollPane.audioData =
|
|
5777
|
+
set audioData(audioData) {
|
|
5778
|
+
this.audioDisplayScrollPane.audioData = audioData;
|
|
4627
5779
|
if (this.playStartAction) {
|
|
4628
|
-
this.playStartAction.disabled = (
|
|
5780
|
+
this.playStartAction.disabled = (audioData == null);
|
|
4629
5781
|
}
|
|
4630
5782
|
}
|
|
4631
5783
|
set audioClip(audioClip) {
|
|
4632
5784
|
let audioData = null;
|
|
4633
5785
|
let sel = null;
|
|
4634
5786
|
if (audioClip) {
|
|
4635
|
-
audioData = audioClip.buffer;
|
|
5787
|
+
audioData = audioClip.audioDataHolder.buffer;
|
|
4636
5788
|
sel = audioClip.selection;
|
|
4637
5789
|
}
|
|
4638
5790
|
this._audioClip = audioClip;
|
|
@@ -4745,7 +5897,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
4745
5897
|
|
|
4746
5898
|
class Progress {
|
|
4747
5899
|
constructor() {
|
|
4748
|
-
this.items =
|
|
5900
|
+
this.items = undefined;
|
|
4749
5901
|
this.selectedItemIdx = 0;
|
|
4750
5902
|
this.enableDownload = false;
|
|
4751
5903
|
this.onRowSelect = new EventEmitter();
|
|
@@ -5485,7 +6637,7 @@ class Prompting {
|
|
|
5485
6637
|
constructor() {
|
|
5486
6638
|
this.promptItem = null;
|
|
5487
6639
|
this.showPrompt = false;
|
|
5488
|
-
this.items =
|
|
6640
|
+
this.items = undefined;
|
|
5489
6641
|
this.enableDownload = false;
|
|
5490
6642
|
this.audioSignalCollapsed = true;
|
|
5491
6643
|
this.displayAudioClip = null;
|
|
@@ -5800,6 +6952,7 @@ class LevelBar {
|
|
|
5800
6952
|
this._streamingMode = false;
|
|
5801
6953
|
this._staticLevelInfos = null;
|
|
5802
6954
|
this._playFramePosition = null;
|
|
6955
|
+
this._stateLoading = false;
|
|
5803
6956
|
this.warnDBLevel = DEFAULT_WARN_DB_LEVEL$1;
|
|
5804
6957
|
this.dbValues = new Array();
|
|
5805
6958
|
}
|
|
@@ -5833,17 +6986,22 @@ class LevelBar {
|
|
|
5833
6986
|
}
|
|
5834
6987
|
}
|
|
5835
6988
|
set displayLevelInfos(levelInfos) {
|
|
5836
|
-
this._staticLevelInfos = levelInfos;
|
|
5837
6989
|
if (levelInfos) {
|
|
6990
|
+
this._staticLevelInfos = levelInfos;
|
|
5838
6991
|
this.dbValues = levelInfos.bufferLevelInfos.map((li) => {
|
|
5839
6992
|
return li.powerLevelsDB();
|
|
5840
6993
|
});
|
|
5841
6994
|
}
|
|
5842
6995
|
else {
|
|
6996
|
+
this._staticLevelInfos = null;
|
|
5843
6997
|
this.dbValues = new Array();
|
|
5844
6998
|
}
|
|
5845
6999
|
this.layoutStatic();
|
|
5846
7000
|
}
|
|
7001
|
+
set stateLoading(loading) {
|
|
7002
|
+
this._stateLoading = loading;
|
|
7003
|
+
this.layoutStatic();
|
|
7004
|
+
}
|
|
5847
7005
|
set channelCount(channelCount) {
|
|
5848
7006
|
this.reset();
|
|
5849
7007
|
}
|
|
@@ -6024,6 +7182,12 @@ class LevelBar {
|
|
|
6024
7182
|
}
|
|
6025
7183
|
}
|
|
6026
7184
|
}
|
|
7185
|
+
else if (this._stateLoading) {
|
|
7186
|
+
g.strokeStyle = 'white';
|
|
7187
|
+
g.fillStyle = 'white';
|
|
7188
|
+
g.font = '20px sans-serif';
|
|
7189
|
+
g.fillText("Loading...", 10, 25);
|
|
7190
|
+
}
|
|
6027
7191
|
}
|
|
6028
7192
|
}
|
|
6029
7193
|
}
|
|
@@ -6066,7 +7230,7 @@ class LevelBar {
|
|
|
6066
7230
|
}
|
|
6067
7231
|
}
|
|
6068
7232
|
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 });
|
|
6069
|
-
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: `
|
|
7233
|
+
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: `
|
|
6070
7234
|
<div #virtualCanvas>
|
|
6071
7235
|
<canvas #levelbar></canvas>
|
|
6072
7236
|
<canvas #markerCanvas></canvas>
|
|
@@ -6123,6 +7287,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
6123
7287
|
type: Input
|
|
6124
7288
|
}], displayLevelInfos: [{
|
|
6125
7289
|
type: Input
|
|
7290
|
+
}], stateLoading: [{
|
|
7291
|
+
type: Input
|
|
6126
7292
|
}], onResize: [{
|
|
6127
7293
|
type: HostListener,
|
|
6128
7294
|
args: ['window:resize', ['$event']]
|
|
@@ -6713,47 +7879,68 @@ class PeakLevelInterceptor {
|
|
|
6713
7879
|
}
|
|
6714
7880
|
}
|
|
6715
7881
|
class LevelMeasure {
|
|
7882
|
+
//private bufferLevelInfos=new Array<LevelInfo>();
|
|
7883
|
+
//private peakLevelInfo!:LevelInfo;
|
|
6716
7884
|
constructor() {
|
|
6717
7885
|
this.worker = null;
|
|
6718
7886
|
this.workerURL = WorkerHelper.buildWorkerBlobURL(this.workerFunction);
|
|
6719
7887
|
}
|
|
6720
|
-
calcBufferLevelInfos(
|
|
7888
|
+
calcBufferLevelInfos(audioDataHolder, bufferTimeLength) {
|
|
6721
7889
|
return new Promise((resolve) => {
|
|
6722
|
-
|
|
6723
|
-
let
|
|
6724
|
-
let
|
|
7890
|
+
var _a;
|
|
7891
|
+
let chs = audioDataHolder.numberOfChannels;
|
|
7892
|
+
let bufferFrameLength = Math.round(audioDataHolder.sampleRate * bufferTimeLength);
|
|
7893
|
+
let ais = audioDataHolder.audioInputStream();
|
|
7894
|
+
let audioBuffers = new Array(chs);
|
|
7895
|
+
let trBuffers = new Array(chs);
|
|
6725
7896
|
for (let ch = 0; ch < chs; ch++) {
|
|
6726
|
-
|
|
6727
|
-
let adChCopy = new Float32Array(adCh.length);
|
|
6728
|
-
adChCopy.set(adCh);
|
|
6729
|
-
buffers[ch] = adChCopy.buffer;
|
|
7897
|
+
audioBuffers[ch] = new Float32Array(bufferFrameLength);
|
|
6730
7898
|
}
|
|
7899
|
+
let bufferLevelInfos = new Array();
|
|
7900
|
+
let peakLevelInfo = new LevelInfo(chs);
|
|
6731
7901
|
this.worker = new Worker(this.workerURL);
|
|
6732
7902
|
this.worker.onmessage = (me) => {
|
|
6733
|
-
|
|
6734
|
-
|
|
6735
|
-
linLevelArrs
|
|
6736
|
-
|
|
6737
|
-
|
|
6738
|
-
|
|
6739
|
-
|
|
6740
|
-
|
|
6741
|
-
|
|
6742
|
-
|
|
6743
|
-
|
|
7903
|
+
var _a;
|
|
7904
|
+
if (me.data.linLevelBuffers) {
|
|
7905
|
+
let linLevelArrs = new Array(chs);
|
|
7906
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7907
|
+
linLevelArrs[ch] = new Float32Array(me.data.linLevelBuffers[ch]);
|
|
7908
|
+
}
|
|
7909
|
+
let bufferCount = Math.ceil(me.data.frameLength / me.data.bufferFrameLength);
|
|
7910
|
+
let framePos = 0;
|
|
7911
|
+
for (let bi = 0; bi < bufferCount; bi++) {
|
|
7912
|
+
let minLevels = new Array(chs);
|
|
7913
|
+
let maxLevels = new Array(chs);
|
|
7914
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7915
|
+
let linLvlArrPos = bi * 2;
|
|
7916
|
+
minLevels[ch] = linLevelArrs[ch][linLvlArrPos];
|
|
7917
|
+
maxLevels[ch] = linLevelArrs[ch][linLvlArrPos + 1];
|
|
7918
|
+
}
|
|
7919
|
+
let bli = new LevelInfo(chs, framePos, me.data.bufferFrameLength, minLevels, maxLevels);
|
|
7920
|
+
bufferLevelInfos.push(bli);
|
|
7921
|
+
peakLevelInfo.merge(bli);
|
|
7922
|
+
}
|
|
7923
|
+
}
|
|
7924
|
+
if (me.data.eod === true) {
|
|
7925
|
+
// end of data, terminate worker and return result
|
|
7926
|
+
this.terminateWorker();
|
|
7927
|
+
resolve(new LevelInfos(bufferLevelInfos, peakLevelInfo));
|
|
7928
|
+
}
|
|
7929
|
+
else {
|
|
7930
|
+
let read = ais.read(audioBuffers);
|
|
6744
7931
|
for (let ch = 0; ch < chs; ch++) {
|
|
6745
|
-
let
|
|
6746
|
-
|
|
6747
|
-
maxLevels[ch] = linLevelArrs[ch][linLvlArrPos + 1];
|
|
7932
|
+
let copy = new Float32Array(audioBuffers[ch]);
|
|
7933
|
+
trBuffers[ch] = copy.buffer;
|
|
6748
7934
|
}
|
|
6749
|
-
|
|
6750
|
-
bufferLevelInfos.push(bli);
|
|
6751
|
-
peakLevelInfo.merge(bli);
|
|
7935
|
+
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.postMessage({ bufferFrameLength: bufferFrameLength, audioData: trBuffers, chs: chs, len: read }, trBuffers);
|
|
6752
7936
|
}
|
|
6753
|
-
this.terminateWorker();
|
|
6754
|
-
resolve(new LevelInfos(bufferLevelInfos, peakLevelInfo));
|
|
6755
7937
|
};
|
|
6756
|
-
|
|
7938
|
+
let read = ais.read(audioBuffers);
|
|
7939
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7940
|
+
let copy = new Float32Array(audioBuffers[ch]);
|
|
7941
|
+
trBuffers[ch] = copy.buffer;
|
|
7942
|
+
}
|
|
7943
|
+
(_a = this.worker) === null || _a === void 0 ? void 0 : _a.postMessage({ bufferFrameLength: bufferFrameLength, audioData: trBuffers, chs: chs, len: read }, trBuffers);
|
|
6757
7944
|
});
|
|
6758
7945
|
}
|
|
6759
7946
|
terminateWorker() {
|
|
@@ -6765,40 +7952,63 @@ class LevelMeasure {
|
|
|
6765
7952
|
*/
|
|
6766
7953
|
workerFunction() {
|
|
6767
7954
|
self.onmessage = function (msg) {
|
|
6768
|
-
let
|
|
7955
|
+
let len = msg.data.len;
|
|
6769
7956
|
let bufferFrameLength = msg.data.bufferFrameLength;
|
|
6770
|
-
|
|
6771
|
-
|
|
6772
|
-
|
|
6773
|
-
|
|
7957
|
+
if (len == -1) {
|
|
7958
|
+
// start
|
|
7959
|
+
postMessage({
|
|
7960
|
+
eod: false,
|
|
7961
|
+
bufferFrameLength: bufferFrameLength,
|
|
7962
|
+
frameLength: len
|
|
7963
|
+
});
|
|
6774
7964
|
}
|
|
6775
|
-
|
|
6776
|
-
|
|
6777
|
-
|
|
6778
|
-
|
|
7965
|
+
if (len == 0) {
|
|
7966
|
+
postMessage({
|
|
7967
|
+
eod: true,
|
|
7968
|
+
bufferFrameLength: bufferFrameLength,
|
|
7969
|
+
frameLength: len
|
|
7970
|
+
});
|
|
6779
7971
|
}
|
|
6780
|
-
|
|
7972
|
+
else {
|
|
7973
|
+
let chs = msg.data.chs;
|
|
7974
|
+
let audioData = new Array(chs);
|
|
7975
|
+
let linLevels = new Array(chs);
|
|
6781
7976
|
for (let ch = 0; ch < chs; ch++) {
|
|
6782
|
-
|
|
6783
|
-
for (let s = 0; s < frameLength; s++) {
|
|
6784
|
-
let bi = Math.floor(s / bufferFrameLength);
|
|
6785
|
-
let lvlArrPos = bi * 2;
|
|
6786
|
-
//let bs = s % bufferFrameLength;
|
|
6787
|
-
let chSample = chData[s];
|
|
6788
|
-
if (chSample < linLevels[ch][lvlArrPos]) {
|
|
6789
|
-
linLevels[ch][lvlArrPos] = chSample;
|
|
6790
|
-
}
|
|
6791
|
-
lvlArrPos++;
|
|
6792
|
-
if (chSample > linLevels[ch][lvlArrPos]) {
|
|
6793
|
-
linLevels[ch][lvlArrPos] = chSample;
|
|
6794
|
-
}
|
|
6795
|
-
}
|
|
7977
|
+
audioData[ch] = new Float32Array(msg.data.audioData[ch]);
|
|
6796
7978
|
}
|
|
6797
|
-
|
|
7979
|
+
//let frameLength = audioData[0].length;
|
|
7980
|
+
let bufferCount = Math.ceil(len / bufferFrameLength);
|
|
6798
7981
|
for (let ch = 0; ch < chs; ch++) {
|
|
6799
|
-
|
|
7982
|
+
linLevels[ch] = new Float32Array(bufferCount * 2);
|
|
7983
|
+
}
|
|
7984
|
+
if (audioData && chs > 0) {
|
|
7985
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
7986
|
+
let chData = audioData[ch];
|
|
7987
|
+
for (let s = 0; s < len; s++) {
|
|
7988
|
+
let bi = Math.floor(s / bufferFrameLength);
|
|
7989
|
+
let lvlArrPos = bi * 2;
|
|
7990
|
+
//let bs = s % bufferFrameLength;
|
|
7991
|
+
let chSample = chData[s];
|
|
7992
|
+
if (chSample < linLevels[ch][lvlArrPos]) {
|
|
7993
|
+
linLevels[ch][lvlArrPos] = chSample;
|
|
7994
|
+
}
|
|
7995
|
+
lvlArrPos++;
|
|
7996
|
+
if (chSample > linLevels[ch][lvlArrPos]) {
|
|
7997
|
+
linLevels[ch][lvlArrPos] = chSample;
|
|
7998
|
+
}
|
|
7999
|
+
}
|
|
8000
|
+
}
|
|
8001
|
+
const linLevelBufs = new Array(chs);
|
|
8002
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
8003
|
+
linLevelBufs[ch] = linLevels[ch].buffer;
|
|
8004
|
+
}
|
|
8005
|
+
postMessage({
|
|
8006
|
+
eod: false,
|
|
8007
|
+
bufferFrameLength: bufferFrameLength,
|
|
8008
|
+
frameLength: len,
|
|
8009
|
+
linLevelBuffers: linLevelBufs
|
|
8010
|
+
}, linLevelBufs);
|
|
6800
8011
|
}
|
|
6801
|
-
postMessage({ bufferFrameLength: bufferFrameLength, frameLength: frameLength, linLevelBuffers: linLevelBufs }, linLevelBufs);
|
|
6802
8012
|
}
|
|
6803
8013
|
};
|
|
6804
8014
|
}
|
|
@@ -7174,7 +8384,7 @@ RecordingItemDisplay.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", v
|
|
|
7174
8384
|
<audio-levelbar fxFlex="1 0 1" [streamingMode]="streamingMode" [displayLevelInfos]="_displayLevelInfos"></audio-levelbar>
|
|
7175
8385
|
<spr-recordingitemcontrols fxFlex="0 0 0" [audioLoaded]="displayAudioBuffer!==null" [playStartAction]="playStartAction" [playStopAction]="playStopAction" [peakDbLvl]="peakDbLvl" [agc]="_agc" (onShowRecordingDetails)="onShowRecordingDetails.emit()"></spr-recordingitemcontrols>
|
|
7176
8386
|
</div>
|
|
7177
|
-
`, 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"] }] });
|
|
8387
|
+
`, 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"] }] });
|
|
7178
8388
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingItemDisplay, decorators: [{
|
|
7179
8389
|
type: Component,
|
|
7180
8390
|
args: [{
|
|
@@ -7220,89 +8430,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
7220
8430
|
type: Input
|
|
7221
8431
|
}] } });
|
|
7222
8432
|
|
|
7223
|
-
class Float32ArrayChunkerOutStream {
|
|
7224
|
-
constructor(outStream) {
|
|
7225
|
-
this.outStream = outStream;
|
|
7226
|
-
this.bufs = new Array();
|
|
7227
|
-
this._channels = 0;
|
|
7228
|
-
this._chunkSize = 0;
|
|
7229
|
-
this.filled = 0;
|
|
7230
|
-
this.receivedFrames = 0;
|
|
7231
|
-
this.sentFrames = 0;
|
|
7232
|
-
}
|
|
7233
|
-
createBuffers() {
|
|
7234
|
-
this.bufs = new Array(this._channels);
|
|
7235
|
-
for (let ch = 0; ch < this._channels; ch++) {
|
|
7236
|
-
this.bufs[ch] = new Float32Array(this._chunkSize);
|
|
7237
|
-
}
|
|
7238
|
-
}
|
|
7239
|
-
set chunkSize(chunkSize) {
|
|
7240
|
-
this._chunkSize = chunkSize;
|
|
7241
|
-
this.createBuffers();
|
|
7242
|
-
}
|
|
7243
|
-
get chunkSize() {
|
|
7244
|
-
return this._chunkSize;
|
|
7245
|
-
}
|
|
7246
|
-
set channels(channels) {
|
|
7247
|
-
this._channels = channels;
|
|
7248
|
-
this.createBuffers();
|
|
7249
|
-
}
|
|
7250
|
-
get channels() {
|
|
7251
|
-
return this._channels;
|
|
7252
|
-
}
|
|
7253
|
-
available() {
|
|
7254
|
-
return this._chunkSize - this.filled;
|
|
7255
|
-
}
|
|
7256
|
-
write(buffers) {
|
|
7257
|
-
let copied = 0;
|
|
7258
|
-
if (buffers.length > 0) {
|
|
7259
|
-
let buffersLen = buffers[0].length;
|
|
7260
|
-
this.receivedFrames += buffersLen;
|
|
7261
|
-
let avail = buffersLen;
|
|
7262
|
-
// Fill out buffers until all values copied
|
|
7263
|
-
while (avail > 0) {
|
|
7264
|
-
let toFill = this._chunkSize - this.filled;
|
|
7265
|
-
if (toFill > avail) {
|
|
7266
|
-
toFill = avail;
|
|
7267
|
-
}
|
|
7268
|
-
let sliceEnd = copied + toFill;
|
|
7269
|
-
// Firefox on Android sends only the first channel
|
|
7270
|
-
for (let ch = 0; ch < buffersLen; ch++) {
|
|
7271
|
-
if (buffers[ch]) {
|
|
7272
|
-
let cpPrt = buffers[ch].slice(copied, sliceEnd);
|
|
7273
|
-
let buf = this.bufs[ch];
|
|
7274
|
-
buf.set(cpPrt, this.filled);
|
|
7275
|
-
}
|
|
7276
|
-
}
|
|
7277
|
-
copied += toFill;
|
|
7278
|
-
avail -= toFill;
|
|
7279
|
-
this.filled += toFill;
|
|
7280
|
-
if (this.filled == this._chunkSize) {
|
|
7281
|
-
this.outStream.write(this.bufs);
|
|
7282
|
-
this.sentFrames += this.filled;
|
|
7283
|
-
this.filled = 0;
|
|
7284
|
-
}
|
|
7285
|
-
}
|
|
7286
|
-
}
|
|
7287
|
-
return copied;
|
|
7288
|
-
}
|
|
7289
|
-
flush() {
|
|
7290
|
-
if (this.filled > 0) {
|
|
7291
|
-
let restBufs = new Array(this._channels);
|
|
7292
|
-
for (let ch = 0; ch < this._channels; ch++) {
|
|
7293
|
-
restBufs[ch] = this.bufs[ch].slice(0, this.filled);
|
|
7294
|
-
}
|
|
7295
|
-
this.outStream.write(restBufs);
|
|
7296
|
-
this.outStream.flush();
|
|
7297
|
-
this.sentFrames += this.filled;
|
|
7298
|
-
this.filled = 0;
|
|
7299
|
-
}
|
|
7300
|
-
}
|
|
7301
|
-
close() {
|
|
7302
|
-
this.outStream.close();
|
|
7303
|
-
}
|
|
7304
|
-
}
|
|
7305
|
-
|
|
7306
8433
|
class SequenceAudioFloat32ChunkerOutStream extends Float32ArrayChunkerOutStream {
|
|
7307
8434
|
constructor(outStream, chunkDurationSeconds) {
|
|
7308
8435
|
super(outStream);
|
|
@@ -7311,11 +8438,11 @@ class SequenceAudioFloat32ChunkerOutStream extends Float32ArrayChunkerOutStream
|
|
|
7311
8438
|
this.sequenceAudioFloat32OutStream = outStream;
|
|
7312
8439
|
}
|
|
7313
8440
|
setFormat(channels, sampleRate) {
|
|
7314
|
-
console.debug("SequenceAudioFloat32ChunkerOutStream:setFormat(channels: "
|
|
8441
|
+
//console.debug("SequenceAudioFloat32ChunkerOutStream:setFormat(channels: "+channels+",sampleRate: "+sampleRate+")")
|
|
7315
8442
|
this.channels = channels;
|
|
7316
8443
|
this.sampleRate = sampleRate;
|
|
7317
8444
|
this.chunkSize = Math.round(sampleRate * this.chunkDurationSeconds);
|
|
7318
|
-
console.debug("SequenceAudioFloat32ChunkerOutStream: chunkSize: "
|
|
8445
|
+
//console.debug("SequenceAudioFloat32ChunkerOutStream: chunkSize: "+this.chunkSize);
|
|
7319
8446
|
this.sequenceAudioFloat32OutStream.setFormat(channels, sampleRate);
|
|
7320
8447
|
}
|
|
7321
8448
|
nextStream() {
|
|
@@ -7522,7 +8649,8 @@ class ChunkManager {
|
|
|
7522
8649
|
}
|
|
7523
8650
|
}
|
|
7524
8651
|
let BasicRecorder = class BasicRecorder {
|
|
7525
|
-
constructor(dialog, sessionService, uploader, config) {
|
|
8652
|
+
constructor(changeDetectorRef, dialog, sessionService, uploader, config) {
|
|
8653
|
+
this.changeDetectorRef = changeDetectorRef;
|
|
7526
8654
|
this.dialog = dialog;
|
|
7527
8655
|
this.sessionService = sessionService;
|
|
7528
8656
|
this.uploader = uploader;
|
|
@@ -7537,14 +8665,15 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7537
8665
|
this._selectedDeviceId = undefined;
|
|
7538
8666
|
this._channelCount = 2;
|
|
7539
8667
|
this._session = null;
|
|
8668
|
+
this._recordingFile = null;
|
|
7540
8669
|
this.startedDate = null;
|
|
7541
8670
|
this.uploadProgress = 100;
|
|
7542
8671
|
this.uploadStatus = 'ok';
|
|
7543
8672
|
this.audioSignalCollapsed = true;
|
|
7544
8673
|
this.peakLevelInDb = MIN_DB_LEVEL;
|
|
7545
|
-
this.displayLevelInfos = null;
|
|
7546
8674
|
this.displayAudioClip = null;
|
|
7547
8675
|
this.audioFetchSubscription = null;
|
|
8676
|
+
this.audioFetching = false;
|
|
7548
8677
|
this.destroyed = false;
|
|
7549
8678
|
this.navigationDisabled = true;
|
|
7550
8679
|
// Default: Disabled chunked upload
|
|
@@ -7639,6 +8768,28 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7639
8768
|
this.ac.audioOutStream = outStream;
|
|
7640
8769
|
}
|
|
7641
8770
|
}
|
|
8771
|
+
showRecording() {
|
|
8772
|
+
this._controlAudioPlayer.stop();
|
|
8773
|
+
if (this.displayAudioClip) {
|
|
8774
|
+
let dap = this.displayAudioClip;
|
|
8775
|
+
let adh = dap.audioDataHolder;
|
|
8776
|
+
if (adh) {
|
|
8777
|
+
this.levelMeasure.calcBufferLevelInfos(adh, LEVEL_BAR_INTERVALL_SECONDS).then((levelInfos) => {
|
|
8778
|
+
dap.levelInfos = levelInfos;
|
|
8779
|
+
this.changeDetectorRef.detectChanges();
|
|
8780
|
+
});
|
|
8781
|
+
}
|
|
8782
|
+
this.playStartAction.disabled = false;
|
|
8783
|
+
}
|
|
8784
|
+
else {
|
|
8785
|
+
this.playStartAction.disabled = true;
|
|
8786
|
+
// Collapse audio signal display if open
|
|
8787
|
+
if (!this.audioSignalCollapsed) {
|
|
8788
|
+
this.audioSignalCollapsed = true;
|
|
8789
|
+
}
|
|
8790
|
+
}
|
|
8791
|
+
this.changeDetectorRef.detectChanges();
|
|
8792
|
+
}
|
|
7642
8793
|
start() {
|
|
7643
8794
|
this.statusAlertType = 'info';
|
|
7644
8795
|
this.statusMsg = 'Starting session...';
|
|
@@ -7859,9 +9010,9 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7859
9010
|
}
|
|
7860
9011
|
this.transportActions.startAction.disabled = true;
|
|
7861
9012
|
}
|
|
7862
|
-
postRecording(wavFile, recUrl) {
|
|
9013
|
+
postRecording(wavFile, recUrl, rf) {
|
|
7863
9014
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
7864
|
-
let ul = new Upload(wavBlob, recUrl);
|
|
9015
|
+
let ul = new Upload(wavBlob, recUrl, rf);
|
|
7865
9016
|
this.uploader.queueUpload(ul);
|
|
7866
9017
|
}
|
|
7867
9018
|
postAudioStreamStart() {
|
|
@@ -7900,39 +9051,344 @@ let BasicRecorder = class BasicRecorder {
|
|
|
7900
9051
|
if (apiEndPoint !== '') {
|
|
7901
9052
|
apiEndPoint = apiEndPoint + '/';
|
|
7902
9053
|
}
|
|
7903
|
-
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
7904
|
-
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/concatChunksRequest';
|
|
7905
|
-
let fd = new FormData();
|
|
7906
|
-
fd.set('uuid', this.rfUuid);
|
|
7907
|
-
fd.set('chunkCount', chunkCount.toString());
|
|
7908
|
-
let ul = new Upload(fd, recUrl);
|
|
7909
|
-
this.uploader.queueUpload(ul);
|
|
9054
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
9055
|
+
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/concatChunksRequest';
|
|
9056
|
+
let fd = new FormData();
|
|
9057
|
+
fd.set('uuid', this.rfUuid);
|
|
9058
|
+
fd.set('chunkCount', chunkCount.toString());
|
|
9059
|
+
let ul = new Upload(fd, recUrl, this._recordingFile);
|
|
9060
|
+
this.uploader.queueUpload(ul);
|
|
9061
|
+
console.debug("Queued for upload: " + this._recordingFile);
|
|
9062
|
+
}
|
|
9063
|
+
else {
|
|
9064
|
+
console.error("Recording file UUID not set!");
|
|
9065
|
+
}
|
|
9066
|
+
}
|
|
9067
|
+
closed() {
|
|
9068
|
+
this.statusAlertType = 'info';
|
|
9069
|
+
this.statusMsg = 'Session closed.';
|
|
9070
|
+
}
|
|
9071
|
+
error(msg = 'An unknown error occured during recording.', advice = 'Please retry.') {
|
|
9072
|
+
this.statusMsg = 'ERROR: Recording.';
|
|
9073
|
+
this.statusAlertType = 'error';
|
|
9074
|
+
this.dialog.open(MessageDialog, {
|
|
9075
|
+
data: {
|
|
9076
|
+
type: 'error',
|
|
9077
|
+
title: 'Recording error',
|
|
9078
|
+
msg: msg,
|
|
9079
|
+
advice: advice
|
|
9080
|
+
}
|
|
9081
|
+
});
|
|
9082
|
+
}
|
|
9083
|
+
};
|
|
9084
|
+
// Enable only for developemnt/debug purposes of array audio buffers !!
|
|
9085
|
+
BasicRecorder.FORCE_ARRRAY_AUDIO_BUFFER = false;
|
|
9086
|
+
BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS = 30;
|
|
9087
|
+
BasicRecorder = __decorate([
|
|
9088
|
+
__param(4, Inject(SPEECHRECORDER_CONFIG))
|
|
9089
|
+
], BasicRecorder);
|
|
9090
|
+
|
|
9091
|
+
class AudioDataHolder {
|
|
9092
|
+
constructor(_buffer, _arrayBuffer = null) {
|
|
9093
|
+
this._buffer = _buffer;
|
|
9094
|
+
this._arrayBuffer = _arrayBuffer;
|
|
9095
|
+
this._numberOfChannels = 0;
|
|
9096
|
+
this._sampleRate = 0;
|
|
9097
|
+
this._frameLen = 0;
|
|
9098
|
+
this._duration = 0;
|
|
9099
|
+
if (this._buffer && this._arrayBuffer) {
|
|
9100
|
+
throw Error('Only one of either audio buffer or array audio buffer must be set!');
|
|
9101
|
+
}
|
|
9102
|
+
if (this._buffer || this._arrayBuffer) {
|
|
9103
|
+
if (this._buffer) {
|
|
9104
|
+
this._numberOfChannels = this._buffer.numberOfChannels;
|
|
9105
|
+
this._sampleRate = this._buffer.sampleRate;
|
|
9106
|
+
this._frameLen = this._buffer.length;
|
|
9107
|
+
this._duration = this._frameLen / this._sampleRate;
|
|
9108
|
+
}
|
|
9109
|
+
else if (this._arrayBuffer) {
|
|
9110
|
+
this._numberOfChannels = this._arrayBuffer.channelCount;
|
|
9111
|
+
this._sampleRate = this._arrayBuffer.sampleRate;
|
|
9112
|
+
this._frameLen = this._arrayBuffer.frameLen;
|
|
9113
|
+
this._duration = this._frameLen / this._sampleRate;
|
|
9114
|
+
}
|
|
9115
|
+
}
|
|
9116
|
+
else {
|
|
9117
|
+
throw Error(AudioDataHolder.ONE_OF_MUST_BE_SET_ERR_MSG);
|
|
9118
|
+
}
|
|
9119
|
+
}
|
|
9120
|
+
get duration() {
|
|
9121
|
+
return this._duration;
|
|
9122
|
+
}
|
|
9123
|
+
get sampleRate() {
|
|
9124
|
+
return this._sampleRate;
|
|
9125
|
+
}
|
|
9126
|
+
get numberOfChannels() {
|
|
9127
|
+
return this._numberOfChannels;
|
|
9128
|
+
}
|
|
9129
|
+
get frameLen() {
|
|
9130
|
+
return this._frameLen;
|
|
9131
|
+
}
|
|
9132
|
+
sampleCounts() {
|
|
9133
|
+
return this._numberOfChannels * this._frameLen;
|
|
9134
|
+
}
|
|
9135
|
+
frames(framePos, frameLen, bufs) {
|
|
9136
|
+
let read = 0;
|
|
9137
|
+
if (this._buffer) {
|
|
9138
|
+
let toRead = frameLen;
|
|
9139
|
+
if (this._buffer.length < framePos + frameLen) {
|
|
9140
|
+
toRead = this._buffer.length - framePos;
|
|
9141
|
+
}
|
|
9142
|
+
for (let ch = 0; ch < bufs.length; ch++) {
|
|
9143
|
+
let chData = this._buffer.getChannelData(ch);
|
|
9144
|
+
for (let i = 0; i < toRead; i++) {
|
|
9145
|
+
bufs[ch][i] = chData[framePos + i];
|
|
9146
|
+
}
|
|
9147
|
+
}
|
|
9148
|
+
read = toRead;
|
|
9149
|
+
}
|
|
9150
|
+
else if (this._arrayBuffer) {
|
|
9151
|
+
read = this._arrayBuffer.frames(framePos, frameLen, bufs);
|
|
9152
|
+
}
|
|
9153
|
+
return read;
|
|
9154
|
+
}
|
|
9155
|
+
audioInputStream() {
|
|
9156
|
+
if (this._buffer) {
|
|
9157
|
+
return new AudioBufferInputStream(this._buffer);
|
|
9158
|
+
}
|
|
9159
|
+
if (this._arrayBuffer) {
|
|
9160
|
+
return new ArrayAudioBufferInputStream(this._arrayBuffer);
|
|
9161
|
+
}
|
|
9162
|
+
throw Error(AudioDataHolder.ONE_OF_MUST_BE_SET_ERR_MSG);
|
|
9163
|
+
}
|
|
9164
|
+
get buffer() {
|
|
9165
|
+
return this._buffer;
|
|
9166
|
+
}
|
|
9167
|
+
get arrayBuffer() {
|
|
9168
|
+
return this._arrayBuffer;
|
|
9169
|
+
}
|
|
9170
|
+
}
|
|
9171
|
+
AudioDataHolder.ONE_OF_MUST_BE_SET_ERR_MSG = 'One of either audio buffer or array audio buffer must be set!';
|
|
9172
|
+
class AudioBufferInputStream {
|
|
9173
|
+
constructor(audioBuffer) {
|
|
9174
|
+
this.audioBuffer = audioBuffer;
|
|
9175
|
+
this.framePos = 0;
|
|
9176
|
+
}
|
|
9177
|
+
close() {
|
|
9178
|
+
}
|
|
9179
|
+
skipFrames(n) {
|
|
9180
|
+
this.framePos += n;
|
|
9181
|
+
}
|
|
9182
|
+
read(buffers) {
|
|
9183
|
+
let read = 0;
|
|
9184
|
+
let toRead = buffers[0].length;
|
|
9185
|
+
if (this.framePos + toRead > this.audioBuffer.length) {
|
|
9186
|
+
toRead = this.audioBuffer.length - this.framePos;
|
|
9187
|
+
}
|
|
9188
|
+
for (let ch = 0; ch < buffers.length; ch++) {
|
|
9189
|
+
for (let i = 0; i < toRead; i++) {
|
|
9190
|
+
buffers[ch][i] = this.audioBuffer.getChannelData(ch)[this.framePos + i];
|
|
9191
|
+
}
|
|
9192
|
+
}
|
|
9193
|
+
read = toRead;
|
|
9194
|
+
this.framePos += toRead;
|
|
9195
|
+
return read;
|
|
9196
|
+
}
|
|
9197
|
+
}
|
|
9198
|
+
|
|
9199
|
+
class BasicRecFilesCache {
|
|
9200
|
+
constructor() {
|
|
9201
|
+
//public static readonly DEFAULT_MAX_SAMPLES=30*48000; // TEST 30 seconds
|
|
9202
|
+
this._sampleCount = 0;
|
|
9203
|
+
this.maxSampleCount = BasicRecFilesCache.DEFAULT_MAX_SAMPLES;
|
|
9204
|
+
this._currentRecordingFile = null;
|
|
9205
|
+
}
|
|
9206
|
+
get currentRecordingFile() {
|
|
9207
|
+
return this._currentRecordingFile;
|
|
9208
|
+
}
|
|
9209
|
+
set currentRecordingFile(value) {
|
|
9210
|
+
this._currentRecordingFile = value;
|
|
9211
|
+
this.expire();
|
|
9212
|
+
}
|
|
9213
|
+
}
|
|
9214
|
+
BasicRecFilesCache.DEBUG = false;
|
|
9215
|
+
BasicRecFilesCache.DEFAULT_MAX_SAMPLES = 10 * 60 * 48000; // 20 Minutes mono 48kHz
|
|
9216
|
+
class SprItemsCache extends BasicRecFilesCache {
|
|
9217
|
+
constructor() {
|
|
9218
|
+
super(...arguments);
|
|
9219
|
+
this._items = new Array();
|
|
9220
|
+
}
|
|
9221
|
+
get items() {
|
|
9222
|
+
return this._items;
|
|
9223
|
+
}
|
|
9224
|
+
addItem(item) {
|
|
9225
|
+
this._items.push(item);
|
|
9226
|
+
}
|
|
9227
|
+
getItem(index) {
|
|
9228
|
+
return this._items[index];
|
|
9229
|
+
}
|
|
9230
|
+
length() {
|
|
9231
|
+
return this._items.length;
|
|
9232
|
+
}
|
|
9233
|
+
tryExpire(toBeExpiredRf) {
|
|
9234
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9235
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " try expire:");
|
|
9236
|
+
if (!RecordingFileUtils.equals(toBeExpiredRf, this.currentRecordingFile)) {
|
|
9237
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9238
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " not current file...");
|
|
9239
|
+
if (toBeExpiredRf.serverPersisted) {
|
|
9240
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9241
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " is server persisted...");
|
|
9242
|
+
// expire recording files first stored to the cache
|
|
9243
|
+
let expiredAudio = RecordingFileUtils.expireAudioData(toBeExpiredRf);
|
|
9244
|
+
if (expiredAudio) {
|
|
9245
|
+
this._sampleCount -= expiredAudio.sampleCounts();
|
|
9246
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9247
|
+
console.debug("Rec. files cache: Expired: " + toBeExpiredRf.toString() + ". Cache samples now: " + this._sampleCount);
|
|
9248
|
+
}
|
|
9249
|
+
}
|
|
9250
|
+
else {
|
|
9251
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9252
|
+
console.debug("Rec. files cache: #" + toBeExpiredRf.toString() + " not yet persisted on server.");
|
|
9253
|
+
}
|
|
9254
|
+
}
|
|
9255
|
+
else {
|
|
9256
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9257
|
+
console.debug("Rec. files cache: " + toBeExpiredRf.toString() + " is current file.");
|
|
9258
|
+
}
|
|
9259
|
+
}
|
|
9260
|
+
expire() {
|
|
9261
|
+
// expire corrected versions first
|
|
9262
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9263
|
+
console.debug("Rec. files cache: Expire? current: " + this._sampleCount + ", max: " + this.maxSampleCount);
|
|
9264
|
+
if (this._sampleCount > this.maxSampleCount) {
|
|
9265
|
+
// expire older versions of an item first
|
|
9266
|
+
for (let ii = 0; ii < this._items.length; ii++) {
|
|
9267
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9268
|
+
break;
|
|
9269
|
+
}
|
|
9270
|
+
let it = this._items[ii];
|
|
9271
|
+
let itRfs = it.recs;
|
|
9272
|
+
if (itRfs && itRfs.length > 1) {
|
|
9273
|
+
for (let rfi = 0; rfi < itRfs.length - 1; rfi++) {
|
|
9274
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9275
|
+
break;
|
|
9276
|
+
}
|
|
9277
|
+
let toBeExpiredRf = itRfs[rfi];
|
|
9278
|
+
this.tryExpire(toBeExpiredRf);
|
|
9279
|
+
}
|
|
9280
|
+
}
|
|
9281
|
+
}
|
|
9282
|
+
// if that's not sufficient expire audio data of latest versions as well
|
|
9283
|
+
for (let ii = 0; ii < this._items.length; ii++) {
|
|
9284
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9285
|
+
break;
|
|
9286
|
+
}
|
|
9287
|
+
let it = this._items[ii];
|
|
9288
|
+
let itRfs = it.recs;
|
|
9289
|
+
if (itRfs && itRfs.length > 0) {
|
|
9290
|
+
for (let rfi = 0; rfi < itRfs.length; rfi++) {
|
|
9291
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9292
|
+
break;
|
|
9293
|
+
}
|
|
9294
|
+
let toBeExpiredRf = itRfs[rfi];
|
|
9295
|
+
this.tryExpire(toBeExpiredRf);
|
|
9296
|
+
}
|
|
9297
|
+
}
|
|
9298
|
+
}
|
|
7910
9299
|
}
|
|
7911
|
-
|
|
7912
|
-
|
|
9300
|
+
}
|
|
9301
|
+
addSprRecFile(item, sprRecFile) {
|
|
9302
|
+
this.expire();
|
|
9303
|
+
if (!item.recs) {
|
|
9304
|
+
item.recs = new Array();
|
|
7913
9305
|
}
|
|
9306
|
+
item.recs.push(sprRecFile);
|
|
9307
|
+
this._sampleCount += RecordingFileUtils.sampleCount(sprRecFile);
|
|
9308
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9309
|
+
console.debug("Rec. files cache: Added. Cache samples: " + this._sampleCount);
|
|
7914
9310
|
}
|
|
7915
|
-
|
|
7916
|
-
this.
|
|
7917
|
-
|
|
9311
|
+
setSprRecFileAudioData(sprRecFile, adh) {
|
|
9312
|
+
this.expire();
|
|
9313
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9314
|
+
console.debug("Rec. files cache: Set audio data after expire. Cache samples: " + this._sampleCount);
|
|
9315
|
+
let currSampleCnt = RecordingFileUtils.sampleCount(sprRecFile);
|
|
9316
|
+
this._sampleCount -= currSampleCnt;
|
|
9317
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9318
|
+
console.debug("Rec. files cache: Set audio data subtracted curr sample count: " + currSampleCnt + ". Cache samples: " + this._sampleCount);
|
|
9319
|
+
RecordingFileUtils.setAudioData(sprRecFile, adh);
|
|
9320
|
+
let newSampleCnt = RecordingFileUtils.sampleCount(sprRecFile);
|
|
9321
|
+
this._sampleCount += newSampleCnt;
|
|
9322
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9323
|
+
console.debug("Rec. files cache: Set audio data added new sample count: " + newSampleCnt + ". Cache samples: " + this._sampleCount);
|
|
9324
|
+
let fl = adh === null || adh === void 0 ? void 0 : adh.frameLen;
|
|
9325
|
+
if (fl) {
|
|
9326
|
+
sprRecFile.frames = fl;
|
|
9327
|
+
}
|
|
9328
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9329
|
+
console.debug("Rec. files cache: Set audio data. Cache samples: " + this._sampleCount);
|
|
7918
9330
|
}
|
|
7919
|
-
|
|
7920
|
-
|
|
7921
|
-
|
|
7922
|
-
|
|
7923
|
-
|
|
7924
|
-
|
|
7925
|
-
|
|
7926
|
-
|
|
7927
|
-
|
|
9331
|
+
}
|
|
9332
|
+
class RecFilesCache extends BasicRecFilesCache {
|
|
9333
|
+
constructor() {
|
|
9334
|
+
super(...arguments);
|
|
9335
|
+
this._recFiles = new Array();
|
|
9336
|
+
}
|
|
9337
|
+
get recFiles() {
|
|
9338
|
+
return this._recFiles;
|
|
9339
|
+
}
|
|
9340
|
+
getRecFile(index) {
|
|
9341
|
+
return this._recFiles[index];
|
|
9342
|
+
}
|
|
9343
|
+
length() {
|
|
9344
|
+
return this._recFiles.length;
|
|
9345
|
+
}
|
|
9346
|
+
expire() {
|
|
9347
|
+
if (this._sampleCount > this.maxSampleCount) {
|
|
9348
|
+
// audio recorder list is sorted: lower index is newer
|
|
9349
|
+
for (let rfI = this._recFiles.length - 1; rfI >= 0; rfI--) {
|
|
9350
|
+
if (this._sampleCount <= this.maxSampleCount) {
|
|
9351
|
+
break;
|
|
9352
|
+
}
|
|
9353
|
+
let toBeExpiredRf = this._recFiles[rfI];
|
|
9354
|
+
if (toBeExpiredRf.serverPersisted) {
|
|
9355
|
+
if (!RecordingFileUtils.equals(toBeExpiredRf, this.currentRecordingFile)) {
|
|
9356
|
+
// expire recording files first stored to the cache
|
|
9357
|
+
let expiredAudio = RecordingFileUtils.expireAudioData(toBeExpiredRf);
|
|
9358
|
+
if (expiredAudio) {
|
|
9359
|
+
this._sampleCount -= expiredAudio.sampleCounts();
|
|
9360
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9361
|
+
console.debug("Rec. files cache: Expired #" + rfI + ". Cache samples: " + this._sampleCount);
|
|
9362
|
+
}
|
|
9363
|
+
}
|
|
9364
|
+
else {
|
|
9365
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9366
|
+
console.debug("Rec. files cache: #" + rfI + " is current file. (not expiring)");
|
|
9367
|
+
}
|
|
9368
|
+
}
|
|
9369
|
+
else {
|
|
9370
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9371
|
+
console.debug("Rec. files cache: #" + rfI + " not yet server persisted.");
|
|
9372
|
+
}
|
|
7928
9373
|
}
|
|
7929
|
-
}
|
|
9374
|
+
}
|
|
7930
9375
|
}
|
|
7931
|
-
|
|
7932
|
-
|
|
7933
|
-
|
|
7934
|
-
|
|
7935
|
-
|
|
9376
|
+
addRecFile(recFile) {
|
|
9377
|
+
this.expire();
|
|
9378
|
+
this._recFiles.push(recFile);
|
|
9379
|
+
this._sampleCount += RecordingFileUtils.sampleCount(recFile);
|
|
9380
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9381
|
+
console.debug("Rec. files cache: Added. Cache samples: " + this._sampleCount);
|
|
9382
|
+
}
|
|
9383
|
+
setRecFileAudioData(recFile, adh) {
|
|
9384
|
+
this.expire();
|
|
9385
|
+
this._sampleCount -= RecordingFileUtils.sampleCount(recFile);
|
|
9386
|
+
RecordingFileUtils.setAudioData(recFile, adh);
|
|
9387
|
+
this._sampleCount += RecordingFileUtils.sampleCount(recFile);
|
|
9388
|
+
if (BasicRecFilesCache.DEBUG)
|
|
9389
|
+
console.debug("Rec. files cache: Set audio data. Cache samples: " + this._sampleCount);
|
|
9390
|
+
}
|
|
9391
|
+
}
|
|
7936
9392
|
|
|
7937
9393
|
/**
|
|
7938
9394
|
* Created by klausj on 17.06.2017.
|
|
@@ -8025,16 +9481,62 @@ class RecordingService {
|
|
|
8025
9481
|
let recUrl = recFilesUrl + '/' + encItemcode + '/' + version;
|
|
8026
9482
|
return this.audioRequest(recUrl);
|
|
8027
9483
|
}
|
|
9484
|
+
fetchRecordingFileAudioBuffer(aCtx, projectName, recordingFile) {
|
|
9485
|
+
let wobs = new Observable(observer => {
|
|
9486
|
+
let recFileId = recordingFile.recordingFileId;
|
|
9487
|
+
if (!recFileId) {
|
|
9488
|
+
recFileId = recordingFile.uuid;
|
|
9489
|
+
}
|
|
9490
|
+
if (recordingFile.session && recFileId) {
|
|
9491
|
+
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
9492
|
+
obs.subscribe(resp => {
|
|
9493
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9494
|
+
if (resp.body) {
|
|
9495
|
+
aCtx.decodeAudioData(resp.body, ab => {
|
|
9496
|
+
observer.next(ab);
|
|
9497
|
+
observer.complete();
|
|
9498
|
+
}, error => {
|
|
9499
|
+
observer.error(error);
|
|
9500
|
+
observer.complete();
|
|
9501
|
+
});
|
|
9502
|
+
}
|
|
9503
|
+
else {
|
|
9504
|
+
observer.error('Fetching audio file: response has no body');
|
|
9505
|
+
}
|
|
9506
|
+
}, (error) => {
|
|
9507
|
+
if (error.status == 404) {
|
|
9508
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9509
|
+
observer.next(null);
|
|
9510
|
+
observer.complete();
|
|
9511
|
+
}
|
|
9512
|
+
else {
|
|
9513
|
+
// all other states are errors
|
|
9514
|
+
observer.error(error);
|
|
9515
|
+
observer.complete();
|
|
9516
|
+
}
|
|
9517
|
+
});
|
|
9518
|
+
}
|
|
9519
|
+
else {
|
|
9520
|
+
observer.error();
|
|
9521
|
+
}
|
|
9522
|
+
});
|
|
9523
|
+
return wobs;
|
|
9524
|
+
}
|
|
8028
9525
|
fetchAndApplyRecordingFile(aCtx, projectName, recordingFile) {
|
|
8029
9526
|
let wobs = new Observable(observer => {
|
|
8030
|
-
|
|
8031
|
-
|
|
9527
|
+
let recFileId = recordingFile.recordingFileId;
|
|
9528
|
+
if (!recFileId) {
|
|
9529
|
+
recFileId = recordingFile.uuid;
|
|
9530
|
+
}
|
|
9531
|
+
if (recordingFile.session && recFileId) {
|
|
9532
|
+
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
8032
9533
|
obs.subscribe(resp => {
|
|
8033
9534
|
//console.log("Fetched audio file. HTTP response status: "+resp.status+", type: "+resp.type+", byte length: "+ resp.body.byteLength);
|
|
8034
9535
|
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
8035
9536
|
if (resp.body) {
|
|
8036
9537
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
8037
|
-
|
|
9538
|
+
let adh = new AudioDataHolder(ab, null);
|
|
9539
|
+
RecordingFileUtils.setAudioData(recordingFile, adh);
|
|
8038
9540
|
if (this.debugDelay > 0) {
|
|
8039
9541
|
window.setTimeout(() => {
|
|
8040
9542
|
observer.next(recordingFile);
|
|
@@ -8072,6 +9574,47 @@ class RecordingService {
|
|
|
8072
9574
|
});
|
|
8073
9575
|
return wobs;
|
|
8074
9576
|
}
|
|
9577
|
+
fetchSprRecordingFileAudioBuffer(aCtx, projectName, recordingFile) {
|
|
9578
|
+
let wobs = new Observable(observer => {
|
|
9579
|
+
if (recordingFile.session) {
|
|
9580
|
+
let obs = this.fetchSprAudiofile(projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
9581
|
+
obs.subscribe({
|
|
9582
|
+
next: resp => {
|
|
9583
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9584
|
+
if (resp.body) {
|
|
9585
|
+
aCtx.decodeAudioData(resp.body, ab => {
|
|
9586
|
+
//RecordingFileUtils.setAudioData(recordingFile,new AudioDataHolder(ab,null));
|
|
9587
|
+
observer.next(ab);
|
|
9588
|
+
observer.complete();
|
|
9589
|
+
}, error => {
|
|
9590
|
+
observer.error(error);
|
|
9591
|
+
observer.complete();
|
|
9592
|
+
});
|
|
9593
|
+
}
|
|
9594
|
+
else {
|
|
9595
|
+
observer.error('Fetching audio file: response has no body');
|
|
9596
|
+
}
|
|
9597
|
+
},
|
|
9598
|
+
error: (error) => {
|
|
9599
|
+
if (error.status == 404) {
|
|
9600
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9601
|
+
observer.next(null);
|
|
9602
|
+
observer.complete();
|
|
9603
|
+
}
|
|
9604
|
+
else {
|
|
9605
|
+
// all other states are errors
|
|
9606
|
+
observer.error(error);
|
|
9607
|
+
observer.complete();
|
|
9608
|
+
}
|
|
9609
|
+
}
|
|
9610
|
+
});
|
|
9611
|
+
}
|
|
9612
|
+
else {
|
|
9613
|
+
observer.error();
|
|
9614
|
+
}
|
|
9615
|
+
});
|
|
9616
|
+
return wobs;
|
|
9617
|
+
}
|
|
8075
9618
|
fetchAndApplySprRecordingFile(aCtx, projectName, recordingFile) {
|
|
8076
9619
|
let wobs = new Observable(observer => {
|
|
8077
9620
|
if (recordingFile.session) {
|
|
@@ -8081,7 +9624,7 @@ class RecordingService {
|
|
|
8081
9624
|
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
8082
9625
|
if (resp.body) {
|
|
8083
9626
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
8084
|
-
recordingFile
|
|
9627
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(ab, null));
|
|
8085
9628
|
if (this.debugDelay > 0) {
|
|
8086
9629
|
window.setTimeout(() => {
|
|
8087
9630
|
observer.next(recordingFile);
|
|
@@ -8126,7 +9669,8 @@ class RecordingService {
|
|
|
8126
9669
|
// Do not use Promise version, which does not work with Safari 13
|
|
8127
9670
|
if (resp.body) {
|
|
8128
9671
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
8129
|
-
let
|
|
9672
|
+
let adh = new AudioDataHolder(ab, null);
|
|
9673
|
+
let rf = new SprRecordingFile(sessId, itemcode, version, adh);
|
|
8130
9674
|
if (this.debugDelay > 0) {
|
|
8131
9675
|
window.setTimeout(() => {
|
|
8132
9676
|
observer.next(rf);
|
|
@@ -8246,14 +9790,9 @@ const DEFAULT_PRE_REC_DELAY = 1000;
|
|
|
8246
9790
|
const DEFAULT_POST_REC_DELAY = 500;
|
|
8247
9791
|
class SessionManager extends BasicRecorder {
|
|
8248
9792
|
constructor(changeDetectorRef, renderer, dialog, sessionService, recFileService, uploader, config) {
|
|
8249
|
-
super(dialog, sessionService, uploader, config);
|
|
8250
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
9793
|
+
super(changeDetectorRef, dialog, sessionService, uploader, config);
|
|
8251
9794
|
this.renderer = renderer;
|
|
8252
|
-
this.dialog = dialog;
|
|
8253
|
-
this.sessionService = sessionService;
|
|
8254
9795
|
this.recFileService = recFileService;
|
|
8255
|
-
this.uploader = uploader;
|
|
8256
|
-
this.config = config;
|
|
8257
9796
|
this.enableUploadRecordings = true;
|
|
8258
9797
|
this.enableDownloadRecordings = false;
|
|
8259
9798
|
this.status = 0 /* BLOCKED */;
|
|
@@ -8287,7 +9826,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8287
9826
|
};
|
|
8288
9827
|
}
|
|
8289
9828
|
ngOnDestroy() {
|
|
8290
|
-
console.debug("Com destroy, disable wake lock.")
|
|
9829
|
+
//console.debug("Com destroy, disable wake lock.")
|
|
8291
9830
|
this.disableWakeLockCond();
|
|
8292
9831
|
this.destroyed = true;
|
|
8293
9832
|
// TODO stop capture /playback
|
|
@@ -8418,7 +9957,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8418
9957
|
progressPercentValue() {
|
|
8419
9958
|
let v = 100;
|
|
8420
9959
|
if (this.items) {
|
|
8421
|
-
v = this.promptIndex * 100 / (this.items.length - 1);
|
|
9960
|
+
v = this.promptIndex * 100 / (this.items.length() - 1);
|
|
8422
9961
|
}
|
|
8423
9962
|
return v;
|
|
8424
9963
|
}
|
|
@@ -8432,9 +9971,6 @@ class SessionManager extends BasicRecorder {
|
|
|
8432
9971
|
return ((this._session != null) && (this._session.type === 'TEST_DEF_A') && (this.audioDevices != null) && this.audioDevices.length > 0);
|
|
8433
9972
|
}
|
|
8434
9973
|
set controlAudioPlayer(controlAudioPlayer) {
|
|
8435
|
-
if (this._controlAudioPlayer) {
|
|
8436
|
-
//this._controlAudioPlayer.listener=null;
|
|
8437
|
-
}
|
|
8438
9974
|
this._controlAudioPlayer = controlAudioPlayer;
|
|
8439
9975
|
if (this._controlAudioPlayer) {
|
|
8440
9976
|
this._controlAudioPlayer.listener = this;
|
|
@@ -8519,6 +10055,8 @@ class SessionManager extends BasicRecorder {
|
|
|
8519
10055
|
this.autorecording = true;
|
|
8520
10056
|
}
|
|
8521
10057
|
if (this.ac != null) {
|
|
10058
|
+
// Hide loading hint on livelevel display
|
|
10059
|
+
this.audioFetching = false;
|
|
8522
10060
|
if (!this.ac.opened) {
|
|
8523
10061
|
if (this._selectedDeviceId) {
|
|
8524
10062
|
console.log("Open session with audio device Id: \'" + this._selectedDeviceId + "\' for " + this._channelCount + " channels");
|
|
@@ -8535,7 +10073,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8535
10073
|
}
|
|
8536
10074
|
loadScript() {
|
|
8537
10075
|
this.promptItemCount = 0;
|
|
8538
|
-
this.items = new
|
|
10076
|
+
this.items = new SprItemsCache();
|
|
8539
10077
|
let ln = 0;
|
|
8540
10078
|
//TODO randomize not supported
|
|
8541
10079
|
for (let si = 0; si < this._script.sections.length; si++) {
|
|
@@ -8549,7 +10087,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8549
10087
|
let pi = pis[piSectIdx];
|
|
8550
10088
|
let promptAsStr = PromptitemUtil.toPlainTextString(pi);
|
|
8551
10089
|
let it = new Item$1(promptAsStr, section.training, (!pi.type || pi.type === 'recording'));
|
|
8552
|
-
this.items.
|
|
10090
|
+
this.items.addItem(it);
|
|
8553
10091
|
ln++;
|
|
8554
10092
|
}
|
|
8555
10093
|
}
|
|
@@ -8590,10 +10128,10 @@ class SessionManager extends BasicRecorder {
|
|
|
8590
10128
|
}
|
|
8591
10129
|
downloadRecording() {
|
|
8592
10130
|
if (this.displayRecFile) {
|
|
8593
|
-
let ab = this.displayRecFile.
|
|
10131
|
+
let ab = this.displayRecFile.audioDataHolder;
|
|
8594
10132
|
let ww = new WavWriter();
|
|
8595
|
-
if (ab) {
|
|
8596
|
-
let wavFile = ww.writeAsync(ab, (wavFile) => {
|
|
10133
|
+
if (ab === null || ab === void 0 ? void 0 : ab.buffer) {
|
|
10134
|
+
let wavFile = ww.writeAsync(ab.buffer, (wavFile) => {
|
|
8597
10135
|
let blob = new Blob([wavFile], { type: 'audio/wav' });
|
|
8598
10136
|
let rfUrl = URL.createObjectURL(blob);
|
|
8599
10137
|
let dataDnlLnk = this.renderer.createElement('a');
|
|
@@ -8616,7 +10154,10 @@ class SessionManager extends BasicRecorder {
|
|
|
8616
10154
|
set displayRecFile(displayRecFile) {
|
|
8617
10155
|
this._displayRecFile = displayRecFile;
|
|
8618
10156
|
if (this._displayRecFile) {
|
|
8619
|
-
|
|
10157
|
+
if (this.items) {
|
|
10158
|
+
this.items.currentRecordingFile = this._displayRecFile;
|
|
10159
|
+
}
|
|
10160
|
+
let ab = this._displayRecFile.audioDataHolder;
|
|
8620
10161
|
if (ab) {
|
|
8621
10162
|
this.displayAudioClip = new AudioClip(ab);
|
|
8622
10163
|
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
@@ -8624,27 +10165,46 @@ class SessionManager extends BasicRecorder {
|
|
|
8624
10165
|
else {
|
|
8625
10166
|
// clear for now ...
|
|
8626
10167
|
this.displayAudioClip = null;
|
|
8627
|
-
this.controlAudioPlayer
|
|
10168
|
+
if (this.controlAudioPlayer) {
|
|
10169
|
+
this.controlAudioPlayer.audioClip = null;
|
|
10170
|
+
}
|
|
8628
10171
|
if (this._controlAudioPlayer && this._session) {
|
|
8629
10172
|
//... and try to fetch from server
|
|
8630
|
-
this.
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8635
|
-
|
|
8636
|
-
|
|
10173
|
+
this.audioFetching = true;
|
|
10174
|
+
let rf = this._displayRecFile;
|
|
10175
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this._controlAudioPlayer.context, this._session.project, rf).subscribe({
|
|
10176
|
+
next: (ab) => {
|
|
10177
|
+
this.audioFetching = false;
|
|
10178
|
+
let fabDh = null;
|
|
10179
|
+
if (ab) {
|
|
10180
|
+
if (rf && this.items) {
|
|
10181
|
+
if (SessionManager.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
10182
|
+
let aab = ArrayAudioBuffer.fromAudioBuffer(ab);
|
|
10183
|
+
fabDh = new AudioDataHolder(null, aab);
|
|
10184
|
+
}
|
|
10185
|
+
else {
|
|
10186
|
+
fabDh = new AudioDataHolder(ab);
|
|
10187
|
+
}
|
|
10188
|
+
this.items.setSprRecFileAudioData(rf, fabDh);
|
|
10189
|
+
}
|
|
10190
|
+
}
|
|
10191
|
+
else {
|
|
10192
|
+
// Should actually be handled by the error resolver
|
|
10193
|
+
this.statusMsg = 'Recording file could not be loaded.';
|
|
10194
|
+
this.statusAlertType = 'error';
|
|
10195
|
+
}
|
|
10196
|
+
if (fabDh) {
|
|
10197
|
+
// 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
|
|
10198
|
+
this.displayAudioClip = new AudioClip(fabDh);
|
|
10199
|
+
}
|
|
10200
|
+
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
10201
|
+
this.showRecording();
|
|
10202
|
+
}, error: err => {
|
|
10203
|
+
console.error("Could not load recording file from server: " + err);
|
|
10204
|
+
this.audioFetching = false;
|
|
10205
|
+
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
8637
10206
|
this.statusAlertType = 'error';
|
|
8638
10207
|
}
|
|
8639
|
-
if (fab) {
|
|
8640
|
-
this.displayAudioClip = new AudioClip(fab);
|
|
8641
|
-
}
|
|
8642
|
-
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
8643
|
-
this.showRecording();
|
|
8644
|
-
}, err => {
|
|
8645
|
-
console.error("Could not load recording file from server: " + err);
|
|
8646
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
8647
|
-
this.statusAlertType = 'error';
|
|
8648
10208
|
});
|
|
8649
10209
|
}
|
|
8650
10210
|
else {
|
|
@@ -8655,34 +10215,14 @@ class SessionManager extends BasicRecorder {
|
|
|
8655
10215
|
}
|
|
8656
10216
|
else {
|
|
8657
10217
|
this.displayAudioClip = null;
|
|
8658
|
-
this.controlAudioPlayer
|
|
10218
|
+
if (this.controlAudioPlayer) {
|
|
10219
|
+
this.controlAudioPlayer.audioClip = null;
|
|
10220
|
+
}
|
|
8659
10221
|
}
|
|
8660
10222
|
}
|
|
8661
10223
|
get displayRecFile() {
|
|
8662
10224
|
return this._displayRecFile;
|
|
8663
10225
|
}
|
|
8664
|
-
showRecording() {
|
|
8665
|
-
this.controlAudioPlayer.stop();
|
|
8666
|
-
if (this.displayAudioClip) {
|
|
8667
|
-
this.levelMeasure.calcBufferLevelInfos(this.displayAudioClip.buffer, LEVEL_BAR_INTERVALL_SECONDS).then((levelInfos) => {
|
|
8668
|
-
this.displayLevelInfos = levelInfos;
|
|
8669
|
-
this.changeDetectorRef.detectChanges();
|
|
8670
|
-
});
|
|
8671
|
-
this.playStartAction.disabled = false;
|
|
8672
|
-
}
|
|
8673
|
-
else {
|
|
8674
|
-
// TODO
|
|
8675
|
-
// Setting to null does not trigger a change if it was null before (happens after nextitem() in AUTOPROGRESS mode)
|
|
8676
|
-
// The level bar display does not clear, it shows the last captured stream
|
|
8677
|
-
this.displayLevelInfos = null;
|
|
8678
|
-
this.playStartAction.disabled = true;
|
|
8679
|
-
// Collapse audio signal display if open
|
|
8680
|
-
if (!this.audioSignalCollapsed) {
|
|
8681
|
-
this.audioSignalCollapsed = true;
|
|
8682
|
-
}
|
|
8683
|
-
}
|
|
8684
|
-
this.changeDetectorRef.detectChanges();
|
|
8685
|
-
}
|
|
8686
10226
|
isRecordingItem() {
|
|
8687
10227
|
return (this.promptItem != null && this.promptItem.type !== 'nonrecording');
|
|
8688
10228
|
}
|
|
@@ -8697,17 +10237,20 @@ class SessionManager extends BasicRecorder {
|
|
|
8697
10237
|
if (this.audioFetchSubscription) {
|
|
8698
10238
|
this.audioFetchSubscription.unsubscribe();
|
|
8699
10239
|
}
|
|
10240
|
+
this.audioFetching = false;
|
|
8700
10241
|
this.clearPrompt();
|
|
8701
10242
|
let isNonrecording = (this.promptItem.type === 'nonrecording');
|
|
8702
10243
|
if (isNonrecording || !this.section.promptphase || this.section.promptphase === 'IDLE') {
|
|
8703
10244
|
this.applyPrompt();
|
|
8704
10245
|
}
|
|
8705
10246
|
if (isNonrecording) {
|
|
10247
|
+
this.displayRecFile = null;
|
|
10248
|
+
this.displayRecFileVersion = 0;
|
|
8706
10249
|
this.startStopSignalState = 4 /* OFF */;
|
|
8707
10250
|
}
|
|
8708
10251
|
else {
|
|
8709
10252
|
if (this.items) {
|
|
8710
|
-
let it = this.items
|
|
10253
|
+
let it = this.items.getItem(this.promptIndex);
|
|
8711
10254
|
if (!it.recs) {
|
|
8712
10255
|
it.recs = new Array();
|
|
8713
10256
|
}
|
|
@@ -8724,13 +10267,13 @@ class SessionManager extends BasicRecorder {
|
|
|
8724
10267
|
this.displayRecFileVersion = 0;
|
|
8725
10268
|
}
|
|
8726
10269
|
}
|
|
8727
|
-
if (!temporary) {
|
|
8728
|
-
this.showRecording();
|
|
8729
|
-
}
|
|
8730
10270
|
if (!this.readonly) {
|
|
8731
10271
|
this.startStopSignalState = 0 /* IDLE */;
|
|
8732
10272
|
}
|
|
8733
10273
|
}
|
|
10274
|
+
if (!temporary) {
|
|
10275
|
+
this.showRecording();
|
|
10276
|
+
}
|
|
8734
10277
|
this.updateStartActionDisableState();
|
|
8735
10278
|
this.updateNavigationActions();
|
|
8736
10279
|
}
|
|
@@ -8768,7 +10311,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8768
10311
|
updateNavigationActions() {
|
|
8769
10312
|
let fwdNxtActionDisabled = true;
|
|
8770
10313
|
if (this.items) {
|
|
8771
|
-
let currRecs = this.items
|
|
10314
|
+
let currRecs = this.items.getItem(this._promptIndex).recs;
|
|
8772
10315
|
fwdNxtActionDisabled = !(currRecs != null && currRecs.length > 0);
|
|
8773
10316
|
}
|
|
8774
10317
|
this.transportActions.fwdNextAction.disabled = this.navigationDisabled || fwdNxtActionDisabled;
|
|
@@ -8782,10 +10325,10 @@ class SessionManager extends BasicRecorder {
|
|
|
8782
10325
|
newPrIdx = 0;
|
|
8783
10326
|
}
|
|
8784
10327
|
if (this.items != null) {
|
|
8785
|
-
let itRecs = this.items
|
|
10328
|
+
let itRecs = this.items.getItem(newPrIdx).recs;
|
|
8786
10329
|
while (itRecs != null && (itRecs.length > 0) && newPrIdx < this.promptItemCount) {
|
|
8787
10330
|
newPrIdx++;
|
|
8788
|
-
itRecs = this.items
|
|
10331
|
+
itRecs = this.items.getItem(newPrIdx).recs;
|
|
8789
10332
|
}
|
|
8790
10333
|
if (!itRecs || itRecs.length == 0) {
|
|
8791
10334
|
this.promptIndex = newPrIdx;
|
|
@@ -8806,6 +10349,23 @@ class SessionManager extends BasicRecorder {
|
|
|
8806
10349
|
}
|
|
8807
10350
|
}
|
|
8808
10351
|
started() {
|
|
10352
|
+
let ic = this.promptItem.itemcode;
|
|
10353
|
+
let rf = null;
|
|
10354
|
+
if (this._session && ic) {
|
|
10355
|
+
let sessId = this._session.sessionId;
|
|
10356
|
+
let cpIdx = this.promptIndex;
|
|
10357
|
+
if (this.items) {
|
|
10358
|
+
let it = this.items.getItem(cpIdx);
|
|
10359
|
+
if (!it.recs) {
|
|
10360
|
+
it.recs = new Array();
|
|
10361
|
+
}
|
|
10362
|
+
rf = new SprRecordingFile(sessId, ic, it.recs.length, null);
|
|
10363
|
+
//it.recs.push(rf);
|
|
10364
|
+
this.items.addSprRecFile(it, rf);
|
|
10365
|
+
this.items.currentRecordingFile = rf;
|
|
10366
|
+
}
|
|
10367
|
+
}
|
|
10368
|
+
this._recordingFile = rf;
|
|
8809
10369
|
this.status = 3 /* PRE_RECORDING */;
|
|
8810
10370
|
super.started();
|
|
8811
10371
|
this.startStopSignalState = 1 /* PRERECORDING */;
|
|
@@ -8932,13 +10492,14 @@ class SessionManager extends BasicRecorder {
|
|
|
8932
10492
|
if (rfd.recording && rfd.recording.itemcode) {
|
|
8933
10493
|
let prIdx = this.promptIndexByItemcode(rfd.recording.itemcode);
|
|
8934
10494
|
if (this.items != null && prIdx !== null) {
|
|
8935
|
-
let it = this.items
|
|
10495
|
+
let it = this.items.getItem(prIdx);
|
|
8936
10496
|
if (it && this._session) {
|
|
8937
|
-
if (!it.recs) {
|
|
8938
|
-
|
|
8939
|
-
}
|
|
10497
|
+
// if (!it.recs) {
|
|
10498
|
+
// it.recs = new Array<SprRecordingFile>();
|
|
10499
|
+
// }
|
|
8940
10500
|
let rf = new SprRecordingFile(this._session.sessionId, rfd.recording.itemcode, rfd.version, null);
|
|
8941
|
-
|
|
10501
|
+
rf.serverPersisted = true;
|
|
10502
|
+
this.items.addSprRecFile(it, rf);
|
|
8942
10503
|
}
|
|
8943
10504
|
else {
|
|
8944
10505
|
//console.debug("WARN: No recording item with code: \"" +rfd.recording.itemcode+ "\" found.");
|
|
@@ -8952,6 +10513,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8952
10513
|
addRecordingFileByPromptIndex(promptIndex, rf) {
|
|
8953
10514
|
}
|
|
8954
10515
|
stopped() {
|
|
10516
|
+
var _a;
|
|
8955
10517
|
this.updateStartActionDisableState();
|
|
8956
10518
|
this.transportActions.stopAction.disabled = true;
|
|
8957
10519
|
this.transportActions.nextAction.disabled = true;
|
|
@@ -8960,22 +10522,24 @@ class SessionManager extends BasicRecorder {
|
|
|
8960
10522
|
this.statusMsg = 'Recorded.';
|
|
8961
10523
|
this.startStopSignalState = 0 /* IDLE */;
|
|
8962
10524
|
let ad = null;
|
|
10525
|
+
let ada = null;
|
|
10526
|
+
let adh = null;
|
|
10527
|
+
let frameLen = 0;
|
|
8963
10528
|
if (this.ac != null) {
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
|
|
8967
|
-
let rf = null;
|
|
8968
|
-
if (this._session && ic) {
|
|
8969
|
-
let sessId = this._session.sessionId;
|
|
8970
|
-
let cpIdx = this.promptIndex;
|
|
8971
|
-
if (this.items) {
|
|
8972
|
-
let it = this.items[cpIdx];
|
|
8973
|
-
if (!it.recs) {
|
|
8974
|
-
it.recs = new Array();
|
|
8975
|
-
}
|
|
8976
|
-
rf = new SprRecordingFile(sessId, ic, it.recs.length, ad);
|
|
8977
|
-
it.recs.push(rf);
|
|
10529
|
+
if (this.uploadChunkSizeSeconds || SessionManager.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
10530
|
+
ada = this.ac.audioBufferArray();
|
|
10531
|
+
frameLen = ada.frameLen;
|
|
8978
10532
|
}
|
|
10533
|
+
else {
|
|
10534
|
+
ad = this.ac.audioBuffer();
|
|
10535
|
+
frameLen = ad.length;
|
|
10536
|
+
}
|
|
10537
|
+
adh = new AudioDataHolder(ad, ada);
|
|
10538
|
+
}
|
|
10539
|
+
// Use an own reference since the writing of the wave file is asynchronous and this._recordingFile might already contain the next recording
|
|
10540
|
+
let rf = this._recordingFile;
|
|
10541
|
+
if (rf && rf instanceof SprRecordingFile) {
|
|
10542
|
+
(_a = this.items) === null || _a === void 0 ? void 0 : _a.setSprRecFileAudioData(rf, adh);
|
|
8979
10543
|
if (this.enableUploadRecordings && !this.uploadChunkSizeSeconds) {
|
|
8980
10544
|
// TODO use SpeechRecorderconfig resp. RecfileService
|
|
8981
10545
|
// convert asynchronously to 16-bit integer PCM
|
|
@@ -8983,7 +10547,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8983
10547
|
// TODO duplicate conversion for manual download
|
|
8984
10548
|
//console.log("Build wav writer...");
|
|
8985
10549
|
this.processingRecording = true;
|
|
8986
|
-
if (ad
|
|
10550
|
+
if (ad) {
|
|
8987
10551
|
let ww = new WavWriter();
|
|
8988
10552
|
//new REST API URL
|
|
8989
10553
|
let apiEndPoint = '';
|
|
@@ -8996,7 +10560,7 @@ class SessionManager extends BasicRecorder {
|
|
|
8996
10560
|
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
8997
10561
|
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.itemCode;
|
|
8998
10562
|
ww.writeAsync(ad, (wavFile) => {
|
|
8999
|
-
this.postRecording(wavFile, recUrl);
|
|
10563
|
+
this.postRecording(wavFile, recUrl, rf);
|
|
9000
10564
|
this.processingRecording = false;
|
|
9001
10565
|
this.updateWakeLock();
|
|
9002
10566
|
});
|
|
@@ -9007,8 +10571,8 @@ class SessionManager extends BasicRecorder {
|
|
|
9007
10571
|
let complete = true;
|
|
9008
10572
|
if (this.items) {
|
|
9009
10573
|
// search backwards, to gain faster detection of incomplete state
|
|
9010
|
-
for (let ri = this.items.length - 1; ri >= 0; ri--) {
|
|
9011
|
-
let it = this.items
|
|
10574
|
+
for (let ri = this.items.length() - 1; ri >= 0; ri--) {
|
|
10575
|
+
let it = this.items.getItem(ri);
|
|
9012
10576
|
if (it.recording && !it.training && (!it.recs || it.recs.length == 0)) {
|
|
9013
10577
|
complete = false;
|
|
9014
10578
|
break;
|
|
@@ -9073,13 +10637,13 @@ class SessionManager extends BasicRecorder {
|
|
|
9073
10637
|
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
9074
10638
|
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.promptItem.itemcode + '/' + this.rfUuid + '/' + chunkIdx;
|
|
9075
10639
|
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
9076
|
-
this.postRecording(wavFile, recUrl);
|
|
10640
|
+
this.postRecording(wavFile, recUrl, null);
|
|
9077
10641
|
this.processingRecording = false;
|
|
9078
10642
|
});
|
|
9079
10643
|
}
|
|
9080
|
-
postRecording(wavFile, recUrl) {
|
|
10644
|
+
postRecording(wavFile, recUrl, rf) {
|
|
9081
10645
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
9082
|
-
let ul = new Upload(wavBlob, recUrl);
|
|
10646
|
+
let ul = new Upload(wavBlob, recUrl, rf);
|
|
9083
10647
|
this.uploader.queueUpload(ul);
|
|
9084
10648
|
}
|
|
9085
10649
|
stop() {
|
|
@@ -9115,7 +10679,7 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9115
10679
|
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
9116
10680
|
<app-sprprompting [projectName]="projectName"
|
|
9117
10681
|
[startStopSignalState]="startStopSignalState" [promptItem]="promptItem" [showPrompt]="showPrompt"
|
|
9118
|
-
[items]="items"
|
|
10682
|
+
[items]="items?.items"
|
|
9119
10683
|
[transportActions]="transportActions"
|
|
9120
10684
|
[selectedItemIdx]="promptIndex" (onItemSelect)="itemSelect($event)" (onNextItem)="nextItem()" (onPrevItem)="prevItem()"
|
|
9121
10685
|
[audioSignalCollapsed]="audioSignalCollapsed" [displayAudioClip]="displayAudioClip"
|
|
@@ -9129,10 +10693,10 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9129
10693
|
|
|
9130
10694
|
|
|
9131
10695
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}" [ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
9132
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="
|
|
10696
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="displayAudioClip?.levelInfos" [stateLoading]="audioFetching"></audio-levelbar>
|
|
9133
10697
|
<div fxLayout="row">
|
|
9134
10698
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
9135
|
-
[audioLoaded]="displayAudioClip?.
|
|
10699
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
9136
10700
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
9137
10701
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
9138
10702
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -9150,7 +10714,7 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9150
10714
|
<div fxFlex="1 1 30%" fxLayoutAlign="start center">
|
|
9151
10715
|
<app-sprstatusdisplay fxHide.xs [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"></app-sprstatusdisplay>
|
|
9152
10716
|
</div>
|
|
9153
|
-
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="items
|
|
10717
|
+
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="!items || items.length()>1"></app-sprtransport>
|
|
9154
10718
|
<div fxFlex="1 1 30%" fxLayoutAlign="end center" fxLayout="row">
|
|
9155
10719
|
<app-uploadstatus class="ricontrols" fxHide.xs fxLayoutAlign="end center" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
9156
10720
|
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
@@ -9158,7 +10722,7 @@ SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version
|
|
|
9158
10722
|
<app-readystateindicator class="ricontrols" fxLayoutAlign="end center" fxHide.xs [ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
9159
10723
|
</div>
|
|
9160
10724
|
</div>
|
|
9161
|
-
`, 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"] }] });
|
|
10725
|
+
`, 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"] }] });
|
|
9162
10726
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SessionManager, decorators: [{
|
|
9163
10727
|
type: Component,
|
|
9164
10728
|
args: [{
|
|
@@ -9169,7 +10733,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
9169
10733
|
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
9170
10734
|
<app-sprprompting [projectName]="projectName"
|
|
9171
10735
|
[startStopSignalState]="startStopSignalState" [promptItem]="promptItem" [showPrompt]="showPrompt"
|
|
9172
|
-
[items]="items"
|
|
10736
|
+
[items]="items?.items"
|
|
9173
10737
|
[transportActions]="transportActions"
|
|
9174
10738
|
[selectedItemIdx]="promptIndex" (onItemSelect)="itemSelect($event)" (onNextItem)="nextItem()" (onPrevItem)="prevItem()"
|
|
9175
10739
|
[audioSignalCollapsed]="audioSignalCollapsed" [displayAudioClip]="displayAudioClip"
|
|
@@ -9183,10 +10747,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
9183
10747
|
|
|
9184
10748
|
|
|
9185
10749
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}" [ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
9186
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="
|
|
10750
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [displayLevelInfos]="displayAudioClip?.levelInfos" [stateLoading]="audioFetching"></audio-levelbar>
|
|
9187
10751
|
<div fxLayout="row">
|
|
9188
10752
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
9189
|
-
[audioLoaded]="displayAudioClip?.
|
|
10753
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
9190
10754
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
9191
10755
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
9192
10756
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -9204,7 +10768,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
9204
10768
|
<div fxFlex="1 1 30%" fxLayoutAlign="start center">
|
|
9205
10769
|
<app-sprstatusdisplay fxHide.xs [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"></app-sprstatusdisplay>
|
|
9206
10770
|
</div>
|
|
9207
|
-
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="items
|
|
10771
|
+
<app-sprtransport fxFlex="10 0 30%" fxLayoutAlign="center center" [readonly]="readonly" [actions]="transportActions" [navigationEnabled]="!items || items.length()>1"></app-sprtransport>
|
|
9208
10772
|
<div fxFlex="1 1 30%" fxLayoutAlign="end center" fxLayout="row">
|
|
9209
10773
|
<app-uploadstatus class="ricontrols" fxHide.xs fxLayoutAlign="end center" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
9210
10774
|
[status]="uploadStatus" [awaitNewUpload]="processingRecording"></app-uploadstatus>
|
|
@@ -9497,7 +11061,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
9497
11061
|
this.uploadUpdate(ue);
|
|
9498
11062
|
};
|
|
9499
11063
|
window.addEventListener('beforeunload', (e) => {
|
|
9500
|
-
console.debug("Before page unload event");
|
|
11064
|
+
//console.debug("Before page unload event");
|
|
9501
11065
|
if (this.ready()) {
|
|
9502
11066
|
return;
|
|
9503
11067
|
}
|
|
@@ -9816,14 +11380,15 @@ class AudioDisplayPlayer {
|
|
|
9816
11380
|
if (this.aCtx) {
|
|
9817
11381
|
this.aCtx.decodeAudioData(data, (audioBuffer) => {
|
|
9818
11382
|
//console.debug("Audio Buffer Samplerate: ", audioBuffer.sampleRate)
|
|
9819
|
-
|
|
11383
|
+
let adh = new AudioDataHolder(audioBuffer, null);
|
|
11384
|
+
this.audioClip = new AudioClip(adh);
|
|
9820
11385
|
});
|
|
9821
11386
|
}
|
|
9822
11387
|
}
|
|
9823
|
-
set audioData(
|
|
9824
|
-
this.audioDisplayScrollPane.audioData =
|
|
9825
|
-
if (
|
|
9826
|
-
let clip = new AudioClip(
|
|
11388
|
+
set audioData(audioData) {
|
|
11389
|
+
this.audioDisplayScrollPane.audioData = audioData;
|
|
11390
|
+
if (audioData) {
|
|
11391
|
+
let clip = new AudioClip(audioData);
|
|
9827
11392
|
if (this.ap) {
|
|
9828
11393
|
this.ap.audioClip = clip;
|
|
9829
11394
|
this.playStartAction.disabled = false;
|
|
@@ -9845,7 +11410,7 @@ class AudioDisplayPlayer {
|
|
|
9845
11410
|
let audioData = null;
|
|
9846
11411
|
let sel = null;
|
|
9847
11412
|
if (audioClip) {
|
|
9848
|
-
audioData = audioClip.
|
|
11413
|
+
audioData = audioClip.audioDataHolder;
|
|
9849
11414
|
sel = audioClip.selection;
|
|
9850
11415
|
if (this._audioClip) {
|
|
9851
11416
|
this._audioClip.addSelectionObserver((ac) => {
|
|
@@ -10116,7 +11681,7 @@ class RecordingFileService {
|
|
|
10116
11681
|
// Do not use Promise version, which does not work with Safari 13
|
|
10117
11682
|
if (resp.body) {
|
|
10118
11683
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
10119
|
-
recordingFile
|
|
11684
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(ab));
|
|
10120
11685
|
if (this.debugDelay > 0) {
|
|
10121
11686
|
window.setTimeout(() => {
|
|
10122
11687
|
observer.next(recordingFile);
|
|
@@ -10166,7 +11731,7 @@ class RecordingFileService {
|
|
|
10166
11731
|
if (resp.body) {
|
|
10167
11732
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
10168
11733
|
if (rf) {
|
|
10169
|
-
rf
|
|
11734
|
+
RecordingFileUtils.setAudioData(rf, new AudioDataHolder(ab));
|
|
10170
11735
|
}
|
|
10171
11736
|
else {
|
|
10172
11737
|
observer.error('Recording file object null');
|
|
@@ -10217,7 +11782,8 @@ class RecordingFileService {
|
|
|
10217
11782
|
if (resp.body) {
|
|
10218
11783
|
aCtx.decodeAudioData(resp.body, ab => {
|
|
10219
11784
|
if (rf) {
|
|
10220
|
-
|
|
11785
|
+
let adh = new AudioDataHolder(ab);
|
|
11786
|
+
RecordingFileUtils.setAudioData(rf, adh);
|
|
10221
11787
|
}
|
|
10222
11788
|
else {
|
|
10223
11789
|
observer.error('Recording file object null');
|
|
@@ -10260,7 +11826,7 @@ class RecordingFileService {
|
|
|
10260
11826
|
// append UUID to make request URL unique to avoid localhost server caching
|
|
10261
11827
|
recUrl = recUrl + '.json?requestUUID=' + UUID.generate();
|
|
10262
11828
|
}
|
|
10263
|
-
console.log("Path request URL: "
|
|
11829
|
+
//console.log("Path request URL: "+recUrl)
|
|
10264
11830
|
return this.http.patch(recUrl, { editSampleRate: editSampleRate, editStartFrame: editStartFrame, editEndFrame: editEndFrame }, { withCredentials: this.withCredentials });
|
|
10265
11831
|
}
|
|
10266
11832
|
}
|
|
@@ -10280,6 +11846,7 @@ class RecordingFileMetaComponent {
|
|
|
10280
11846
|
constructor() {
|
|
10281
11847
|
this.sessionId = null;
|
|
10282
11848
|
this._recordingFile = null;
|
|
11849
|
+
this.stateLoading = false;
|
|
10283
11850
|
this.itemCode = null;
|
|
10284
11851
|
this.uuid = null;
|
|
10285
11852
|
}
|
|
@@ -10296,12 +11863,12 @@ class RecordingFileMetaComponent {
|
|
|
10296
11863
|
}
|
|
10297
11864
|
if (this.itemCode) {
|
|
10298
11865
|
this.uuid = null;
|
|
10299
|
-
console.debug("SprRecordingFile: "
|
|
11866
|
+
//console.debug("SprRecordingFile: "+this.itemCode+ " UUID: "+this.uuid)
|
|
10300
11867
|
}
|
|
10301
11868
|
else {
|
|
10302
11869
|
this.itemCode = null;
|
|
10303
11870
|
this.uuid = (_b = this._recordingFile) === null || _b === void 0 ? void 0 : _b.uuid;
|
|
10304
|
-
console.debug("RecordingFile: "
|
|
11871
|
+
//console.debug("RecordingFile: "+this.itemCode+ " UUID: "+this.uuid)
|
|
10305
11872
|
}
|
|
10306
11873
|
}
|
|
10307
11874
|
else {
|
|
@@ -10318,10 +11885,11 @@ class RecordingFileMetaComponent {
|
|
|
10318
11885
|
}
|
|
10319
11886
|
}
|
|
10320
11887
|
RecordingFileMetaComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileMetaComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10321
|
-
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: `
|
|
11888
|
+
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: `
|
|
10322
11889
|
<mat-card>
|
|
10323
11890
|
<mat-card-title>Recording file ID: {{recordingFile?.recordingFileId}}</mat-card-title>
|
|
10324
11891
|
<mat-card-content>
|
|
11892
|
+
<mat-progress-spinner *ngIf="stateLoading" mode="indeterminate" [diameter]="20"></mat-progress-spinner>
|
|
10325
11893
|
<table>
|
|
10326
11894
|
<tr *ngIf="itemCode">
|
|
10327
11895
|
<td>Itemcode:</td>
|
|
@@ -10351,7 +11919,7 @@ RecordingFileMetaComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0
|
|
|
10351
11919
|
</table>
|
|
10352
11920
|
</mat-card-content>
|
|
10353
11921
|
</mat-card>
|
|
10354
|
-
`, 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"] }] });
|
|
11922
|
+
`, 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"] }] });
|
|
10355
11923
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileMetaComponent, decorators: [{
|
|
10356
11924
|
type: Component,
|
|
10357
11925
|
args: [{
|
|
@@ -10360,6 +11928,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
10360
11928
|
<mat-card>
|
|
10361
11929
|
<mat-card-title>Recording file ID: {{recordingFile?.recordingFileId}}</mat-card-title>
|
|
10362
11930
|
<mat-card-content>
|
|
11931
|
+
<mat-progress-spinner *ngIf="stateLoading" mode="indeterminate" [diameter]="20"></mat-progress-spinner>
|
|
10363
11932
|
<table>
|
|
10364
11933
|
<tr *ngIf="itemCode">
|
|
10365
11934
|
<td>Itemcode:</td>
|
|
@@ -10394,6 +11963,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
10394
11963
|
}]
|
|
10395
11964
|
}], propDecorators: { sessionId: [{
|
|
10396
11965
|
type: Input
|
|
11966
|
+
}], stateLoading: [{
|
|
11967
|
+
type: Input
|
|
10397
11968
|
}], recordingFile: [{
|
|
10398
11969
|
type: Input
|
|
10399
11970
|
}] } });
|
|
@@ -10536,6 +12107,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10536
12107
|
this.recordingFileVersion = null;
|
|
10537
12108
|
this.routedByQueryParam = false;
|
|
10538
12109
|
this.posInList = null;
|
|
12110
|
+
this.audioFetching = false;
|
|
10539
12111
|
this.naviInfoLoading = false;
|
|
10540
12112
|
this.parentE = this.eRef.nativeElement;
|
|
10541
12113
|
this.firstAction = new Action('First');
|
|
@@ -10707,18 +12279,20 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10707
12279
|
this.updateActions();
|
|
10708
12280
|
let audioContext = AudioContextProvider.audioContextInstance();
|
|
10709
12281
|
if (audioContext) {
|
|
12282
|
+
this.audioFetching = true;
|
|
10710
12283
|
this.recordingFileService.fetchSprRecordingFile(audioContext, rfId).subscribe(value => {
|
|
12284
|
+
this.audioFetching = false;
|
|
10711
12285
|
this.status = 'Audio file loaded.';
|
|
10712
12286
|
let clip = null;
|
|
10713
12287
|
this.recordingFile = value;
|
|
10714
12288
|
if (this.recordingFile) {
|
|
10715
|
-
let ab = this.recordingFile.
|
|
12289
|
+
let ab = this.recordingFile.audioDataHolder;
|
|
10716
12290
|
if (ab) {
|
|
10717
12291
|
clip = new AudioClip(ab);
|
|
10718
12292
|
let esffsr = null;
|
|
10719
12293
|
let eeffsr = null;
|
|
10720
12294
|
let esr = null;
|
|
10721
|
-
if (clip.
|
|
12295
|
+
if (clip.audioDataHolder != null) {
|
|
10722
12296
|
esr = ab.sampleRate;
|
|
10723
12297
|
if (esr != null) {
|
|
10724
12298
|
esffsr = RecordingFileUtil.editStartFrameForSampleRate(this.recordingFile, esr);
|
|
@@ -10730,8 +12304,8 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10730
12304
|
sel = new Selection(ab.sampleRate, esffsr, eeffsr);
|
|
10731
12305
|
}
|
|
10732
12306
|
else {
|
|
10733
|
-
let ch0 = ab.getChannelData(0);
|
|
10734
|
-
let frameLength =
|
|
12307
|
+
//let ch0 = ab.getChannelData(0);
|
|
12308
|
+
let frameLength = ab.frameLen;
|
|
10735
12309
|
sel = new Selection(esr, esffsr, frameLength);
|
|
10736
12310
|
}
|
|
10737
12311
|
}
|
|
@@ -10745,6 +12319,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10745
12319
|
this.audioClip = clip;
|
|
10746
12320
|
this.loadedRecfile();
|
|
10747
12321
|
}, error1 => {
|
|
12322
|
+
this.audioFetching = false;
|
|
10748
12323
|
this.status = 'Error loading audio file!';
|
|
10749
12324
|
});
|
|
10750
12325
|
}
|
|
@@ -10854,7 +12429,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
10854
12429
|
for (let avRfV of avRf) {
|
|
10855
12430
|
os += avRfV.version + '/';
|
|
10856
12431
|
}
|
|
10857
|
-
console.debug(os);
|
|
12432
|
+
//console.debug(os);
|
|
10858
12433
|
}
|
|
10859
12434
|
}
|
|
10860
12435
|
this.updatePos();
|
|
@@ -10870,7 +12445,7 @@ RecordingFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0
|
|
|
10870
12445
|
|
|
10871
12446
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
10872
12447
|
<div class="ctrlview">
|
|
10873
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12448
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
10874
12449
|
|
|
10875
12450
|
<audio-display-control [audioClip]="audioClip"
|
|
10876
12451
|
[playStartAction]="playStartAction"
|
|
@@ -10883,7 +12458,7 @@ RecordingFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0
|
|
|
10883
12458
|
[zoomFitToPanelAction]="zoomFitToPanelAction"></audio-display-control>
|
|
10884
12459
|
<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>
|
|
10885
12460
|
</div>
|
|
10886
|
-
`, 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"] }] });
|
|
12461
|
+
`, 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"] }] });
|
|
10887
12462
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileViewComponent, decorators: [{
|
|
10888
12463
|
type: Component,
|
|
10889
12464
|
args: [{
|
|
@@ -10892,7 +12467,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
10892
12467
|
|
|
10893
12468
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
10894
12469
|
<div class="ctrlview">
|
|
10895
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12470
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
10896
12471
|
|
|
10897
12472
|
<audio-display-control [audioClip]="audioClip"
|
|
10898
12473
|
[playStartAction]="playStartAction"
|
|
@@ -10986,7 +12561,7 @@ class RecordingFileUI extends RecordingFileViewComponent {
|
|
|
10986
12561
|
applySelection() {
|
|
10987
12562
|
var _a;
|
|
10988
12563
|
if (this.audioClip) {
|
|
10989
|
-
let ab = this.audioClip.
|
|
12564
|
+
let ab = this.audioClip.audioDataHolder;
|
|
10990
12565
|
let s = this.audioClip.selection;
|
|
10991
12566
|
if (ab && ((_a = this.recordingFile) === null || _a === void 0 ? void 0 : _a.recordingFileId)) {
|
|
10992
12567
|
let sr = null;
|
|
@@ -11024,7 +12599,7 @@ RecordingFileUI.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
|
|
|
11024
12599
|
|
|
11025
12600
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
11026
12601
|
<div class="ctrlview">
|
|
11027
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12602
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
11028
12603
|
<audio-display-control [audioClip]="audioClip"
|
|
11029
12604
|
[playStartAction]="playStartAction"
|
|
11030
12605
|
[playSelectionAction]="playSelectionAction"
|
|
@@ -11038,7 +12613,7 @@ RecordingFileUI.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", versio
|
|
|
11038
12613
|
</div>
|
|
11039
12614
|
|
|
11040
12615
|
<button mat-raised-button color="accent" (click)="applySelection()" [disabled]="editSaved">{{this.applyButtonText()}}</button>
|
|
11041
|
-
`, 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"] }] });
|
|
12616
|
+
`, 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"] }] });
|
|
11042
12617
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: RecordingFileUI, decorators: [{
|
|
11043
12618
|
type: Component,
|
|
11044
12619
|
args: [{
|
|
@@ -11049,7 +12624,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
11049
12624
|
|
|
11050
12625
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
11051
12626
|
<div class="ctrlview">
|
|
11052
|
-
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile"></app-recording-file-meta>
|
|
12627
|
+
<app-recording-file-meta [sessionId]="sessionId" [recordingFile]="recordingFile" [stateLoading]="audioFetching"></app-recording-file-meta>
|
|
11053
12628
|
<audio-display-control [audioClip]="audioClip"
|
|
11054
12629
|
[playStartAction]="playStartAction"
|
|
11055
12630
|
[playSelectionAction]="playSelectionAction"
|
|
@@ -11106,7 +12681,8 @@ class MediaUtils {
|
|
|
11106
12681
|
|
|
11107
12682
|
class RecordingList {
|
|
11108
12683
|
constructor() {
|
|
11109
|
-
|
|
12684
|
+
//private recordingList:Array<RecordingFile>=new Array<RecordingFile>();
|
|
12685
|
+
this.recordingList = new RecFilesCache();
|
|
11110
12686
|
//cols=['index','length','samples','samplerate','action'];
|
|
11111
12687
|
this.cols = ['index', 'startedDate', 'length', 'action'];
|
|
11112
12688
|
this.selectDisabled = false;
|
|
@@ -11118,7 +12694,7 @@ class RecordingList {
|
|
|
11118
12694
|
this.buildDataSource();
|
|
11119
12695
|
}
|
|
11120
12696
|
buildDataSource() {
|
|
11121
|
-
this.recordingList.sort((a, b) => {
|
|
12697
|
+
this.recordingList.recFiles.sort((a, b) => {
|
|
11122
12698
|
let cmp = 0;
|
|
11123
12699
|
let aD = null;
|
|
11124
12700
|
let bD = null;
|
|
@@ -11139,25 +12715,36 @@ class RecordingList {
|
|
|
11139
12715
|
}
|
|
11140
12716
|
return cmp;
|
|
11141
12717
|
});
|
|
11142
|
-
this.recordingListDataSource.data = this.recordingList;
|
|
12718
|
+
this.recordingListDataSource.data = this.recordingList.recFiles;
|
|
11143
12719
|
}
|
|
11144
|
-
|
|
11145
|
-
this.recordingList.
|
|
12720
|
+
addRecFile(rf) {
|
|
12721
|
+
this.recordingList.addRecFile(rf);
|
|
11146
12722
|
this.buildDataSource();
|
|
11147
12723
|
}
|
|
12724
|
+
setRecFileAudioData(recFile, adh) {
|
|
12725
|
+
this.recordingList.setRecFileAudioData(recFile, adh);
|
|
12726
|
+
}
|
|
11148
12727
|
selectRecordingFile(rf) {
|
|
12728
|
+
this.recordingList.currentRecordingFile = rf;
|
|
11149
12729
|
this.selectedRecordingFileChanged.emit(rf);
|
|
11150
12730
|
}
|
|
11151
12731
|
selectTop() {
|
|
11152
|
-
if (this.recordingList.length > 0) {
|
|
11153
|
-
this.selectRecordingFile(this.recordingList[0]);
|
|
12732
|
+
if (this.recordingList.recFiles.length > 0) {
|
|
12733
|
+
this.selectRecordingFile(this.recordingList.recFiles[0]);
|
|
11154
12734
|
}
|
|
11155
12735
|
}
|
|
11156
12736
|
lengthTimeFormatted(rf) {
|
|
11157
12737
|
var _a;
|
|
11158
12738
|
let str = '--:--:--';
|
|
11159
|
-
|
|
11160
|
-
|
|
12739
|
+
let tl = null;
|
|
12740
|
+
if (rf.timeLength) {
|
|
12741
|
+
tl = rf.timeLength;
|
|
12742
|
+
}
|
|
12743
|
+
else if (rf.frames && rf.audioDataHolder) {
|
|
12744
|
+
tl = rf.frames / ((_a = rf.audioDataHolder) === null || _a === void 0 ? void 0 : _a.sampleRate);
|
|
12745
|
+
}
|
|
12746
|
+
if (tl) {
|
|
12747
|
+
str = MediaUtils.toMediaTime(tl);
|
|
11161
12748
|
}
|
|
11162
12749
|
return str;
|
|
11163
12750
|
}
|
|
@@ -11243,8 +12830,11 @@ class RecorderCombiPane {
|
|
|
11243
12830
|
}
|
|
11244
12831
|
ngAfterViewInit() {
|
|
11245
12832
|
}
|
|
11246
|
-
|
|
11247
|
-
this.recordingListComp.
|
|
12833
|
+
addRecFile(rf) {
|
|
12834
|
+
this.recordingListComp.addRecFile(rf);
|
|
12835
|
+
}
|
|
12836
|
+
setRecFileAudioData(recFile, adh) {
|
|
12837
|
+
this.recordingListComp.setRecFileAudioData(recFile, adh);
|
|
11248
12838
|
}
|
|
11249
12839
|
selectRecordingFile(rf) {
|
|
11250
12840
|
this.selectedRecordingFileChanged.emit(rf);
|
|
@@ -11317,15 +12907,11 @@ class Item {
|
|
|
11317
12907
|
}
|
|
11318
12908
|
class AudioRecorder extends BasicRecorder {
|
|
11319
12909
|
constructor(changeDetectorRef, renderer, route, dialog, sessionService, recFileService, uploader, config) {
|
|
11320
|
-
super(dialog, sessionService, uploader, config);
|
|
11321
|
-
this.changeDetectorRef = changeDetectorRef;
|
|
12910
|
+
super(changeDetectorRef, dialog, sessionService, uploader, config);
|
|
11322
12911
|
this.renderer = renderer;
|
|
11323
12912
|
this.route = route;
|
|
11324
|
-
this.dialog = dialog;
|
|
11325
|
-
this.sessionService = sessionService;
|
|
11326
12913
|
this.recFileService = recFileService;
|
|
11327
12914
|
this.uploader = uploader;
|
|
11328
|
-
this.config = config;
|
|
11329
12915
|
this._project = null;
|
|
11330
12916
|
this.projectName = null;
|
|
11331
12917
|
this.enableUploadRecordings = true;
|
|
@@ -11508,13 +13094,15 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11508
13094
|
if (rfs) {
|
|
11509
13095
|
if (rfs instanceof Array) {
|
|
11510
13096
|
rfs.forEach((rf) => {
|
|
13097
|
+
// the list comes from the server, asssuem all recording files as server persisted
|
|
13098
|
+
rf.serverPersisted = true;
|
|
11511
13099
|
if (rf.startedDate) {
|
|
11512
13100
|
rf._startedAsDateObj = new Date(rf.startedDate);
|
|
11513
13101
|
}
|
|
11514
13102
|
if (rf.date) {
|
|
11515
13103
|
rf._dateAsDateObj = new Date(rf.date);
|
|
11516
13104
|
}
|
|
11517
|
-
this.recorderCombiPane.
|
|
13105
|
+
this.recorderCombiPane.addRecFile(rf);
|
|
11518
13106
|
});
|
|
11519
13107
|
}
|
|
11520
13108
|
else {
|
|
@@ -11568,6 +13156,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11568
13156
|
return this._project;
|
|
11569
13157
|
}
|
|
11570
13158
|
selectRecordingFile(rf) {
|
|
13159
|
+
this.audioFetching = false;
|
|
11571
13160
|
this.displayRecFile = rf;
|
|
11572
13161
|
}
|
|
11573
13162
|
uploadUpdate(ue) {
|
|
@@ -11589,9 +13178,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11589
13178
|
this.changeDetectorRef.detectChanges();
|
|
11590
13179
|
}
|
|
11591
13180
|
set controlAudioPlayer(controlAudioPlayer) {
|
|
11592
|
-
if (this._controlAudioPlayer) {
|
|
11593
|
-
//this._controlAudioPlayer.listener=null;
|
|
11594
|
-
}
|
|
11595
13181
|
this._controlAudioPlayer = controlAudioPlayer;
|
|
11596
13182
|
if (this._controlAudioPlayer) {
|
|
11597
13183
|
this._controlAudioPlayer.listener = this;
|
|
@@ -11671,6 +13257,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11671
13257
|
this.displayAudioClip = null;
|
|
11672
13258
|
this.showRecording();
|
|
11673
13259
|
if (this.ac) {
|
|
13260
|
+
this.audioFetching = false;
|
|
11674
13261
|
if (!this.ac.opened) {
|
|
11675
13262
|
if (this._selectedDeviceId) {
|
|
11676
13263
|
console.log("Open session with audio device Id: \'" + this._selectedDeviceId + "\' for " + this._channelCount + " channels");
|
|
@@ -11687,10 +13274,10 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11687
13274
|
}
|
|
11688
13275
|
downloadRecording() {
|
|
11689
13276
|
if (this.displayRecFile) {
|
|
11690
|
-
let ab = this.displayRecFile.
|
|
13277
|
+
let ab = this.displayRecFile.audioDataHolder;
|
|
11691
13278
|
let ww = new WavWriter();
|
|
11692
|
-
if (ab) {
|
|
11693
|
-
let wavFile = ww.writeAsync(ab, (wavFile) => {
|
|
13279
|
+
if (ab === null || ab === void 0 ? void 0 : ab.buffer) {
|
|
13280
|
+
let wavFile = ww.writeAsync(ab.buffer, (wavFile) => {
|
|
11694
13281
|
let blob = new Blob([wavFile], { type: 'audio/wav' });
|
|
11695
13282
|
let rfUrl = URL.createObjectURL(blob);
|
|
11696
13283
|
let dataDnlLnk = this.renderer.createElement('a');
|
|
@@ -11713,35 +13300,50 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11713
13300
|
set displayRecFile(displayRecFile) {
|
|
11714
13301
|
this._displayRecFile = displayRecFile;
|
|
11715
13302
|
if (this._displayRecFile) {
|
|
11716
|
-
let
|
|
11717
|
-
if (
|
|
11718
|
-
this.displayAudioClip = new AudioClip(
|
|
13303
|
+
let adh = this._displayRecFile.audioDataHolder;
|
|
13304
|
+
if (adh) {
|
|
13305
|
+
this.displayAudioClip = new AudioClip(adh);
|
|
13306
|
+
console.debug(" set recording file: display audio clip set");
|
|
11719
13307
|
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
11720
13308
|
}
|
|
11721
13309
|
else {
|
|
11722
13310
|
// clear for now ...
|
|
11723
13311
|
this.displayAudioClip = null;
|
|
13312
|
+
console.debug("set recording file: display audio clip null");
|
|
11724
13313
|
this.controlAudioPlayer.audioClip = null;
|
|
11725
13314
|
if (this._controlAudioPlayer && this._session) {
|
|
11726
13315
|
//... and try to fetch from server
|
|
11727
|
-
this.
|
|
11728
|
-
|
|
11729
|
-
|
|
11730
|
-
|
|
11731
|
-
|
|
11732
|
-
|
|
11733
|
-
|
|
13316
|
+
this.audioFetching = true;
|
|
13317
|
+
let rf = this._displayRecFile;
|
|
13318
|
+
let clip = this.displayAudioClip;
|
|
13319
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileAudioBuffer(this._controlAudioPlayer.context, this._session.project, rf).subscribe({
|
|
13320
|
+
next: ab => {
|
|
13321
|
+
this.audioFetching = false;
|
|
13322
|
+
let fabDh = null;
|
|
13323
|
+
if (ab) {
|
|
13324
|
+
if (rf) {
|
|
13325
|
+
fabDh = new AudioDataHolder(ab);
|
|
13326
|
+
this.recorderCombiPane.setRecFileAudioData(rf, fabDh);
|
|
13327
|
+
}
|
|
13328
|
+
}
|
|
13329
|
+
else {
|
|
13330
|
+
console.error('Recording file could not be loaded.');
|
|
13331
|
+
this.statusMsg = 'Recording file could not be loaded.';
|
|
13332
|
+
this.statusAlertType = 'error';
|
|
13333
|
+
}
|
|
13334
|
+
if (fabDh) {
|
|
13335
|
+
// 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
|
|
13336
|
+
this.displayAudioClip = new AudioClip(fabDh);
|
|
13337
|
+
//console.debug("set recording file: display audio clip from fetched audio buffer");
|
|
13338
|
+
}
|
|
13339
|
+
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
13340
|
+
this.showRecording();
|
|
13341
|
+
}, error: err => {
|
|
13342
|
+
console.error("Could not load recording file from server: " + err);
|
|
13343
|
+
this.audioFetching = false;
|
|
13344
|
+
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
11734
13345
|
this.statusAlertType = 'error';
|
|
11735
13346
|
}
|
|
11736
|
-
if (fab) {
|
|
11737
|
-
this.displayAudioClip = new AudioClip(fab);
|
|
11738
|
-
}
|
|
11739
|
-
this.controlAudioPlayer.audioClip = this.displayAudioClip;
|
|
11740
|
-
this.showRecording();
|
|
11741
|
-
}, err => {
|
|
11742
|
-
console.error("Could not load recording file from server: " + err);
|
|
11743
|
-
this.statusMsg = 'Recording file could not be loaded: ' + err;
|
|
11744
|
-
this.statusAlertType = 'error';
|
|
11745
13347
|
});
|
|
11746
13348
|
}
|
|
11747
13349
|
else {
|
|
@@ -11751,6 +13353,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11751
13353
|
}
|
|
11752
13354
|
}
|
|
11753
13355
|
else {
|
|
13356
|
+
console.debug("recording file null");
|
|
11754
13357
|
this.displayAudioClip = null;
|
|
11755
13358
|
this.controlAudioPlayer.audioClip = null;
|
|
11756
13359
|
}
|
|
@@ -11759,28 +13362,6 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11759
13362
|
get displayRecFile() {
|
|
11760
13363
|
return this._displayRecFile;
|
|
11761
13364
|
}
|
|
11762
|
-
showRecording() {
|
|
11763
|
-
this.controlAudioPlayer.stop();
|
|
11764
|
-
if (this.displayAudioClip) {
|
|
11765
|
-
this.levelMeasure.calcBufferLevelInfos(this.displayAudioClip.buffer, LEVEL_BAR_INTERVALL_SECONDS).then((levelInfos) => {
|
|
11766
|
-
this.displayLevelInfos = levelInfos;
|
|
11767
|
-
this.changeDetectorRef.detectChanges();
|
|
11768
|
-
});
|
|
11769
|
-
this.playStartAction.disabled = false;
|
|
11770
|
-
}
|
|
11771
|
-
else {
|
|
11772
|
-
// TODO
|
|
11773
|
-
// Setting to null does not trigger a change if it was null before (happens after nextitem() in AUTOPROGRESS mode)
|
|
11774
|
-
// The level bar display does not clear, it shows the last captured stream
|
|
11775
|
-
this.displayLevelInfos = null;
|
|
11776
|
-
this.playStartAction.disabled = true;
|
|
11777
|
-
// Collapse audio signal display if open
|
|
11778
|
-
if (!this.audioSignalCollapsed) {
|
|
11779
|
-
this.audioSignalCollapsed = true;
|
|
11780
|
-
}
|
|
11781
|
-
}
|
|
11782
|
-
this.changeDetectorRef.detectChanges();
|
|
11783
|
-
}
|
|
11784
13365
|
updateStartActionDisableState() {
|
|
11785
13366
|
this.transportActions.startAction.disabled = !(this.ac);
|
|
11786
13367
|
}
|
|
@@ -11824,6 +13405,19 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11824
13405
|
super.started();
|
|
11825
13406
|
this.statusAlertType = 'info';
|
|
11826
13407
|
this.statusMsg = 'Recording...';
|
|
13408
|
+
if (!this.rfUuid) {
|
|
13409
|
+
this.rfUuid = UUID.generate();
|
|
13410
|
+
}
|
|
13411
|
+
let sessId = 0;
|
|
13412
|
+
if (this._session) {
|
|
13413
|
+
sessId = this._session.sessionId;
|
|
13414
|
+
}
|
|
13415
|
+
let rf = new RecordingFile(this.rfUuid, sessId, null);
|
|
13416
|
+
rf._startedAsDateObj = this.startedDate;
|
|
13417
|
+
if (rf._startedAsDateObj) {
|
|
13418
|
+
rf.startedDate = rf._startedAsDateObj.toString();
|
|
13419
|
+
}
|
|
13420
|
+
this._recordingFile = rf;
|
|
11827
13421
|
let maxRecordingTimeMs = MAX_RECORDING_TIME_MS;
|
|
11828
13422
|
this.maxRecTimerId = window.setTimeout(() => {
|
|
11829
13423
|
this.stopRecordingMaxRec();
|
|
@@ -11860,68 +13454,75 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11860
13454
|
this.transportActions.pauseAction.disabled = true;
|
|
11861
13455
|
this.statusAlertType = 'info';
|
|
11862
13456
|
this.statusMsg = 'Recorded.';
|
|
11863
|
-
let ad;
|
|
13457
|
+
let ad = null;
|
|
13458
|
+
let ada = null;
|
|
13459
|
+
let adh = null;
|
|
13460
|
+
let frameLen = 0;
|
|
11864
13461
|
if (this.ac) {
|
|
11865
|
-
|
|
13462
|
+
if (this.uploadChunkSizeSeconds || AudioRecorder.FORCE_ARRRAY_AUDIO_BUFFER) {
|
|
13463
|
+
ada = this.ac.audioBufferArray();
|
|
13464
|
+
frameLen = ada.frameLen;
|
|
13465
|
+
}
|
|
13466
|
+
else {
|
|
13467
|
+
ad = this.ac.audioBuffer();
|
|
13468
|
+
frameLen = ad.length;
|
|
13469
|
+
}
|
|
13470
|
+
adh = new AudioDataHolder(ad, ada);
|
|
11866
13471
|
let sessId = 0;
|
|
11867
13472
|
if (this._session) {
|
|
11868
13473
|
sessId = this._session.sessionId;
|
|
11869
13474
|
}
|
|
11870
|
-
if (
|
|
11871
|
-
this.
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
13475
|
+
if (this._recordingFile) {
|
|
13476
|
+
// Use an own reference since the writing of the wave file is asynchronous and this._recordingFile might already contain the next recording
|
|
13477
|
+
let rf = this._recordingFile;
|
|
13478
|
+
RecordingFileUtils.setAudioData(rf, adh);
|
|
13479
|
+
this.recorderCombiPane.addRecFile(rf);
|
|
13480
|
+
// Upload if upload enabled and not in chunked upload mode
|
|
13481
|
+
if (this.enableUploadRecordings && !this.uploadChunkSizeSeconds && rf != null && ad != null) {
|
|
13482
|
+
let apiEndPoint = '';
|
|
13483
|
+
if (this.config && this.config.apiEndPoint) {
|
|
13484
|
+
apiEndPoint = this.config.apiEndPoint;
|
|
13485
|
+
}
|
|
13486
|
+
if (apiEndPoint !== '') {
|
|
13487
|
+
apiEndPoint = apiEndPoint + '/';
|
|
13488
|
+
}
|
|
13489
|
+
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
13490
|
+
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.uuid;
|
|
13491
|
+
// convert asynchronously to 16-bit integer PCM
|
|
13492
|
+
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
13493
|
+
// TODO duplicate conversion for manual download
|
|
13494
|
+
this.processingRecording = true;
|
|
13495
|
+
let ww = new WavWriter();
|
|
13496
|
+
ww.writeAsync(ad, (wavFile) => {
|
|
13497
|
+
this.postRecordingMultipart(wavFile, recUrl, rf);
|
|
13498
|
+
this.processingRecording = false;
|
|
13499
|
+
this.updateWakeLock();
|
|
13500
|
+
this.changeDetectorRef.detectChanges();
|
|
13501
|
+
});
|
|
11889
13502
|
}
|
|
11890
|
-
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11891
|
-
let recUrl = sessionsUrl + '/' + rf.session + '/' + RECFILE_API_CTX + '/' + rf.uuid;
|
|
11892
|
-
// convert asynchronously to 16-bit integer PCM
|
|
11893
|
-
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
11894
|
-
// TODO duplicate conversion for manual download
|
|
11895
|
-
this.processingRecording = true;
|
|
11896
|
-
let ww = new WavWriter();
|
|
11897
|
-
ww.writeAsync(ad, (wavFile) => {
|
|
11898
|
-
this.postRecordingMultipart(wavFile, rf.uuid, rf.session, rf._startedAsDateObj, recUrl);
|
|
11899
|
-
this.processingRecording = false;
|
|
11900
|
-
this.updateWakeLock();
|
|
11901
|
-
this.changeDetectorRef.detectChanges();
|
|
11902
|
-
});
|
|
11903
13503
|
}
|
|
11904
13504
|
}
|
|
13505
|
+
this.displayRecFile = this._recordingFile;
|
|
11905
13506
|
this.status = 1 /* IDLE */;
|
|
11906
13507
|
this.navigationDisabled = false;
|
|
11907
13508
|
this.updateNavigationActions();
|
|
11908
13509
|
this.updateWakeLock();
|
|
11909
13510
|
this.changeDetectorRef.detectChanges();
|
|
11910
13511
|
}
|
|
11911
|
-
postRecordingMultipart(wavFile,
|
|
13512
|
+
postRecordingMultipart(wavFile, recUrl, rf) {
|
|
11912
13513
|
let wavBlob = new Blob([wavFile], { type: 'audio/wav' });
|
|
11913
13514
|
let fd = new FormData();
|
|
11914
|
-
if (uuid) {
|
|
11915
|
-
fd.set('uuid', uuid);
|
|
13515
|
+
if (rf.uuid) {
|
|
13516
|
+
fd.set('uuid', rf.uuid);
|
|
11916
13517
|
}
|
|
11917
|
-
if (
|
|
11918
|
-
fd.set('sessionId',
|
|
13518
|
+
if (rf.session !== null) {
|
|
13519
|
+
fd.set('sessionId', rf.session.toString());
|
|
11919
13520
|
}
|
|
11920
|
-
if (
|
|
11921
|
-
fd.set('startedDate',
|
|
13521
|
+
if (rf._startedAsDateObj) {
|
|
13522
|
+
fd.set('startedDate', rf._startedAsDateObj.toJSON());
|
|
11922
13523
|
}
|
|
11923
13524
|
fd.set('audio', wavBlob);
|
|
11924
|
-
let ul = new Upload(fd, recUrl);
|
|
13525
|
+
let ul = new Upload(fd, recUrl, rf);
|
|
11925
13526
|
this.uploader.queueUpload(ul);
|
|
11926
13527
|
}
|
|
11927
13528
|
postChunkAudioBuffer(audioBuffer, chunkIdx) {
|
|
@@ -11938,8 +13539,9 @@ class AudioRecorder extends BasicRecorder {
|
|
|
11938
13539
|
}
|
|
11939
13540
|
let sessionsUrl = apiEndPoint + SessionService.SESSION_API_CTX;
|
|
11940
13541
|
let recUrl = sessionsUrl + '/' + ((_a = this.session) === null || _a === void 0 ? void 0 : _a.sessionId) + '/' + RECFILE_API_CTX + '/' + this.rfUuid + '/' + chunkIdx;
|
|
13542
|
+
let rf = this._recordingFile;
|
|
11941
13543
|
ww.writeAsync(audioBuffer, (wavFile) => {
|
|
11942
|
-
this.postRecording(wavFile, recUrl);
|
|
13544
|
+
this.postRecording(wavFile, recUrl, rf);
|
|
11943
13545
|
this.processingRecording = false;
|
|
11944
13546
|
});
|
|
11945
13547
|
}
|
|
@@ -11988,11 +13590,11 @@ AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
|
|
|
11988
13590
|
|
|
11989
13591
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}"
|
|
11990
13592
|
[ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
11991
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()"
|
|
11992
|
-
[displayLevelInfos]="
|
|
13593
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [stateLoading]="audioFetching"
|
|
13594
|
+
[displayLevelInfos]="displayAudioClip?.levelInfos"></audio-levelbar>
|
|
11993
13595
|
<div fxLayout="row">
|
|
11994
13596
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
11995
|
-
[audioLoaded]="displayAudioClip?.
|
|
13597
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
11996
13598
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
11997
13599
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
11998
13600
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -12031,7 +13633,7 @@ AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version:
|
|
|
12031
13633
|
[ready]="dataSaved && !isActive()"></app-readystateindicator>
|
|
12032
13634
|
</div>
|
|
12033
13635
|
</div>
|
|
12034
|
-
`, 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"] }] });
|
|
13636
|
+
`, 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"] }] });
|
|
12035
13637
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: AudioRecorder, decorators: [{
|
|
12036
13638
|
type: Component,
|
|
12037
13639
|
args: [{
|
|
@@ -12054,11 +13656,11 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImpo
|
|
|
12054
13656
|
|
|
12055
13657
|
<div fxLayout="row" fxLayout.xs="column" [ngStyle]="{'height.px':100,'min-height.px': 100}"
|
|
12056
13658
|
[ngStyle.xs]="{'height.px':125,'min-height.px': 125}">
|
|
12057
|
-
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()"
|
|
12058
|
-
[displayLevelInfos]="
|
|
13659
|
+
<audio-levelbar fxFlex="1 0 1" [streamingMode]="isRecording()" [stateLoading]="audioFetching"
|
|
13660
|
+
[displayLevelInfos]="displayAudioClip?.levelInfos"></audio-levelbar>
|
|
12059
13661
|
<div fxLayout="row">
|
|
12060
13662
|
<spr-recordingitemcontrols fxFlex="10 0 1"
|
|
12061
|
-
[audioLoaded]="displayAudioClip?.
|
|
13663
|
+
[audioLoaded]="displayAudioClip?.audioDataHolder!==null"
|
|
12062
13664
|
[playStartAction]="controlAudioPlayer?.startAction"
|
|
12063
13665
|
[playStopAction]="controlAudioPlayer?.stopAction"
|
|
12064
13666
|
[peakDbLvl]="peakLevelInDb"
|
|
@@ -12338,20 +13940,20 @@ class SpeechrecorderngModule {
|
|
|
12338
13940
|
}
|
|
12339
13941
|
SpeechrecorderngModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
12340
13942
|
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,
|
|
12341
|
-
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] });
|
|
12342
|
-
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]] });
|
|
13943
|
+
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] });
|
|
13944
|
+
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]] });
|
|
12343
13945
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.3.11", ngImport: i0, type: SpeechrecorderngModule, decorators: [{
|
|
12344
13946
|
type: NgModule,
|
|
12345
13947
|
args: [{
|
|
12346
13948
|
declarations: [AudioSignal, Sonagram, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, Progress, SimpleTrafficLight, Recinstructions, Prompter, PromptContainer, PromptingContainer, Prompting, StatusDisplay,
|
|
12347
13949
|
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder],
|
|
12348
13950
|
exports: [MessageDialog, SpeechrecorderngComponent, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, AudioRecorder],
|
|
12349
|
-
imports: [RouterModule.forChild(SPR_ROUTES), FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule],
|
|
13951
|
+
imports: [RouterModule.forChild(SPR_ROUTES), FlexLayoutModule, CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule, MatMenuModule],
|
|
12350
13952
|
providers: [SessionService, ProjectService, ScriptService, RecordingService, RecordingFileService, SpeechRecorderUploader]
|
|
12351
13953
|
}]
|
|
12352
13954
|
}] });
|
|
12353
13955
|
|
|
12354
|
-
const VERSION = '
|
|
13956
|
+
const VERSION = '3.0.1';
|
|
12355
13957
|
|
|
12356
13958
|
/*
|
|
12357
13959
|
* Public API Surface of speechrecorderng
|