speechrecorderng 3.4.4 → 3.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/esm2020/lib/action/action.mjs +3 -3
- package/esm2020/lib/audio/audio_display.mjs +7 -9
- package/esm2020/lib/audio/audio_player.mjs +13 -26
- package/esm2020/lib/audio/capture/capture.mjs +244 -207
- package/esm2020/lib/audio/context.mjs +64 -2
- package/esm2020/lib/audio/io/stream.mjs +1 -1
- package/esm2020/lib/audio/net_audio_buffer.mjs +5 -9
- package/esm2020/lib/audio/playback/array_audio_buffer_source_node.mjs +2 -2
- package/esm2020/lib/audio/playback/audio_source_worklet_module_loader.mjs +2 -2
- package/esm2020/lib/audio/playback/inddb_audio_buffer_source_node.mjs +1 -1
- package/esm2020/lib/audio/playback/player.mjs +137 -96
- package/esm2020/lib/audio/ui/audio_display_control.mjs +1 -1
- package/esm2020/lib/audio/ui/container.mjs +3 -3
- package/esm2020/lib/db/inddb.mjs +1 -1
- package/esm2020/lib/net/uploader.mjs +31 -28
- package/esm2020/lib/speechrecorder/project/project.mjs +1 -1
- package/esm2020/lib/speechrecorder/project/project.service.mjs +4 -4
- package/esm2020/lib/speechrecorder/recordings/basic_recording.service.mjs +59 -56
- package/esm2020/lib/speechrecorder/recordings/recordings.service.mjs +151 -142
- package/esm2020/lib/speechrecorder/script/script.service.mjs +1 -1
- package/esm2020/lib/speechrecorder/session/audiorecorder.mjs +49 -99
- package/esm2020/lib/speechrecorder/session/basicrecorder.mjs +9 -2
- package/esm2020/lib/speechrecorder/session/controlpanel.mjs +13 -11
- package/esm2020/lib/speechrecorder/session/progress.mjs +1 -1
- package/esm2020/lib/speechrecorder/session/prompting.mjs +1 -1
- package/esm2020/lib/speechrecorder/session/recorder_combi_pane.mjs +1 -1
- package/esm2020/lib/speechrecorder/session/recording_list.mjs +1 -1
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-meta.component.mjs +3 -3
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-navi.component.mjs +3 -3
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-u-i.component.mjs +17 -16
- package/esm2020/lib/speechrecorder/session/recordingfile/recording-file-view.component.mjs +13 -14
- package/esm2020/lib/speechrecorder/session/recordingfile/recordingfile-service.mjs +145 -135
- package/esm2020/lib/speechrecorder/session/session.service.mjs +12 -9
- package/esm2020/lib/speechrecorder/session/sessionmanager.mjs +66 -70
- package/esm2020/lib/speechrecorder/startstopsignal/startstopsignal.mjs +1 -2
- package/esm2020/lib/speechrecorderng.component.mjs +10 -16
- package/esm2020/lib/speechrecorderng.module.mjs +1 -1
- package/esm2020/lib/spr.module.version.mjs +2 -2
- package/esm2020/lib/ui/recordingitem_display.mjs +2 -2
- package/fesm2015/speechrecorderng.mjs +1077 -976
- package/fesm2015/speechrecorderng.mjs.map +1 -1
- package/fesm2020/speechrecorderng.mjs +1074 -976
- package/fesm2020/speechrecorderng.mjs.map +1 -1
- package/lib/action/action.d.ts +1 -1
- package/lib/audio/audio_display.d.ts +1 -3
- package/lib/audio/audio_player.d.ts +0 -1
- package/lib/audio/capture/capture.d.ts +5 -4
- package/lib/audio/context.d.ts +2 -0
- package/lib/audio/io/stream.d.ts +1 -1
- package/lib/audio/net_audio_buffer.d.ts +2 -4
- package/lib/audio/playback/player.d.ts +3 -2
- package/lib/net/uploader.d.ts +6 -6
- package/lib/speechrecorder/project/project.d.ts +1 -0
- package/lib/speechrecorder/project/project.service.d.ts +4 -4
- package/lib/speechrecorder/recordings/basic_recording.service.d.ts +2 -2
- package/lib/speechrecorder/recordings/recordings.service.d.ts +8 -8
- package/lib/speechrecorder/script/script.service.d.ts +2 -2
- package/lib/speechrecorder/session/audiorecorder.d.ts +1 -2
- package/lib/speechrecorder/session/basicrecorder.d.ts +4 -1
- package/lib/speechrecorder/session/controlpanel.d.ts +1 -1
- package/lib/speechrecorder/session/recordingfile/recording-file-meta.component.d.ts +1 -0
- package/lib/speechrecorder/session/recordingfile/recordingfile-service.d.ts +2 -2
- package/lib/speechrecorder/session/session.service.d.ts +2 -2
- package/lib/speechrecorder/session/sessionmanager.d.ts +1 -0
- package/lib/spr.module.version.d.ts +1 -1
- package/package.json +1 -1
|
@@ -6,17 +6,15 @@ import { HttpErrorResponse, HttpHeaders, HttpClientModule } from '@angular/commo
|
|
|
6
6
|
import { timeout } from 'rxjs/operators';
|
|
7
7
|
import * as i1$1 from '@angular/common';
|
|
8
8
|
import { CommonModule } from '@angular/common';
|
|
9
|
-
import * as i1$2 from '@angular/router';
|
|
10
|
-
import { RouterModule } from '@angular/router';
|
|
11
9
|
import * as i4$1 from '@angular/material/checkbox';
|
|
12
10
|
import { MatCheckbox, MatCheckboxModule } from '@angular/material/checkbox';
|
|
13
11
|
import * as i2 from '@angular/material/icon';
|
|
14
12
|
import { MatIconModule } from '@angular/material/icon';
|
|
15
13
|
import * as i4 from '@angular/material/tooltip';
|
|
16
14
|
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
17
|
-
import * as i1$
|
|
15
|
+
import * as i1$2 from '@angular/cdk/layout';
|
|
18
16
|
import { Breakpoints } from '@angular/cdk/layout';
|
|
19
|
-
import * as i1$
|
|
17
|
+
import * as i1$3 from '@angular/material/dialog';
|
|
20
18
|
import { MAT_DIALOG_DATA, MatDialogModule } from '@angular/material/dialog';
|
|
21
19
|
import * as i3 from '@angular/material/button';
|
|
22
20
|
import { MatButtonModule } from '@angular/material/button';
|
|
@@ -25,13 +23,15 @@ import * as i3$1 from '@angular/material/progress-spinner';
|
|
|
25
23
|
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
|
|
26
24
|
import * as i7 from '@angular/material/progress-bar';
|
|
27
25
|
import { MatProgressBarModule } from '@angular/material/progress-bar';
|
|
26
|
+
import * as i4$2 from '@angular/router';
|
|
27
|
+
import { RouterModule } from '@angular/router';
|
|
28
28
|
import * as i3$2 from '@angular/material/card';
|
|
29
29
|
import { MatCardModule } from '@angular/material/card';
|
|
30
30
|
import { MatDividerModule } from '@angular/material/divider';
|
|
31
31
|
import { MatGridListModule } from '@angular/material/grid-list';
|
|
32
32
|
import * as i6 from '@angular/material/snack-bar';
|
|
33
33
|
import { MatSnackBarModule } from '@angular/material/snack-bar';
|
|
34
|
-
import * as i4$
|
|
34
|
+
import * as i4$3 from '@angular/material/table';
|
|
35
35
|
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
|
|
36
36
|
import { MatSelectModule } from '@angular/material/select';
|
|
37
37
|
import { MatInputModule } from '@angular/material/input';
|
|
@@ -95,7 +95,7 @@ class Action {
|
|
|
95
95
|
ctrl.disabled = this.disabled;
|
|
96
96
|
this.controls.push(ctrl);
|
|
97
97
|
if (actionEventName) {
|
|
98
|
-
ctrl.addEventListener(actionEventName, (
|
|
98
|
+
ctrl.addEventListener(actionEventName, () => {
|
|
99
99
|
this.perform();
|
|
100
100
|
});
|
|
101
101
|
}
|
|
@@ -103,7 +103,7 @@ class Action {
|
|
|
103
103
|
}
|
|
104
104
|
}
|
|
105
105
|
removeControl(ctrl) {
|
|
106
|
-
|
|
106
|
+
const i = this.controls.indexOf(ctrl);
|
|
107
107
|
if (i >= 0) {
|
|
108
108
|
this.controls = this.controls.splice(i, 1);
|
|
109
109
|
}
|
|
@@ -944,7 +944,7 @@ class ArrayAudioBufferSourceNode extends AudioSourceNode {
|
|
|
944
944
|
}
|
|
945
945
|
};
|
|
946
946
|
}
|
|
947
|
-
fillBuffer(
|
|
947
|
+
fillBuffer() {
|
|
948
948
|
if (this._arrayAudioBuffer && this._audioInputStream && this._aisBufs) {
|
|
949
949
|
let filled = this.filledFrames;
|
|
950
950
|
let bufLen = 0;
|
|
@@ -1741,7 +1741,7 @@ const aswpStr = "\n" +
|
|
|
1741
1741
|
"\n" +
|
|
1742
1742
|
" let copied=0;\n" +
|
|
1743
1743
|
" do{\n" +
|
|
1744
|
-
" if(this.currentAudioBufferAvail
|
|
1744
|
+
" if(this.currentAudioBufferAvail===0){\n" +
|
|
1745
1745
|
" let nxtBuff=this.audioBuffers.shift();\n" +
|
|
1746
1746
|
" if(nxtBuff){\n" +
|
|
1747
1747
|
" this.currentAudioBuffer=nxtBuff;\n" +
|
|
@@ -1973,9 +1973,8 @@ class IndexedDbAudioBufferSourceNode extends AudioSourceNode {
|
|
|
1973
1973
|
}
|
|
1974
1974
|
|
|
1975
1975
|
class NetAudioBuffer extends BasicAudioSource {
|
|
1976
|
-
constructor(
|
|
1976
|
+
constructor(_recFileService, _baseUrl, _channelCount, _sampleRate, _chunkFrameLen, _frameLen, _uuid = null, _orgFetchChunkFrameLen = _chunkFrameLen) {
|
|
1977
1977
|
super();
|
|
1978
|
-
this._audioContext = _audioContext;
|
|
1979
1978
|
this._recFileService = _recFileService;
|
|
1980
1979
|
this._baseUrl = _baseUrl;
|
|
1981
1980
|
this._channelCount = _channelCount;
|
|
@@ -1993,9 +1992,6 @@ class NetAudioBuffer extends BasicAudioSource {
|
|
|
1993
1992
|
get recFileService() {
|
|
1994
1993
|
return this._recFileService;
|
|
1995
1994
|
}
|
|
1996
|
-
get audioContext() {
|
|
1997
|
-
return this._audioContext;
|
|
1998
|
-
}
|
|
1999
1995
|
get baseUrl() {
|
|
2000
1996
|
return this._baseUrl;
|
|
2001
1997
|
}
|
|
@@ -2033,8 +2029,8 @@ class NetAudioBuffer extends BasicAudioSource {
|
|
|
2033
2029
|
toString() {
|
|
2034
2030
|
return "Indexed db audio buffer. Channels: " + this.channelCount + ", sample rate: " + this.sampleRate + ", chunk frame length: " + this._chunkFrameLen + ", number of chunks: " + this.chunkCount + ", frame length: " + this.frameLen + ", sealed: " + this.sealed();
|
|
2035
2031
|
}
|
|
2036
|
-
static fromChunkAudioBuffer(
|
|
2037
|
-
let nab = new NetAudioBuffer(
|
|
2032
|
+
static fromChunkAudioBuffer(recordingsService, baseUrl, ab, frameLen, orgFetchChunkFrameLen = ab.length) {
|
|
2033
|
+
let nab = new NetAudioBuffer(recordingsService, baseUrl, ab.numberOfChannels, ab.sampleRate, ab.length, frameLen, null, orgFetchChunkFrameLen);
|
|
2038
2034
|
nab.ready();
|
|
2039
2035
|
return nab;
|
|
2040
2036
|
}
|
|
@@ -2077,7 +2073,7 @@ class NetRandomAccessAudioStream {
|
|
|
2077
2073
|
}
|
|
2078
2074
|
chunk(baseUrl, ci, cb, errCb) {
|
|
2079
2075
|
let startFrame = ci * this._netAb.orgFetchChunkFrameLen;
|
|
2080
|
-
this._netAb.recFileService.chunkAudioRequest(
|
|
2076
|
+
this._netAb.recFileService.chunkAudioRequest(baseUrl, startFrame, this._netAb.orgFetchChunkFrameLen).subscribe({
|
|
2081
2077
|
next: (chDl) => {
|
|
2082
2078
|
if (chDl) {
|
|
2083
2079
|
const ab = chDl.decodedAudioBuffer;
|
|
@@ -2479,6 +2475,85 @@ class NetAudioBufferSourceNode extends AudioSourceNode {
|
|
|
2479
2475
|
}
|
|
2480
2476
|
}
|
|
2481
2477
|
|
|
2478
|
+
class AudioContextProvider {
|
|
2479
|
+
static audioContextInstance() {
|
|
2480
|
+
if (!this._audioContext) {
|
|
2481
|
+
let debugFail = false;
|
|
2482
|
+
if (!window.AudioContext || typeof window.AudioContext !== 'function' || debugFail) {
|
|
2483
|
+
this._audioContext = null;
|
|
2484
|
+
throw new Error('Browser does not support Web Audio API!');
|
|
2485
|
+
}
|
|
2486
|
+
else {
|
|
2487
|
+
console.debug("Get new audio context...");
|
|
2488
|
+
this._audioContext = new window.AudioContext();
|
|
2489
|
+
console.debug("Created new audio context.");
|
|
2490
|
+
this._audioContext.addEventListener('statechange', () => {
|
|
2491
|
+
console.debug("Audio context state changed: " + this._audioContext?.state);
|
|
2492
|
+
});
|
|
2493
|
+
console.debug("Created new audio context with state: " + this._audioContext?.state);
|
|
2494
|
+
}
|
|
2495
|
+
}
|
|
2496
|
+
return this._audioContext;
|
|
2497
|
+
}
|
|
2498
|
+
// public static audioContextInstanceRunning(audioContext?:AudioContext):Promise<AudioContext>{
|
|
2499
|
+
//
|
|
2500
|
+
// return new Promise<AudioContext>((resolve,reject)=>{
|
|
2501
|
+
// let aCtx=audioContext?audioContext:AudioContextProvider.audioContextInstance();
|
|
2502
|
+
// if(aCtx) {
|
|
2503
|
+
// if(aCtx.state==='closed') {
|
|
2504
|
+
// reject(new Error('Audio context already closed.'));
|
|
2505
|
+
// }else if(aCtx.state==='running') {
|
|
2506
|
+
// resolve(aCtx);
|
|
2507
|
+
// }else{
|
|
2508
|
+
// aCtx.resume().then(() => {
|
|
2509
|
+
// if(aCtx) {
|
|
2510
|
+
// resolve(aCtx);
|
|
2511
|
+
// }else{
|
|
2512
|
+
// reject(new Error('Could not get audio context'));
|
|
2513
|
+
// }
|
|
2514
|
+
// }).catch(() => {
|
|
2515
|
+
// reject(new Error('Could not resume audio context'));
|
|
2516
|
+
// })
|
|
2517
|
+
// }
|
|
2518
|
+
// }else{
|
|
2519
|
+
// reject(new Error('Could not get audio context from browser'));
|
|
2520
|
+
// }
|
|
2521
|
+
// });
|
|
2522
|
+
// }
|
|
2523
|
+
// public static decodeAudioData(data:ArrayBuffer,audioContext?:AudioContext):Promise<AudioBuffer>{
|
|
2524
|
+
// return new Promise<AudioBuffer>((resolve,reject)=>{
|
|
2525
|
+
// // decodeAudioData requires an audio context in running state
|
|
2526
|
+
// AudioContextProvider.audioContextInstanceRunning(audioContext).then(
|
|
2527
|
+
// (aCtx)=>{
|
|
2528
|
+
// // Do not use Promise version, which does not work with Safari 13
|
|
2529
|
+
// aCtx.decodeAudioData(data,decodedData => {
|
|
2530
|
+
// resolve(decodedData);
|
|
2531
|
+
// },(reason) => {
|
|
2532
|
+
// reject(reason);
|
|
2533
|
+
// });
|
|
2534
|
+
// }
|
|
2535
|
+
// ).catch((reason)=>{
|
|
2536
|
+
// reject(reason);
|
|
2537
|
+
// })
|
|
2538
|
+
// })
|
|
2539
|
+
// }
|
|
2540
|
+
static decodeAudioData(data) {
|
|
2541
|
+
return new Promise((resolve, reject) => {
|
|
2542
|
+
if (!this._offlineAudioContext) {
|
|
2543
|
+
this._offlineAudioContext = new OfflineAudioContext(1, 44100, 44100);
|
|
2544
|
+
}
|
|
2545
|
+
// Do not use Promise version, which does not work with Safari 13
|
|
2546
|
+
this._offlineAudioContext.decodeAudioData(data, decodedData => {
|
|
2547
|
+
resolve(decodedData);
|
|
2548
|
+
}, (reason) => {
|
|
2549
|
+
reject(reason);
|
|
2550
|
+
});
|
|
2551
|
+
});
|
|
2552
|
+
}
|
|
2553
|
+
}
|
|
2554
|
+
AudioContextProvider._audioContext = null;
|
|
2555
|
+
AudioContextProvider._offlineAudioContext = null;
|
|
2556
|
+
|
|
2482
2557
|
var EventType;
|
|
2483
2558
|
(function (EventType) {
|
|
2484
2559
|
EventType[EventType["CLOSED"] = 0] = "CLOSED";
|
|
@@ -2502,8 +2577,9 @@ class AudioPlayerEvent {
|
|
|
2502
2577
|
}
|
|
2503
2578
|
}
|
|
2504
2579
|
class AudioPlayer {
|
|
2505
|
-
constructor(
|
|
2580
|
+
constructor(listener) {
|
|
2506
2581
|
this.running = false;
|
|
2582
|
+
this.context = null;
|
|
2507
2583
|
this.ready = false;
|
|
2508
2584
|
this._audioClip = null;
|
|
2509
2585
|
this._audioSource = null;
|
|
@@ -2511,7 +2587,6 @@ class AudioPlayer {
|
|
|
2511
2587
|
this.sourceAudioWorkletNode = null;
|
|
2512
2588
|
this.playStartTime = null;
|
|
2513
2589
|
this.timerVar = null;
|
|
2514
|
-
this.context = context;
|
|
2515
2590
|
this.listener = listener;
|
|
2516
2591
|
this.bufSize = AudioPlayer.DEFAULT_BUFSIZE;
|
|
2517
2592
|
this.n = navigator;
|
|
@@ -2528,15 +2603,23 @@ class AudioPlayer {
|
|
|
2528
2603
|
this._stopAction = new Action('Stop');
|
|
2529
2604
|
this._stopAction.disabled = true;
|
|
2530
2605
|
this._stopAction.onAction = () => this.stop();
|
|
2531
|
-
this.context.addEventListener('statechange', (ev) => {
|
|
2532
|
-
if (this.context.state !== 'running') {
|
|
2533
|
-
this.stop();
|
|
2534
|
-
}
|
|
2535
|
-
});
|
|
2536
2606
|
}
|
|
2537
2607
|
get autoPlayOnSelectToggleAction() {
|
|
2538
2608
|
return this._autoPlayOnSelectToggleAction;
|
|
2539
2609
|
}
|
|
2610
|
+
_audioContext() {
|
|
2611
|
+
if (!this.context) {
|
|
2612
|
+
this.context = AudioContextProvider.audioContextInstance();
|
|
2613
|
+
if (this.context) {
|
|
2614
|
+
this.context.addEventListener('statechange', (ev) => {
|
|
2615
|
+
if (this.context && this.context.state !== 'running') {
|
|
2616
|
+
this.stop();
|
|
2617
|
+
}
|
|
2618
|
+
});
|
|
2619
|
+
}
|
|
2620
|
+
}
|
|
2621
|
+
return this.context;
|
|
2622
|
+
}
|
|
2540
2623
|
get startAction() {
|
|
2541
2624
|
return this._startAction;
|
|
2542
2625
|
}
|
|
@@ -2555,9 +2638,9 @@ class AudioPlayer {
|
|
|
2555
2638
|
chs = audioDataHolder.numberOfChannels;
|
|
2556
2639
|
if (chs > 0) {
|
|
2557
2640
|
length = audioDataHolder.frameLen;
|
|
2558
|
-
if (chs > this.context.destination.maxChannelCount) {
|
|
2559
|
-
|
|
2560
|
-
}
|
|
2641
|
+
//if (chs > this.context.destination.maxChannelCount) {
|
|
2642
|
+
// // TODO exception
|
|
2643
|
+
//}
|
|
2561
2644
|
}
|
|
2562
2645
|
this.audioSource = audioDataHolder.audioSource;
|
|
2563
2646
|
audioClip.addSelectionObserver((ac) => {
|
|
@@ -2577,16 +2660,11 @@ class AudioPlayer {
|
|
|
2577
2660
|
set audioSource(value) {
|
|
2578
2661
|
this.stop();
|
|
2579
2662
|
this._audioSource = value;
|
|
2580
|
-
if (this._audioSource
|
|
2581
|
-
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2585
|
-
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
2586
|
-
}
|
|
2587
|
-
}
|
|
2588
|
-
else {
|
|
2589
|
-
this._loadSourceWorkletAndInitStart();
|
|
2663
|
+
if (this._audioSource) {
|
|
2664
|
+
this.ready = true;
|
|
2665
|
+
this.updateStartActions();
|
|
2666
|
+
if (this.listener) {
|
|
2667
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
2590
2668
|
}
|
|
2591
2669
|
}
|
|
2592
2670
|
else {
|
|
@@ -2598,24 +2676,27 @@ class AudioPlayer {
|
|
|
2598
2676
|
}
|
|
2599
2677
|
}
|
|
2600
2678
|
_loadSourceWorkletAndInitStart() {
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
|
|
2606
|
-
this.listener
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
this.listener
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2679
|
+
if (this.context) {
|
|
2680
|
+
AudioSourceWorkletModuleLoader.loadModule(this.context).then(() => {
|
|
2681
|
+
//console.debug("Player ready. ( by Player::_loadSourceWorkletAndInitStart()");
|
|
2682
|
+
this.ready = true;
|
|
2683
|
+
this.updateStartActions();
|
|
2684
|
+
if (this.listener) {
|
|
2685
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
2686
|
+
}
|
|
2687
|
+
}).catch((error) => {
|
|
2688
|
+
this.ready = false;
|
|
2689
|
+
this.updateStartActions();
|
|
2690
|
+
if (this.listener) {
|
|
2691
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.CLOSED));
|
|
2692
|
+
}
|
|
2693
|
+
console.error('Could not add module ' + error);
|
|
2694
|
+
});
|
|
2695
|
+
}
|
|
2616
2696
|
}
|
|
2617
2697
|
_startAudioSourceWorkletNode() {
|
|
2618
|
-
|
|
2698
|
+
this._loadSourceWorkletAndInitStart();
|
|
2699
|
+
if (this.context && this.sourceAudioWorkletNode) {
|
|
2619
2700
|
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
2620
2701
|
let msg = 'Unknwon error';
|
|
2621
2702
|
if (ev instanceof ErrorEvent) {
|
|
@@ -2642,16 +2723,25 @@ class AudioPlayer {
|
|
|
2642
2723
|
}
|
|
2643
2724
|
}
|
|
2644
2725
|
start() {
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2726
|
+
this._audioContext();
|
|
2727
|
+
if (this.context) {
|
|
2728
|
+
if (!this._startAction.disabled && !this.running) {
|
|
2729
|
+
if (this.context.state === 'suspended') {
|
|
2730
|
+
this.context.resume().then(() => {
|
|
2731
|
+
this._start();
|
|
2732
|
+
}).catch((reason) => {
|
|
2733
|
+
console.error(reason.message());
|
|
2734
|
+
throw reason;
|
|
2735
|
+
});
|
|
2736
|
+
}
|
|
2737
|
+
else if (this.context.state === 'closed') {
|
|
2738
|
+
const msg = 'Error: Cannot start playback. Audio context is already closed!';
|
|
2739
|
+
console.error(msg);
|
|
2740
|
+
throw new Error(msg);
|
|
2741
|
+
}
|
|
2742
|
+
else {
|
|
2648
2743
|
this._start();
|
|
2649
|
-
}
|
|
2650
|
-
console.error('Could not resume audio context: ' + reason);
|
|
2651
|
-
});
|
|
2652
|
-
}
|
|
2653
|
-
else {
|
|
2654
|
-
this._start();
|
|
2744
|
+
}
|
|
2655
2745
|
}
|
|
2656
2746
|
}
|
|
2657
2747
|
}
|
|
@@ -2676,9 +2766,12 @@ class AudioPlayer {
|
|
|
2676
2766
|
}
|
|
2677
2767
|
}
|
|
2678
2768
|
startSelectionDisabled() {
|
|
2679
|
-
return !(this._audioClip &&
|
|
2769
|
+
return !(this._audioClip && !this.startAction.disabled && this._audioClip.selection);
|
|
2680
2770
|
}
|
|
2681
2771
|
_start(playSelection = false) {
|
|
2772
|
+
if (!this.context) {
|
|
2773
|
+
throw new Error("Could not get audio context!");
|
|
2774
|
+
}
|
|
2682
2775
|
if (this._audioSource instanceof AudioBufferSource) {
|
|
2683
2776
|
this.sourceBufferNode = this.context.createBufferSource();
|
|
2684
2777
|
this.sourceBufferNode.buffer = this._audioSource.audioBuffer;
|
|
@@ -2709,68 +2802,90 @@ class AudioPlayer {
|
|
|
2709
2802
|
}
|
|
2710
2803
|
}
|
|
2711
2804
|
else if (this._audioSource instanceof ArrayAudioBuffer || this._audioSource instanceof IndexedDbAudioBuffer || this._audioSource instanceof NetAudioBuffer) {
|
|
2712
|
-
this.
|
|
2713
|
-
|
|
2714
|
-
|
|
2715
|
-
|
|
2716
|
-
|
|
2717
|
-
|
|
2718
|
-
|
|
2719
|
-
const iasn = new IndexedDbAudioBufferSourceNode(this.context);
|
|
2720
|
-
iasn.inddbAudioBuffer = this._audioSource;
|
|
2721
|
-
this.sourceAudioWorkletNode = iasn;
|
|
2722
|
-
}
|
|
2723
|
-
else if (this._audioSource instanceof NetAudioBuffer) {
|
|
2724
|
-
const nabsn = new NetAudioBufferSourceNode(this.context);
|
|
2725
|
-
nabsn.netAudioBuffer = this._audioSource;
|
|
2726
|
-
this.sourceAudioWorkletNode = nabsn;
|
|
2727
|
-
}
|
|
2728
|
-
if (this.sourceAudioWorkletNode) {
|
|
2729
|
-
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
2730
|
-
let msg = 'Unknwon error';
|
|
2731
|
-
if (ev instanceof ErrorEvent) {
|
|
2732
|
-
msg = ev.message;
|
|
2805
|
+
AudioSourceWorkletModuleLoader.loadModule(this.context).then(() => {
|
|
2806
|
+
this.playStartTime = null;
|
|
2807
|
+
if (this.context) {
|
|
2808
|
+
if (this._audioSource instanceof ArrayAudioBuffer) {
|
|
2809
|
+
const aabsn = new ArrayAudioBufferSourceNode(this.context);
|
|
2810
|
+
aabsn.arrayAudioBuffer = this._audioSource;
|
|
2811
|
+
this.sourceAudioWorkletNode = aabsn;
|
|
2733
2812
|
}
|
|
2734
|
-
|
|
2735
|
-
|
|
2736
|
-
|
|
2813
|
+
else if (this._audioSource instanceof IndexedDbAudioBuffer) {
|
|
2814
|
+
const iasn = new IndexedDbAudioBufferSourceNode(this.context);
|
|
2815
|
+
iasn.inddbAudioBuffer = this._audioSource;
|
|
2816
|
+
this.sourceAudioWorkletNode = iasn;
|
|
2817
|
+
}
|
|
2818
|
+
else if (this._audioSource instanceof NetAudioBuffer) {
|
|
2819
|
+
const nabsn = new NetAudioBufferSourceNode(this.context);
|
|
2820
|
+
nabsn.netAudioBuffer = this._audioSource;
|
|
2821
|
+
this.sourceAudioWorkletNode = nabsn;
|
|
2822
|
+
}
|
|
2823
|
+
if (this.sourceAudioWorkletNode) {
|
|
2824
|
+
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
2825
|
+
let msg = 'Unknwon error';
|
|
2826
|
+
if (ev instanceof ErrorEvent) {
|
|
2827
|
+
msg = ev.message;
|
|
2828
|
+
}
|
|
2829
|
+
console.error("Audio source worklet error: " + msg);
|
|
2830
|
+
if (this.listener) {
|
|
2831
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.ERROR));
|
|
2832
|
+
}
|
|
2833
|
+
};
|
|
2834
|
+
this.sourceAudioWorkletNode.connect(this.context.destination); // this already starts playing
|
|
2835
|
+
this.sourceAudioWorkletNode.onended = () => this.onended();
|
|
2836
|
+
this.running = true;
|
|
2837
|
+
const ac = this._audioClip;
|
|
2838
|
+
let offset = 0;
|
|
2839
|
+
if (playSelection && ac && ac.selection) {
|
|
2840
|
+
const s = ac.selection;
|
|
2841
|
+
const sr = ac.audioDataHolder.sampleRate;
|
|
2842
|
+
offset = s.leftFrame / sr;
|
|
2843
|
+
const stopPosInsecs = s.rightFrame / sr;
|
|
2844
|
+
const dur = stopPosInsecs - offset;
|
|
2845
|
+
this.sourceAudioWorkletNode.start(0, offset, dur);
|
|
2846
|
+
}
|
|
2847
|
+
else {
|
|
2848
|
+
this.sourceAudioWorkletNode.start();
|
|
2849
|
+
}
|
|
2850
|
+
//this.playStartTime = this.context.currentTime - offset;
|
|
2851
|
+
this._startAction.disabled = true;
|
|
2852
|
+
this._startSelectionAction.disabled = true;
|
|
2853
|
+
this._stopAction.disabled = false;
|
|
2854
|
+
if (this.listener) {
|
|
2855
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.STARTED));
|
|
2856
|
+
}
|
|
2737
2857
|
}
|
|
2738
|
-
};
|
|
2739
|
-
this.sourceAudioWorkletNode.connect(this.context.destination); // this already starts playing
|
|
2740
|
-
this.sourceAudioWorkletNode.onended = () => this.onended();
|
|
2741
|
-
this.running = true;
|
|
2742
|
-
const ac = this._audioClip;
|
|
2743
|
-
let offset = 0;
|
|
2744
|
-
if (playSelection && ac && ac.selection) {
|
|
2745
|
-
const s = ac.selection;
|
|
2746
|
-
const sr = ac.audioDataHolder.sampleRate;
|
|
2747
|
-
offset = s.leftFrame / sr;
|
|
2748
|
-
const stopPosInsecs = s.rightFrame / sr;
|
|
2749
|
-
const dur = stopPosInsecs - offset;
|
|
2750
|
-
this.sourceAudioWorkletNode.start(0, offset, dur);
|
|
2751
|
-
}
|
|
2752
|
-
else {
|
|
2753
|
-
this.sourceAudioWorkletNode.start();
|
|
2754
2858
|
}
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
this.
|
|
2758
|
-
this.
|
|
2859
|
+
}).catch((error) => {
|
|
2860
|
+
console.error(error.message);
|
|
2861
|
+
this.ready = false;
|
|
2862
|
+
this.updateStartActions();
|
|
2759
2863
|
if (this.listener) {
|
|
2760
|
-
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.
|
|
2864
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.CLOSED));
|
|
2761
2865
|
}
|
|
2762
|
-
|
|
2866
|
+
throw error;
|
|
2867
|
+
});
|
|
2763
2868
|
}
|
|
2764
2869
|
}
|
|
2765
2870
|
startSelected() {
|
|
2871
|
+
this._audioContext();
|
|
2872
|
+
if (!this.context) {
|
|
2873
|
+
throw new Error("Could not get audio context!");
|
|
2874
|
+
}
|
|
2766
2875
|
if (!this._startAction.disabled && !this.running) {
|
|
2767
|
-
if (this.context.state
|
|
2876
|
+
if (this.context.state === 'suspended') {
|
|
2768
2877
|
this.context.resume().then(() => {
|
|
2769
2878
|
this._start(true);
|
|
2770
2879
|
}).catch((reason) => {
|
|
2771
|
-
console.error(
|
|
2880
|
+
console.error(reason.message);
|
|
2881
|
+
throw reason;
|
|
2772
2882
|
});
|
|
2773
2883
|
}
|
|
2884
|
+
else if (this.context.state === 'closed') {
|
|
2885
|
+
const msg = 'Error: Cannot start playback of selection. Audio context is already closed!';
|
|
2886
|
+
console.error(msg);
|
|
2887
|
+
throw new Error(msg);
|
|
2888
|
+
}
|
|
2774
2889
|
else {
|
|
2775
2890
|
this._start(true);
|
|
2776
2891
|
}
|
|
@@ -2807,7 +2922,7 @@ class AudioPlayer {
|
|
|
2807
2922
|
}
|
|
2808
2923
|
get playPositionTime() {
|
|
2809
2924
|
let ppt = null;
|
|
2810
|
-
if (this.playStartTime !== null) {
|
|
2925
|
+
if (this.context && this.playStartTime !== null) {
|
|
2811
2926
|
ppt = this.context.currentTime - this.playStartTime;
|
|
2812
2927
|
}
|
|
2813
2928
|
else if (this.sourceAudioWorkletNode) {
|
|
@@ -3149,8 +3264,10 @@ const awpStr = "class AudioCaptureInterceptorProcessor extends AudioWorkletProce
|
|
|
3149
3264
|
"\n" +
|
|
3150
3265
|
"registerProcessor('capture-interceptor',AudioCaptureInterceptorProcessor);\n";
|
|
3151
3266
|
class AudioCapture {
|
|
3152
|
-
|
|
3267
|
+
//private context:AudioContext|null=null;
|
|
3268
|
+
constructor() {
|
|
3153
3269
|
this._maxAutoNetMemStoreSamples = AudioCapture.DEFAULT_MAX_NET_AUTO_MEM_STORE_SAMPLES;
|
|
3270
|
+
this.context = null;
|
|
3154
3271
|
this._recUUID = null;
|
|
3155
3272
|
this.agcStatus = null;
|
|
3156
3273
|
this.bufferingNode = null;
|
|
@@ -3165,13 +3282,7 @@ class AudioCapture {
|
|
|
3165
3282
|
this.persisted = true;
|
|
3166
3283
|
this.persistError = null;
|
|
3167
3284
|
this.inddbAudioBuffer = null;
|
|
3168
|
-
this.context = context;
|
|
3169
3285
|
this.n = navigator;
|
|
3170
|
-
this.context.addEventListener('statechange', (ev) => {
|
|
3171
|
-
if (this.context.state !== 'running') {
|
|
3172
|
-
this.close();
|
|
3173
|
-
}
|
|
3174
|
-
});
|
|
3175
3286
|
}
|
|
3176
3287
|
get maxAutoNetMemStoreSamples() {
|
|
3177
3288
|
return this._maxAutoNetMemStoreSamples;
|
|
@@ -3200,6 +3311,19 @@ class AudioCapture {
|
|
|
3200
3311
|
get opened() {
|
|
3201
3312
|
return this._opened;
|
|
3202
3313
|
}
|
|
3314
|
+
_audioContext() {
|
|
3315
|
+
if (!this.context) {
|
|
3316
|
+
this.context = AudioContextProvider.audioContextInstance();
|
|
3317
|
+
if (this.context) {
|
|
3318
|
+
this.context.addEventListener('statechange', () => {
|
|
3319
|
+
if (this.context && this.context.state !== 'running') {
|
|
3320
|
+
this.close();
|
|
3321
|
+
}
|
|
3322
|
+
});
|
|
3323
|
+
}
|
|
3324
|
+
}
|
|
3325
|
+
return this.context;
|
|
3326
|
+
}
|
|
3203
3327
|
initData() {
|
|
3204
3328
|
if (!this._recUUID) {
|
|
3205
3329
|
this._recUUID = UUID.generate();
|
|
@@ -3314,119 +3438,137 @@ class AudioCapture {
|
|
|
3314
3438
|
}
|
|
3315
3439
|
}
|
|
3316
3440
|
addCaptureInterceptor() {
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
this.listener
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
let chunk = new Array(chs);
|
|
3339
|
-
const samples = this.framesRecorded * chs;
|
|
3340
|
-
if ((AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this.audioStorageType || AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this.audioStorageType) && this.data && samples > this._maxAutoNetMemStoreSamples) {
|
|
3341
|
-
this.data = null;
|
|
3342
|
-
}
|
|
3343
|
-
//console.debug("Data initialized: "+(this.data!=null));
|
|
3344
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
3345
|
-
//console.debug("Data ch initialized: "+(this.data !=null && this.data[ch] !=null));
|
|
3346
|
-
if (ch < this.channelCount) {
|
|
3347
|
-
if (dt.data[ch]) {
|
|
3348
|
-
let fa = new Float32Array(dt.data[ch]);
|
|
3349
|
-
if (this.data && this.data[ch]) {
|
|
3350
|
-
this.data[ch].push(fa);
|
|
3351
|
-
}
|
|
3352
|
-
chunk[ch] = fa;
|
|
3353
|
-
// Use samples of channel 0 to count frames (samples)
|
|
3354
|
-
if (ch == 0) {
|
|
3355
|
-
this.framesRecorded += fa.length;
|
|
3356
|
-
}
|
|
3357
|
-
}
|
|
3441
|
+
if (this.context) {
|
|
3442
|
+
const awn = new AudioWorkletNode(this.context, 'capture-interceptor');
|
|
3443
|
+
awn.onprocessorerror = (ev) => {
|
|
3444
|
+
let msg = 'Unknwon error';
|
|
3445
|
+
if (ev instanceof ErrorEvent) {
|
|
3446
|
+
msg = ev.message;
|
|
3447
|
+
}
|
|
3448
|
+
console.error("Capture audio worklet error: " + msg);
|
|
3449
|
+
if (this.listener) {
|
|
3450
|
+
this.listener.error(msg);
|
|
3451
|
+
}
|
|
3452
|
+
};
|
|
3453
|
+
let awnPt = awn.port;
|
|
3454
|
+
if (awnPt) {
|
|
3455
|
+
awnPt.onmessage = (ev) => {
|
|
3456
|
+
if (this.capturing) {
|
|
3457
|
+
let dt = ev.data;
|
|
3458
|
+
let chs = dt.chs;
|
|
3459
|
+
let adaLen = dt.data.length;
|
|
3460
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
3461
|
+
console.debug('Received data from worklet: ' + chs + ' ' + dt.len + ' Data chs: ' + adaLen);
|
|
3358
3462
|
}
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
this.
|
|
3363
|
-
// // Random test error:
|
|
3364
|
-
// if(Math.random()>0.98) {
|
|
3365
|
-
// throw new Error('Test');
|
|
3366
|
-
// }
|
|
3463
|
+
let chunk = new Array(chs);
|
|
3464
|
+
const samples = this.framesRecorded * chs;
|
|
3465
|
+
if ((AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this.audioStorageType || AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this.audioStorageType) && this.data && samples > this._maxAutoNetMemStoreSamples) {
|
|
3466
|
+
this.data = null;
|
|
3367
3467
|
}
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3468
|
+
//console.debug("Data initialized: "+(this.data!=null));
|
|
3469
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3470
|
+
//console.debug("Data ch initialized: "+(this.data !=null && this.data[ch] !=null));
|
|
3471
|
+
if (ch < this.channelCount) {
|
|
3472
|
+
if (dt.data[ch]) {
|
|
3473
|
+
let fa = new Float32Array(dt.data[ch]);
|
|
3474
|
+
if (this.data && this.data[ch]) {
|
|
3475
|
+
this.data[ch].push(fa);
|
|
3476
|
+
}
|
|
3477
|
+
chunk[ch] = fa;
|
|
3478
|
+
// Use samples of channel 0 to count frames (samples)
|
|
3479
|
+
if (ch == 0) {
|
|
3480
|
+
this.framesRecorded += fa.length;
|
|
3481
|
+
}
|
|
3482
|
+
}
|
|
3374
3483
|
}
|
|
3375
|
-
|
|
3484
|
+
}
|
|
3485
|
+
if (this.audioOutStream) {
|
|
3376
3486
|
try {
|
|
3377
|
-
this.
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3487
|
+
this.audioOutStream.write(chunk);
|
|
3488
|
+
// // Random test error:
|
|
3489
|
+
// if(Math.random()>0.98) {
|
|
3490
|
+
// throw new Error('Test');
|
|
3491
|
+
// }
|
|
3381
3492
|
}
|
|
3382
|
-
|
|
3383
|
-
if (
|
|
3384
|
-
|
|
3385
|
-
if (err instanceof DOMException) {
|
|
3386
|
-
errExpl = ': ' + err.name + ': ' + err.message;
|
|
3387
|
-
}
|
|
3388
|
-
this.listener.error("Could not handle recorded audio data" + errExpl, "Please try to record again.");
|
|
3493
|
+
catch (err) {
|
|
3494
|
+
if (err instanceof Error) {
|
|
3495
|
+
this.persistError = err;
|
|
3389
3496
|
}
|
|
3390
3497
|
else {
|
|
3391
|
-
this.
|
|
3498
|
+
this.persistError = new Error('Error handling recorded audio data');
|
|
3499
|
+
}
|
|
3500
|
+
console.error("Capture error: " + err);
|
|
3501
|
+
try {
|
|
3502
|
+
this.stop();
|
|
3503
|
+
}
|
|
3504
|
+
catch (err2) {
|
|
3505
|
+
console.error("Capture next error (ignored): " + err2);
|
|
3506
|
+
}
|
|
3507
|
+
finally {
|
|
3508
|
+
if (this.listener) {
|
|
3509
|
+
let errExpl = '';
|
|
3510
|
+
if (err instanceof DOMException) {
|
|
3511
|
+
errExpl = ': ' + err.name + ': ' + err.message;
|
|
3512
|
+
}
|
|
3513
|
+
this.listener.error("Could not handle recorded audio data" + errExpl, "Please try to record again.");
|
|
3514
|
+
}
|
|
3515
|
+
else {
|
|
3516
|
+
this.close();
|
|
3517
|
+
}
|
|
3392
3518
|
}
|
|
3393
3519
|
}
|
|
3394
3520
|
}
|
|
3521
|
+
if (AudioStorageType.DB_CHUNKED === this._audioStorageType && this._persistentAudioStorageTarget) {
|
|
3522
|
+
this.store();
|
|
3523
|
+
}
|
|
3395
3524
|
}
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
this._opened = true;
|
|
3410
|
-
if (this.listener) {
|
|
3411
|
-
this.listener.opened();
|
|
3525
|
+
};
|
|
3526
|
+
}
|
|
3527
|
+
// Tried to fix that Safari does not record the second channel
|
|
3528
|
+
// Does not help
|
|
3529
|
+
//awn.channelCount=this.channelCount;
|
|
3530
|
+
//awn.channelCountMode='explicit';
|
|
3531
|
+
//console.debug('Channel count explicitly set to '+this.channelCount);
|
|
3532
|
+
this.bufferingNode = awn;
|
|
3533
|
+
//this.bufferingNode.channelCount=this.channelCount;
|
|
3534
|
+
this._opened = true;
|
|
3535
|
+
if (this.listener) {
|
|
3536
|
+
this.listener.opened();
|
|
3537
|
+
}
|
|
3412
3538
|
}
|
|
3413
3539
|
}
|
|
3414
|
-
open(channelCount, selDeviceId, autoGainControlConfigs) {
|
|
3540
|
+
open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation) {
|
|
3415
3541
|
//console.debug("Capture open: ctx state: "+this.context.state);
|
|
3416
|
-
|
|
3542
|
+
this.context = this._audioContext();
|
|
3543
|
+
if (!this.context) {
|
|
3544
|
+
throw new Error("Could not get audio context!");
|
|
3545
|
+
}
|
|
3546
|
+
if (this.context.state === 'suspended') {
|
|
3417
3547
|
//console.debug("Capture open: Resume context");
|
|
3418
3548
|
this.context.resume().then(() => {
|
|
3419
3549
|
//console.debug("Capture open (ctx resumed): ctx state: "+this.context.state);
|
|
3420
|
-
this._open(channelCount, selDeviceId, autoGainControlConfigs);
|
|
3550
|
+
this._open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation);
|
|
3551
|
+
}).catch((err) => {
|
|
3552
|
+
console.error(err.message);
|
|
3553
|
+
throw err;
|
|
3421
3554
|
});
|
|
3422
3555
|
}
|
|
3556
|
+
else if (this.context.state === 'closed') {
|
|
3557
|
+
const msg = 'Error on start capture: The audio context is already closed.';
|
|
3558
|
+
console.error(msg);
|
|
3559
|
+
throw new Error(msg);
|
|
3560
|
+
}
|
|
3423
3561
|
else {
|
|
3424
|
-
this._open(channelCount, selDeviceId, autoGainControlConfigs);
|
|
3562
|
+
this._open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation);
|
|
3425
3563
|
}
|
|
3426
3564
|
}
|
|
3427
|
-
_open(channelCount, selDeviceId, autoGainControlConfigs) {
|
|
3565
|
+
_open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation) {
|
|
3428
3566
|
this.channelCount = channelCount;
|
|
3429
3567
|
this.framesRecorded = 0;
|
|
3568
|
+
this.context = this._audioContext();
|
|
3569
|
+
if (!this.context) {
|
|
3570
|
+
throw new Error("Could not get audio context!");
|
|
3571
|
+
}
|
|
3430
3572
|
//var msc = new AudioStreamConstr();
|
|
3431
3573
|
// var msc={};
|
|
3432
3574
|
//msc.video = false;
|
|
@@ -3534,7 +3676,7 @@ class AudioCapture {
|
|
|
3534
3676
|
audio: {
|
|
3535
3677
|
deviceId: selDeviceId,
|
|
3536
3678
|
channelCount: channelCount,
|
|
3537
|
-
|
|
3679
|
+
echoCancellation: allowEchoCancellation ? undefined : false
|
|
3538
3680
|
},
|
|
3539
3681
|
video: false,
|
|
3540
3682
|
};
|
|
@@ -3545,106 +3687,109 @@ class AudioCapture {
|
|
|
3545
3687
|
console.debug("Audio capture, AGC: " + this.agcStatus);
|
|
3546
3688
|
let ump = navigator.mediaDevices.getUserMedia(msc);
|
|
3547
3689
|
ump.then((s) => {
|
|
3548
|
-
this.
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
let
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
|
|
3556
|
-
|
|
3557
|
-
|
|
3558
|
-
|
|
3559
|
-
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
|
|
3564
|
-
let
|
|
3565
|
-
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
//
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
//
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
else {
|
|
3595
|
-
// Register capture interceptor module
|
|
3596
|
-
let audioWorkletModuleBlob = new Blob([awpStr], { type: 'text/javascript' });
|
|
3597
|
-
let audioWorkletModuleBlobUrl = window.URL.createObjectURL(audioWorkletModuleBlob);
|
|
3598
|
-
this.context.audioWorklet.addModule(audioWorkletModuleBlobUrl).then(() => {
|
|
3599
|
-
AudioCapture.captureInterceptorModuleRegistered = true;
|
|
3690
|
+
if (this.context) {
|
|
3691
|
+
this.stream = s;
|
|
3692
|
+
let aTracks = s.getAudioTracks();
|
|
3693
|
+
for (let i = 0; i < aTracks.length; i++) {
|
|
3694
|
+
let aTrack = aTracks[i];
|
|
3695
|
+
console.info("Track audio info: id: " + aTrack.id + " kind: " + aTrack.kind + " label: \"" + aTrack.label + "\"");
|
|
3696
|
+
let mtrSts = aTrack.getSettings();
|
|
3697
|
+
// Typescript lib.dom.ts MediaTrackSettings.channelCount is missing
|
|
3698
|
+
// https://github.com/mdn/browser-compat-data/blob/5493d8f937e05b2ddbd41b99f5bdfad4a1f2ed85/api/MediaTrackSettings.json
|
|
3699
|
+
//@ts-ignore
|
|
3700
|
+
console.info("Track audio settings: Ch cnt: " + mtrSts.channelCount + ", AGC: " + mtrSts.autoGainControl + ", Echo cancell.: " + mtrSts.echoCancellation);
|
|
3701
|
+
if (mtrSts.autoGainControl) {
|
|
3702
|
+
this.agcStatus = mtrSts.autoGainControl;
|
|
3703
|
+
}
|
|
3704
|
+
console.debug("Echo cancellation: " + mtrSts.echoCancellation);
|
|
3705
|
+
}
|
|
3706
|
+
let vTracks = s.getVideoTracks();
|
|
3707
|
+
for (let i = 0; i < vTracks.length; i++) {
|
|
3708
|
+
let vTrack = vTracks[i];
|
|
3709
|
+
console.info("Track video info: id: " + vTrack.id + " kind: " + vTrack.kind + " label: " + vTrack.label);
|
|
3710
|
+
}
|
|
3711
|
+
this.mediaStream = this.context.createMediaStreamSource(s);
|
|
3712
|
+
// stream channel count ( is always 2 !)
|
|
3713
|
+
let streamChannelCount = this.mediaStream.channelCount;
|
|
3714
|
+
console.info("Stream channel count: " + streamChannelCount);
|
|
3715
|
+
// is not set!!
|
|
3716
|
+
//this.currentSampleRate = this.mediaStream.sampleRate;
|
|
3717
|
+
this.currentSampleRate = this.context.sampleRate;
|
|
3718
|
+
console.info("Source audio node: channels: " + streamChannelCount + " samplerate: " + this.currentSampleRate);
|
|
3719
|
+
if (this.audioOutStream) {
|
|
3720
|
+
this.audioOutStream.setFormat(this.channelCount, this.currentSampleRate);
|
|
3721
|
+
}
|
|
3722
|
+
// W3C -> new name is createScriptProcessor
|
|
3723
|
+
//
|
|
3724
|
+
// Again deprecated, but AudioWorker not yet implemented in stable releases (June 2016)
|
|
3725
|
+
// AudioWorker is now AudioWorkletProcessor ... (May 2017)
|
|
3726
|
+
// Update 12-2020:
|
|
3727
|
+
// The ScriptProcessorNode Interface - DEPRECATED
|
|
3728
|
+
// Update 06-2021
|
|
3729
|
+
// AudioWorkletProcessor is here to stay. Web Audio API has now Recommendation status !
|
|
3730
|
+
if (this.context.audioWorklet) {
|
|
3731
|
+
//const workletFileName = ('file-loader!./interceptor_worklet.js');
|
|
3732
|
+
//const workletFileName = 'http://localhost:4200/assets/interceptor_worklet.js';
|
|
3733
|
+
//console.log(awpStr);
|
|
3734
|
+
if (AudioCapture.captureInterceptorModuleRegistered) {
|
|
3735
|
+
// Required capture interceptor module already registered
|
|
3600
3736
|
this.addCaptureInterceptor();
|
|
3601
|
-
}
|
|
3602
|
-
|
|
3603
|
-
|
|
3737
|
+
}
|
|
3738
|
+
else {
|
|
3739
|
+
// Register capture interceptor module
|
|
3740
|
+
let audioWorkletModuleBlob = new Blob([awpStr], { type: 'text/javascript' });
|
|
3741
|
+
let audioWorkletModuleBlobUrl = window.URL.createObjectURL(audioWorkletModuleBlob);
|
|
3742
|
+
this.context.audioWorklet.addModule(audioWorkletModuleBlobUrl).then(() => {
|
|
3743
|
+
AudioCapture.captureInterceptorModuleRegistered = true;
|
|
3744
|
+
this.addCaptureInterceptor();
|
|
3745
|
+
}).catch((error) => {
|
|
3746
|
+
console.log('Could not add module ' + error);
|
|
3747
|
+
});
|
|
3748
|
+
}
|
|
3604
3749
|
}
|
|
3605
|
-
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
|
|
3612
|
-
|
|
3613
|
-
|
|
3614
|
-
|
|
3615
|
-
|
|
3616
|
-
|
|
3617
|
-
|
|
3618
|
-
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3750
|
+
else if (this.context.createScriptProcessor) {
|
|
3751
|
+
// The ScriptProcessorNode Interface - DEPRECATED Only as fallback
|
|
3752
|
+
// TODO should we use streamChannelCount or channelCount here ?
|
|
3753
|
+
let scriptProcessorNode = this.context.createScriptProcessor(AudioCapture.BUFFER_SIZE, streamChannelCount, streamChannelCount);
|
|
3754
|
+
this.bufferingNode = scriptProcessorNode;
|
|
3755
|
+
let c = 0;
|
|
3756
|
+
if (scriptProcessorNode.onaudioprocess) {
|
|
3757
|
+
scriptProcessorNode.onaudioprocess = (e) => {
|
|
3758
|
+
if (this.capturing) {
|
|
3759
|
+
let inBuffer = e.inputBuffer;
|
|
3760
|
+
// only process requested count of channels
|
|
3761
|
+
let currentBuffers = new Array(channelCount);
|
|
3762
|
+
for (let ch = 0; ch < channelCount; ch++) {
|
|
3763
|
+
let chSamples = inBuffer.getChannelData(ch);
|
|
3764
|
+
let chSamplesCopy = chSamples.slice(0);
|
|
3765
|
+
currentBuffers[ch] = chSamplesCopy.slice(0);
|
|
3766
|
+
if (this.data) {
|
|
3767
|
+
this.data[ch].push(chSamplesCopy);
|
|
3768
|
+
}
|
|
3769
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
3770
|
+
console.debug("Process " + chSamplesCopy.length + " samples.");
|
|
3771
|
+
}
|
|
3772
|
+
this.framesRecorded += chSamplesCopy.length;
|
|
3624
3773
|
}
|
|
3625
|
-
|
|
3626
|
-
|
|
3774
|
+
c++;
|
|
3775
|
+
if (this.audioOutStream) {
|
|
3776
|
+
this.audioOutStream.write(currentBuffers);
|
|
3627
3777
|
}
|
|
3628
|
-
this.framesRecorded += chSamplesCopy.length;
|
|
3629
|
-
}
|
|
3630
|
-
c++;
|
|
3631
|
-
if (this.audioOutStream) {
|
|
3632
|
-
this.audioOutStream.write(currentBuffers);
|
|
3633
3778
|
}
|
|
3779
|
+
};
|
|
3780
|
+
this._opened = true;
|
|
3781
|
+
if (this.listener) {
|
|
3782
|
+
this.listener.opened();
|
|
3634
3783
|
}
|
|
3635
|
-
}
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
this.listener.opened();
|
|
3784
|
+
}
|
|
3785
|
+
else {
|
|
3786
|
+
this.listener.error('Browser does not support audio processing (ScriptProcessor.onaudioprocess method not found)!');
|
|
3639
3787
|
}
|
|
3640
3788
|
}
|
|
3641
3789
|
else {
|
|
3642
|
-
this.listener.error('Browser does not support audio processing (
|
|
3790
|
+
this.listener.error('Browser does not support audio processing (neither AudioWorkletProcessor nor ScriptProcessor)!');
|
|
3643
3791
|
}
|
|
3644
3792
|
}
|
|
3645
|
-
else {
|
|
3646
|
-
this.listener.error('Browser does not support audio processing (neither AudioWorkletProcessor nor ScriptProcessor)!');
|
|
3647
|
-
}
|
|
3648
3793
|
}, (e) => {
|
|
3649
3794
|
console.error(e + " Error name: " + e.name);
|
|
3650
3795
|
if (this.listener) {
|
|
@@ -3665,36 +3810,42 @@ class AudioCapture {
|
|
|
3665
3810
|
});
|
|
3666
3811
|
}
|
|
3667
3812
|
_start() {
|
|
3668
|
-
this.
|
|
3669
|
-
|
|
3670
|
-
this.audioOutStream
|
|
3671
|
-
|
|
3672
|
-
|
|
3673
|
-
|
|
3674
|
-
|
|
3675
|
-
|
|
3676
|
-
|
|
3677
|
-
|
|
3678
|
-
this.listener
|
|
3813
|
+
if (this.context) {
|
|
3814
|
+
this.initData();
|
|
3815
|
+
if (this.audioOutStream) {
|
|
3816
|
+
this.audioOutStream.nextStream();
|
|
3817
|
+
}
|
|
3818
|
+
this.capturing = true;
|
|
3819
|
+
if (this.bufferingNode) {
|
|
3820
|
+
this.mediaStream.connect(this.bufferingNode);
|
|
3821
|
+
this.bufferingNode.connect(this.context.destination);
|
|
3822
|
+
}
|
|
3823
|
+
if (this.listener) {
|
|
3824
|
+
this.listener.started();
|
|
3825
|
+
}
|
|
3679
3826
|
}
|
|
3680
3827
|
}
|
|
3681
3828
|
start() {
|
|
3682
|
-
|
|
3683
|
-
|
|
3684
|
-
|
|
3685
|
-
}
|
|
3686
|
-
else {
|
|
3687
|
-
console.debug("Capture start: audio context not running, state: " + aSt + ", resuming...");
|
|
3688
|
-
this.context.resume().then(() => {
|
|
3689
|
-
console.debug("Capture start: audio context resumed, starting...");
|
|
3829
|
+
if (this.context) {
|
|
3830
|
+
const aSt = this.context.state;
|
|
3831
|
+
if (aSt === 'running') {
|
|
3690
3832
|
this._start();
|
|
3691
|
-
}
|
|
3833
|
+
}
|
|
3834
|
+
else {
|
|
3835
|
+
console.debug("Capture start: audio context not running, state: " + aSt + ", resuming...");
|
|
3836
|
+
this.context.resume().then(() => {
|
|
3837
|
+
console.debug("Capture start: audio context resumed, starting...");
|
|
3838
|
+
this._start();
|
|
3839
|
+
});
|
|
3840
|
+
}
|
|
3692
3841
|
}
|
|
3693
3842
|
}
|
|
3694
3843
|
stop() {
|
|
3695
3844
|
if (this.disconnectStreams && this.bufferingNode) {
|
|
3696
3845
|
this.mediaStream.disconnect(this.bufferingNode);
|
|
3697
|
-
|
|
3846
|
+
if (this.context) {
|
|
3847
|
+
this.bufferingNode.disconnect(this.context.destination);
|
|
3848
|
+
}
|
|
3698
3849
|
}
|
|
3699
3850
|
try {
|
|
3700
3851
|
if (this.audioOutStream) {
|
|
@@ -3817,7 +3968,7 @@ class AudioCapture {
|
|
|
3817
3968
|
}
|
|
3818
3969
|
audioBuffer() {
|
|
3819
3970
|
let ab = null;
|
|
3820
|
-
if (this.data) {
|
|
3971
|
+
if (this.context && this.data) {
|
|
3821
3972
|
let frameLen = 0;
|
|
3822
3973
|
let ch0Data = this.data[0];
|
|
3823
3974
|
for (let ch0Chk of ch0Data) {
|
|
@@ -4519,7 +4670,7 @@ class Uploader {
|
|
|
4519
4670
|
si += v.size;
|
|
4520
4671
|
}
|
|
4521
4672
|
else if (typeof v === 'string') {
|
|
4522
|
-
// encode to
|
|
4673
|
+
// encode to UTF-8 to get upload size
|
|
4523
4674
|
si += this.te.encode().length;
|
|
4524
4675
|
}
|
|
4525
4676
|
});
|
|
@@ -4557,34 +4708,37 @@ class Uploader {
|
|
|
4557
4708
|
// pipe(timeout()) is not the same as xhr.timeout
|
|
4558
4709
|
let uploadedUpload = null;
|
|
4559
4710
|
//console.debug("Post upload: "+ul)
|
|
4560
|
-
this.http.post(ul.url, ul.data, { withCredentials: this.withCredentials }).pipe(timeout(timeoVal)).subscribe(
|
|
4561
|
-
|
|
4562
|
-
|
|
4563
|
-
|
|
4564
|
-
|
|
4565
|
-
|
|
4566
|
-
|
|
4567
|
-
|
|
4568
|
-
|
|
4569
|
-
// The backend returned an unsuccessful response code.
|
|
4570
|
-
// The response body may contain clues as to what went wrong,
|
|
4571
|
-
console.error(`Upload error: Server returned code ${err.status}`);
|
|
4572
|
-
}
|
|
4573
|
-
this.processError(ul);
|
|
4574
|
-
}, () => {
|
|
4575
|
-
//console.debug('Upload complete method called')
|
|
4576
|
-
if (uploadedUpload) {
|
|
4577
|
-
if (this.DEBUG_DELAY > 0) {
|
|
4578
|
-
window.setTimeout(() => {
|
|
4579
|
-
this.uploadDone(ul);
|
|
4580
|
-
}, this.DEBUG_DELAY);
|
|
4711
|
+
this.http.post(ul.url, ul.data, { withCredentials: this.withCredentials }).pipe(timeout(timeoVal)).subscribe({
|
|
4712
|
+
next: (data) => {
|
|
4713
|
+
uploadedUpload = ul;
|
|
4714
|
+
//console.debug('Next method called for upload: '+uploadedUpload)
|
|
4715
|
+
},
|
|
4716
|
+
error: (err) => {
|
|
4717
|
+
if (err.error instanceof Error) {
|
|
4718
|
+
// A client-side or network error occurred. Handle it accordingly.
|
|
4719
|
+
console.error('Upload error occurred:', err.error.message);
|
|
4581
4720
|
}
|
|
4582
4721
|
else {
|
|
4583
|
-
|
|
4722
|
+
// The backend returned an unsuccessful response code.
|
|
4723
|
+
// The response body may contain clues as to what went wrong,
|
|
4724
|
+
console.error(`Upload error: Server returned code ${err.status}`);
|
|
4725
|
+
}
|
|
4726
|
+
this.processError(ul);
|
|
4727
|
+
}, complete: () => {
|
|
4728
|
+
//console.debug('Upload complete method called')
|
|
4729
|
+
if (uploadedUpload) {
|
|
4730
|
+
if (this.DEBUG_DELAY > 0) {
|
|
4731
|
+
window.setTimeout(() => {
|
|
4732
|
+
this.uploadDone(ul);
|
|
4733
|
+
}, this.DEBUG_DELAY);
|
|
4734
|
+
}
|
|
4735
|
+
else {
|
|
4736
|
+
this.uploadDone(uploadedUpload);
|
|
4737
|
+
}
|
|
4738
|
+
}
|
|
4739
|
+
else {
|
|
4740
|
+
console.error('Upload post complete, but upload not set in next method!');
|
|
4584
4741
|
}
|
|
4585
|
-
}
|
|
4586
|
-
else {
|
|
4587
|
-
console.error('Upload post complete, but upload not set in next method!');
|
|
4588
4742
|
}
|
|
4589
4743
|
});
|
|
4590
4744
|
}
|
|
@@ -4599,7 +4753,7 @@ class Uploader {
|
|
|
4599
4753
|
// set retry timer
|
|
4600
4754
|
this.retryTimerId = window.setTimeout(() => {
|
|
4601
4755
|
this.retryTimerRunning = false;
|
|
4602
|
-
//console.debug("Upload retry timer
|
|
4756
|
+
//console.debug("Upload retry timer expired. Continue processing...")
|
|
4603
4757
|
this.process();
|
|
4604
4758
|
}, this.RETRY_DELAY);
|
|
4605
4759
|
this.retryTimerRunning = true;
|
|
@@ -4693,12 +4847,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
4693
4847
|
* Created by klausj on 17.06.2017.
|
|
4694
4848
|
*/
|
|
4695
4849
|
class ProjectService {
|
|
4696
|
-
constructor(http,
|
|
4850
|
+
constructor(http, platformLocation, config) {
|
|
4697
4851
|
this.http = http;
|
|
4698
|
-
this.
|
|
4852
|
+
this.platformLocation = platformLocation;
|
|
4699
4853
|
this.config = config;
|
|
4700
4854
|
this.withCredentials = false;
|
|
4701
|
-
console.log("Base Href: " +
|
|
4855
|
+
console.log("Base Href: " + platformLocation.getBaseHrefFromDOM());
|
|
4702
4856
|
let apiEndPoint = '';
|
|
4703
4857
|
if (config && config.apiEndPoint) {
|
|
4704
4858
|
apiEndPoint = config.apiEndPoint;
|
|
@@ -4781,14 +4935,17 @@ class SessionService {
|
|
|
4781
4935
|
let wrapObs = new Observable(subscriber => {
|
|
4782
4936
|
this._uploadCount++;
|
|
4783
4937
|
let obs = this.http.patch(sesssUrl, body, { withCredentials: this.withCredentials });
|
|
4784
|
-
obs.subscribe(
|
|
4785
|
-
|
|
4786
|
-
|
|
4787
|
-
|
|
4788
|
-
|
|
4789
|
-
|
|
4790
|
-
|
|
4791
|
-
|
|
4938
|
+
obs.subscribe({
|
|
4939
|
+
next: (value) => {
|
|
4940
|
+
subscriber.next(value);
|
|
4941
|
+
},
|
|
4942
|
+
error: error => {
|
|
4943
|
+
this._uploadCount--;
|
|
4944
|
+
subscriber.error(error);
|
|
4945
|
+
}, complete: () => {
|
|
4946
|
+
this._uploadCount--;
|
|
4947
|
+
subscriber.complete();
|
|
4948
|
+
}
|
|
4792
4949
|
});
|
|
4793
4950
|
});
|
|
4794
4951
|
return wrapObs;
|
|
@@ -7402,7 +7559,7 @@ AudioClipUIContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", v
|
|
|
7402
7559
|
<audio-signal [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-signal>
|
|
7403
7560
|
<audio-sonagram [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-sonagram>
|
|
7404
7561
|
</div>
|
|
7405
|
-
`, isInline: true, styles: ["div{margin:0;padding:0;top:0;left:0;width:100%;height:100%;position:relative;box-sizing:border-box;transform:none;overflow:hidden}\n", "canvas{top:0;left:0;width:0;height:0;cursor:ns-resize;position:absolute;
|
|
7562
|
+
`, isInline: true, styles: ["div{margin:0;padding:0;top:0;left:0;width:100%;height:100%;position:relative;box-sizing:border-box;transform:none;overflow:hidden}\n", "canvas{top:0;left:0;width:0;height:0;cursor:ns-resize;position:absolute;z-index:1;transform:none}\n", "audio-signal{top:0;left:0;position:absolute;z-index:1;transform:none}\n", "audio-sonagram{top:0;left:0;position:absolute;z-index:1;transform:none}\n"], dependencies: [{ kind: "component", type: AudioSignal, selector: "audio-signal" }, { kind: "component", type: Sonagram, selector: "audio-sonagram" }] });
|
|
7406
7563
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioClipUIContainer, decorators: [{
|
|
7407
7564
|
type: Component,
|
|
7408
7565
|
args: [{ selector: 'app-audio', template: `
|
|
@@ -7412,7 +7569,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
7412
7569
|
<audio-signal [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-signal>
|
|
7413
7570
|
<audio-sonagram [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-sonagram>
|
|
7414
7571
|
</div>
|
|
7415
|
-
`, styles: ["div{margin:0;padding:0;top:0;left:0;width:100%;height:100%;position:relative;box-sizing:border-box;transform:none;overflow:hidden}\n", "canvas{top:0;left:0;width:0;height:0;cursor:ns-resize;position:absolute;
|
|
7572
|
+
`, styles: ["div{margin:0;padding:0;top:0;left:0;width:100%;height:100%;position:relative;box-sizing:border-box;transform:none;overflow:hidden}\n", "canvas{top:0;left:0;width:0;height:0;cursor:ns-resize;position:absolute;z-index:1;transform:none}\n", "audio-signal{top:0;left:0;position:absolute;z-index:1;transform:none}\n", "audio-sonagram{top:0;left:0;position:absolute;z-index:1;transform:none}\n"] }]
|
|
7416
7573
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { canvasRef: [{
|
|
7417
7574
|
type: ViewChild,
|
|
7418
7575
|
args: ['divider', { static: true }]
|
|
@@ -7726,8 +7883,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
7726
7883
|
}] } });
|
|
7727
7884
|
|
|
7728
7885
|
class AudioDisplay {
|
|
7729
|
-
constructor(
|
|
7730
|
-
this.route = route;
|
|
7886
|
+
constructor(ref, eRef) {
|
|
7731
7887
|
this.ref = ref;
|
|
7732
7888
|
this.eRef = eRef;
|
|
7733
7889
|
this._audioClip = null;
|
|
@@ -7790,7 +7946,7 @@ class AudioDisplay {
|
|
|
7790
7946
|
this.status = 'ERROR';
|
|
7791
7947
|
}
|
|
7792
7948
|
}
|
|
7793
|
-
AudioDisplay.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioDisplay, deps: [{ token:
|
|
7949
|
+
AudioDisplay.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioDisplay, deps: [{ token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
7794
7950
|
AudioDisplay.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AudioDisplay, selector: "app-audiodisplay", inputs: { playStartAction: "playStartAction", playStopAction: "playStopAction", playSelectionAction: "playSelectionAction", autoPlayOnSelectToggleAction: "autoPlayOnSelectToggleAction", audioData: "audioData", audioClip: "audioClip" }, viewQueries: [{ propertyName: "audioDisplayScrollPane", first: true, predicate: AudioDisplayScrollPane, descendants: true, static: true }], ngImport: i0, template: `
|
|
7795
7951
|
|
|
7796
7952
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
@@ -7821,7 +7977,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
7821
7977
|
[zoomSelectedAction]="zoomSelectedAction"
|
|
7822
7978
|
[zoomFitToPanelAction]="zoomFitToPanelAction"></audio-display-control>
|
|
7823
7979
|
`, styles: [":host{display:flex;flex-direction:column;position:absolute;bottom:0;height:100%;width:100%;overflow:hidden;padding:20px;z-index:5;box-sizing:border-box;background-color:#e6e6e6}\n", "legend{margin-left:1em;padding:.2em .8em;font-size:.8em}\n", "fieldset{border:1px darkgray solid}\n"] }]
|
|
7824
|
-
}], ctorParameters: function () { return [{ type:
|
|
7980
|
+
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { playStartAction: [{
|
|
7825
7981
|
type: Input
|
|
7826
7982
|
}], playStopAction: [{
|
|
7827
7983
|
type: Input
|
|
@@ -7852,11 +8008,11 @@ class ResponsiveComponent {
|
|
|
7852
8008
|
});
|
|
7853
8009
|
}
|
|
7854
8010
|
}
|
|
7855
|
-
ResponsiveComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ResponsiveComponent, deps: [{ token: i1$
|
|
8011
|
+
ResponsiveComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ResponsiveComponent, deps: [{ token: i1$2.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Directive });
|
|
7856
8012
|
ResponsiveComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: ResponsiveComponent, ngImport: i0 });
|
|
7857
8013
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ResponsiveComponent, decorators: [{
|
|
7858
8014
|
type: Directive
|
|
7859
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
8015
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; } });
|
|
7860
8016
|
|
|
7861
8017
|
class ScrollIntoViewDirective {
|
|
7862
8018
|
constructor(elRef) {
|
|
@@ -8536,7 +8692,7 @@ class Prompting extends ResponsiveComponent {
|
|
|
8536
8692
|
this.onPrevItem.emit();
|
|
8537
8693
|
}
|
|
8538
8694
|
}
|
|
8539
|
-
Prompting.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: Prompting, deps: [{ token: i1$
|
|
8695
|
+
Prompting.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: Prompting, deps: [{ token: i1$2.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
|
|
8540
8696
|
Prompting.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: Prompting, selector: "app-sprprompting", inputs: { projectName: "projectName", startStopSignalState: "startStopSignalState", promptItem: "promptItem", showPrompt: "showPrompt", items: "items", selectedItemIdx: "selectedItemIdx", transportActions: "transportActions", enableDownload: "enableDownload", audioSignalCollapsed: "audioSignalCollapsed", displayAudioClip: "displayAudioClip", playStartAction: "playStartAction", playSelectionAction: "playSelectionAction", autoPlayOnSelectToggleAction: "autoPlayOnSelectToggleAction", playStopAction: "playStopAction" }, outputs: { onItemSelect: "onItemSelect", onNextItem: "onNextItem", onPrevItem: "onPrevItem" }, viewQueries: [{ propertyName: "simpleTrafficLight", first: true, predicate: SimpleTrafficLight, descendants: true, static: true }, { propertyName: "audioDisplay", first: true, predicate: AudioDisplay, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
8541
8697
|
|
|
8542
8698
|
<app-simpletrafficlight [status]="startStopSignalState"></app-simpletrafficlight>
|
|
@@ -8585,7 +8741,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
8585
8741
|
|
|
8586
8742
|
|
|
8587
8743
|
`, styles: [":host{position:relative;margin:0;padding:0;background:lightgrey;width:100%;flex:1;min-height:0px;display:flex;flex-direction:row;flex-wrap:nowrap}\n", "app-simpletrafficlight{margin:10px;min-height:0px;z-index:3}\n", "app-sprprogress{z-index:3}\n", "div{display:none;position:absolute;z-index:5}\n", "div.active{display:flex;position:absolute;bottom:0;height:90%;width:100%;overflow:hidden;padding:0;z-index:5;box-sizing:border-box;background-color:#0000}\n"] }]
|
|
8588
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
8744
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; }, propDecorators: { simpleTrafficLight: [{
|
|
8589
8745
|
type: ViewChild,
|
|
8590
8746
|
args: [SimpleTrafficLight, { static: true }]
|
|
8591
8747
|
}], audioDisplay: [{
|
|
@@ -8636,7 +8792,7 @@ class SessionFinishedDialog {
|
|
|
8636
8792
|
this.dialogRef.close();
|
|
8637
8793
|
}
|
|
8638
8794
|
}
|
|
8639
|
-
SessionFinishedDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionFinishedDialog, deps: [{ token: i1$
|
|
8795
|
+
SessionFinishedDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionFinishedDialog, deps: [{ token: i1$3.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
8640
8796
|
SessionFinishedDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: SessionFinishedDialog, selector: "spr-session-finished-dialog", ngImport: i0, template: `<h1 mat-dialog-title><mat-icon [style.color]="'green'">done_all</mat-icon> Session finished</h1>
|
|
8641
8797
|
<div mat-dialog-content>
|
|
8642
8798
|
|
|
@@ -8646,7 +8802,7 @@ SessionFinishedDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0",
|
|
|
8646
8802
|
<div mat-dialog-actions>
|
|
8647
8803
|
<button mat-button (click)="closeDialog()">OK</button>
|
|
8648
8804
|
</div>
|
|
8649
|
-
`, isInline: true, dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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"] }, { kind: "directive", type: i1$
|
|
8805
|
+
`, isInline: true, dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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"] }, { kind: "directive", type: i1$3.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$3.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1$3.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] });
|
|
8650
8806
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionFinishedDialog, decorators: [{
|
|
8651
8807
|
type: Component,
|
|
8652
8808
|
args: [{
|
|
@@ -8662,7 +8818,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
8662
8818
|
</div>
|
|
8663
8819
|
`
|
|
8664
8820
|
}]
|
|
8665
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
8821
|
+
}], ctorParameters: function () { return [{ type: i1$3.MatDialogRef }, { type: undefined, decorators: [{
|
|
8666
8822
|
type: Inject,
|
|
8667
8823
|
args: [MAT_DIALOG_DATA]
|
|
8668
8824
|
}] }]; } });
|
|
@@ -8676,7 +8832,7 @@ class MessageDialog {
|
|
|
8676
8832
|
this.dialogRef.close();
|
|
8677
8833
|
}
|
|
8678
8834
|
}
|
|
8679
|
-
MessageDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MessageDialog, deps: [{ token: i1$
|
|
8835
|
+
MessageDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MessageDialog, deps: [{ token: i1$3.MatDialogRef }, { token: MAT_DIALOG_DATA }], target: i0.ɵɵFactoryTarget.Component });
|
|
8680
8836
|
MessageDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: MessageDialog, selector: "msg-dialog", ngImport: i0, template: `<h1 mat-dialog-title><mat-icon *ngIf="data.type==='error'" [style.color]="'red'">error</mat-icon>
|
|
8681
8837
|
<mat-icon *ngIf="data.type==='warning'" [style.color]="'yellow'">warning</mat-icon>{{data.title}}</h1>
|
|
8682
8838
|
<div mat-dialog-content>
|
|
@@ -8688,7 +8844,7 @@ MessageDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version:
|
|
|
8688
8844
|
<div mat-dialog-actions>
|
|
8689
8845
|
<button mat-button (click)="closeDialog()">OK</button>
|
|
8690
8846
|
</div>
|
|
8691
|
-
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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"] }, { kind: "directive", type: i1$
|
|
8847
|
+
`, isInline: true, dependencies: [{ kind: "directive", type: i1$1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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"] }, { kind: "directive", type: i1$3.MatDialogTitle, selector: "[mat-dialog-title], [matDialogTitle]", inputs: ["id"], exportAs: ["matDialogTitle"] }, { kind: "directive", type: i1$3.MatDialogContent, selector: "[mat-dialog-content], mat-dialog-content, [matDialogContent]" }, { kind: "directive", type: i1$3.MatDialogActions, selector: "[mat-dialog-actions], mat-dialog-actions, [matDialogActions]", inputs: ["align"] }] });
|
|
8692
8848
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MessageDialog, decorators: [{
|
|
8693
8849
|
type: Component,
|
|
8694
8850
|
args: [{
|
|
@@ -8706,7 +8862,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
8706
8862
|
</div>
|
|
8707
8863
|
`
|
|
8708
8864
|
}]
|
|
8709
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
8865
|
+
}], ctorParameters: function () { return [{ type: i1$3.MatDialogRef }, { type: undefined, decorators: [{
|
|
8710
8866
|
type: Inject,
|
|
8711
8867
|
args: [MAT_DIALOG_DATA]
|
|
8712
8868
|
}] }]; } });
|
|
@@ -8996,7 +9152,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
8996
9152
|
withCredentials: this.withCredentials
|
|
8997
9153
|
});
|
|
8998
9154
|
}
|
|
8999
|
-
chunkAudioRequest(
|
|
9155
|
+
chunkAudioRequest(baseAudioUrl, startFrame = 0, frameLength) {
|
|
9000
9156
|
let ausps = new URLSearchParams();
|
|
9001
9157
|
ausps.set('startFrame', startFrame.toString());
|
|
9002
9158
|
ausps.set('frameLength', frameLength.toString());
|
|
@@ -9007,67 +9163,69 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9007
9163
|
ausps.set('requestUUID', UUID.generate());
|
|
9008
9164
|
}
|
|
9009
9165
|
let obs = new Observable(observer => {
|
|
9010
|
-
this.audioRequestByURL(baseAudioUrl, ausps).subscribe(
|
|
9011
|
-
|
|
9012
|
-
|
|
9013
|
-
|
|
9014
|
-
|
|
9015
|
-
|
|
9016
|
-
|
|
9017
|
-
|
|
9018
|
-
|
|
9019
|
-
|
|
9020
|
-
|
|
9021
|
-
|
|
9022
|
-
|
|
9023
|
-
|
|
9024
|
-
|
|
9025
|
-
|
|
9026
|
-
|
|
9027
|
-
|
|
9028
|
-
|
|
9029
|
-
|
|
9030
|
-
|
|
9031
|
-
|
|
9032
|
-
|
|
9033
|
-
|
|
9034
|
-
|
|
9035
|
-
|
|
9036
|
-
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9166
|
+
this.audioRequestByURL(baseAudioUrl, ausps).subscribe({
|
|
9167
|
+
next: resp => {
|
|
9168
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9169
|
+
if (resp.body) {
|
|
9170
|
+
//console.debug("chunkAudioRequest: observer.closed: "+observer.closed);
|
|
9171
|
+
//console.debug("Audio file bytes: "+resp.body.byteLength);
|
|
9172
|
+
// Check original audio format
|
|
9173
|
+
let wr = new WavReader(resp.body);
|
|
9174
|
+
const pcmFmt = wr.readFormat();
|
|
9175
|
+
const orgFl = wr.frameLength();
|
|
9176
|
+
// if(pcmFmt){
|
|
9177
|
+
// console.debug("Original WAVE format of download chunk: "+pcmFmt);
|
|
9178
|
+
// }else{
|
|
9179
|
+
// console.error("Could not read WAVE format of original download chunk!");
|
|
9180
|
+
// }
|
|
9181
|
+
// if(orgFl){
|
|
9182
|
+
// console.debug("Original frame length of download chunk: "+orgFl);
|
|
9183
|
+
// }else{
|
|
9184
|
+
// console.error("Could not read WAVE format of original download chunk!");
|
|
9185
|
+
// }
|
|
9186
|
+
if (pcmFmt && orgFl) {
|
|
9187
|
+
AudioContextProvider.decodeAudioData(resp.body).then((ab) => {
|
|
9188
|
+
//console.debug("Decoded audio chunk frames: "+ab.length);
|
|
9189
|
+
let chDl = new ChunkDownload(pcmFmt, orgFl, ab);
|
|
9190
|
+
observer.next(chDl);
|
|
9191
|
+
observer.complete();
|
|
9192
|
+
}).catch(error => {
|
|
9193
|
+
//if(error instanceof HttpErrorResponse) {
|
|
9194
|
+
// if (error.status == 404) {
|
|
9195
|
+
// // Interpret not as an error, the file ist not recorded yet
|
|
9196
|
+
// observer.next(null);
|
|
9197
|
+
// observer.complete()
|
|
9198
|
+
// } else {
|
|
9199
|
+
// // all other states are errors
|
|
9200
|
+
console.error("Recordings service chunkAudioRequest error decoding audio data: " + error.name + ": " + error.message);
|
|
9201
|
+
observer.error(error);
|
|
9202
|
+
// }
|
|
9203
|
+
// }
|
|
9204
|
+
});
|
|
9205
|
+
}
|
|
9206
|
+
else {
|
|
9207
|
+
const errMsg = 'Could not parse audio header for format and/or frame length of download.';
|
|
9208
|
+
console.error(errMsg);
|
|
9209
|
+
observer.error(errMsg);
|
|
9210
|
+
}
|
|
9048
9211
|
}
|
|
9049
9212
|
else {
|
|
9050
|
-
const errMsg = '
|
|
9213
|
+
const errMsg = 'Fetching audio file: response has no body';
|
|
9051
9214
|
console.error(errMsg);
|
|
9052
9215
|
observer.error(errMsg);
|
|
9053
9216
|
}
|
|
9217
|
+
}, error: (error) => {
|
|
9218
|
+
// all other states are errors
|
|
9219
|
+
//const errMsg='Fetching audio file HTTP error: '+error;
|
|
9220
|
+
//console.error(errMsg);
|
|
9221
|
+
observer.error(error);
|
|
9222
|
+
//observer.complete();
|
|
9054
9223
|
}
|
|
9055
|
-
else {
|
|
9056
|
-
const errMsg = 'Fetching audio file: response has no body';
|
|
9057
|
-
console.error(errMsg);
|
|
9058
|
-
observer.error(errMsg);
|
|
9059
|
-
}
|
|
9060
|
-
}, (error) => {
|
|
9061
|
-
// all other states are errors
|
|
9062
|
-
//const errMsg='Fetching audio file HTTP error: '+error;
|
|
9063
|
-
//console.error(errMsg);
|
|
9064
|
-
observer.error(error);
|
|
9065
|
-
//observer.complete();
|
|
9066
9224
|
});
|
|
9067
9225
|
});
|
|
9068
9226
|
return obs;
|
|
9069
9227
|
}
|
|
9070
|
-
chunkAudioRequestToNetAudioBuffer(
|
|
9228
|
+
chunkAudioRequestToNetAudioBuffer(baseAudioUrl, startFrame = 0, orgSampleRate, seconds, frames) {
|
|
9071
9229
|
//let audioUrl=baseAudioUrl+'?startFrame='+startFrame+'&frameLength='+frameLength;
|
|
9072
9230
|
//let audioUrl=new URL(baseAudioUrl);
|
|
9073
9231
|
// if(orgSampleRate!=null && frameLength%orgSampleRate>0){
|
|
@@ -9091,7 +9249,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9091
9249
|
if (resp.body) {
|
|
9092
9250
|
//console.debug("chunkAudioRequestTonetAb: subscriber.closed: "+subscriber.closed);
|
|
9093
9251
|
//console.debug("chunkAudioRequestTonetAb: Audio file bytes: "+resp.body.byteLength);
|
|
9094
|
-
|
|
9252
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9095
9253
|
//console.debug("chunkAudioRequestTonetAb: Decoded audio chunk frames for netAb: "+ab.length);
|
|
9096
9254
|
//console.debug("chunkAudioRequestTonetAb: Create netAb ab from chunk ab...");
|
|
9097
9255
|
if (frames === null) {
|
|
@@ -9105,7 +9263,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9105
9263
|
//console.debug("Platform sr: "+ab.sampleRate+", file sr: "+orgSampleRate+", decoded/org frame length: "+fl+"/"+frames+", ab.length: "+ab.length);
|
|
9106
9264
|
}
|
|
9107
9265
|
}
|
|
9108
|
-
let nab = NetAudioBuffer.fromChunkAudioBuffer(
|
|
9266
|
+
let nab = NetAudioBuffer.fromChunkAudioBuffer(this, baseAudioUrl, ab, fl, frameLength);
|
|
9109
9267
|
//let rp=new ReadyProvider();
|
|
9110
9268
|
//nab.readyProvider=rp;
|
|
9111
9269
|
//rp.ready();
|
|
@@ -9117,7 +9275,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9117
9275
|
subscriber.next(nab);
|
|
9118
9276
|
subscriber.complete();
|
|
9119
9277
|
}
|
|
9120
|
-
}
|
|
9278
|
+
}).catch(error => {
|
|
9121
9279
|
console.error('chunkAudioRequestToNetAb: error: ' + error);
|
|
9122
9280
|
//if(error instanceof HttpErrorResponse) {
|
|
9123
9281
|
subscriber.error(error);
|
|
@@ -9225,7 +9383,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9225
9383
|
withCredentials: this.withCredentials
|
|
9226
9384
|
});
|
|
9227
9385
|
}
|
|
9228
|
-
chunkAudioRequestToIndDb(
|
|
9386
|
+
chunkAudioRequestToIndDb(persistentAudioStorageTarget, inddbAudioBuffer, baseAudioUrl, startFrame = 0, orgSampleRate, seconds) {
|
|
9229
9387
|
//let audioUrl=baseAudioUrl+'?startFrame='+startFrame+'&frameLength='+frameLength;
|
|
9230
9388
|
//let audioUrl=new URL(baseAudioUrl);
|
|
9231
9389
|
let frameLength = orgSampleRate * Math.round(seconds); // Important: multiple of original sample rate to prevent numeric rounding errors on resampling. 10 seconds is a good value for ind db storage.
|
|
@@ -9244,7 +9402,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9244
9402
|
if (resp.body) {
|
|
9245
9403
|
//console.debug("chunkAudioRequestToIndDb: subscriber.closed: "+subscriber.closed);
|
|
9246
9404
|
//console.debug("chunkAudioRequestToIndDb: Audio file bytes: "+resp.body.byteLength);
|
|
9247
|
-
|
|
9405
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9248
9406
|
//console.debug("chunkAudioRequestToIndDb: Decoded audio chunk frames for inddb: "+ab.length);
|
|
9249
9407
|
if (!inddbAudioBuffer) {
|
|
9250
9408
|
//console.debug("chunkAudioRequestToIndDb: Create inddb ab from chunk ab...");
|
|
@@ -9288,7 +9446,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9288
9446
|
}
|
|
9289
9447
|
});
|
|
9290
9448
|
}
|
|
9291
|
-
}
|
|
9449
|
+
}).catch(error => {
|
|
9292
9450
|
console.error('chunkAudioRequestToIndDb: error: ' + error);
|
|
9293
9451
|
//if(error instanceof HttpErrorResponse) {
|
|
9294
9452
|
subscriber.error(error);
|
|
@@ -9296,8 +9454,9 @@ class RecordingService extends BasicRecordingService {
|
|
|
9296
9454
|
});
|
|
9297
9455
|
}
|
|
9298
9456
|
else {
|
|
9299
|
-
|
|
9300
|
-
|
|
9457
|
+
const errMsg = 'chunkAudioRequestToIndDb: Fetching audio file: response has no body';
|
|
9458
|
+
console.error(errMsg);
|
|
9459
|
+
subscriber.error(new Error(errMsg));
|
|
9301
9460
|
}
|
|
9302
9461
|
},
|
|
9303
9462
|
error: (error) => {
|
|
@@ -9309,13 +9468,13 @@ class RecordingService extends BasicRecordingService {
|
|
|
9309
9468
|
});
|
|
9310
9469
|
return obs;
|
|
9311
9470
|
}
|
|
9312
|
-
chunkedAudioRequestToArrayBuffer(
|
|
9471
|
+
chunkedAudioRequestToArrayBuffer(baseAudioUrl, orgSampleRate, seconds) {
|
|
9313
9472
|
let obs = new Observable(subscriber => {
|
|
9314
9473
|
let arrayAudioBuffer = null;
|
|
9315
9474
|
let startFrame = 0;
|
|
9316
9475
|
let frameLength = orgSampleRate * Math.round(seconds); // Important: multiple of original sample rate to prevent numeric rounding errors on resampling.
|
|
9317
9476
|
//console.debug("Chunk audio request startFrame 0");
|
|
9318
|
-
let subscr = this.chunkAudioRequest(
|
|
9477
|
+
let subscr = this.chunkAudioRequest(baseAudioUrl, startFrame, frameLength).pipe(expand(value => {
|
|
9319
9478
|
if (subscriber.closed) {
|
|
9320
9479
|
subscr.unsubscribe();
|
|
9321
9480
|
}
|
|
@@ -9334,7 +9493,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9334
9493
|
startFrame += frameLength;
|
|
9335
9494
|
//console.debug("Next start frame: "+startFrame);
|
|
9336
9495
|
//console.debug("chunkedAudioRequest: expand() subscriber.closed: "+subscriber.closed);
|
|
9337
|
-
return this.chunkAudioRequest(
|
|
9496
|
+
return this.chunkAudioRequest(baseAudioUrl, startFrame, frameLength);
|
|
9338
9497
|
}
|
|
9339
9498
|
}
|
|
9340
9499
|
else {
|
|
@@ -9404,14 +9563,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9404
9563
|
});
|
|
9405
9564
|
return obs;
|
|
9406
9565
|
}
|
|
9407
|
-
chunkedInddbAudioRequest(
|
|
9566
|
+
chunkedInddbAudioRequest(persistentAudioStorageTarget, baseAudioUrl, orgSampleRate, seconds) {
|
|
9408
9567
|
let obs = new Observable(subscriber => {
|
|
9409
9568
|
let inddbAudioBuffer = null;
|
|
9410
9569
|
let startFrame = 0;
|
|
9411
9570
|
//let frameLength = DEFAULT_CHUNKED_DOWNLOAD_FRAMELENGTH;
|
|
9412
9571
|
let frameLength = orgSampleRate * Math.round(seconds);
|
|
9413
9572
|
//console.debug("chunkedInddbAudioRequest: Chunk audio request for inddb. startFrame: "+startFrame);
|
|
9414
|
-
let subscr = this.chunkAudioRequestToIndDb(
|
|
9573
|
+
let subscr = this.chunkAudioRequestToIndDb(persistentAudioStorageTarget, null, baseAudioUrl, startFrame, orgSampleRate, seconds).pipe(expand(iab => {
|
|
9415
9574
|
// console.debug("chunkedInddbAudioRequest (pipe/expand): Got inddb ab: "+iab);
|
|
9416
9575
|
if (subscriber.closed) {
|
|
9417
9576
|
subscr.unsubscribe();
|
|
@@ -9432,7 +9591,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9432
9591
|
startFrame += frameLength;
|
|
9433
9592
|
//console.debug("Next start frame: "+startFrame);
|
|
9434
9593
|
//console.debug("chunkedInddbAudioRequest: expand() subscriber.closed: "+subscriber.closed);
|
|
9435
|
-
return this.chunkAudioRequestToIndDb(
|
|
9594
|
+
return this.chunkAudioRequestToIndDb(persistentAudioStorageTarget, inddbAudioBuffer, baseAudioUrl, startFrame, orgSampleRate, seconds);
|
|
9436
9595
|
}
|
|
9437
9596
|
// } else {
|
|
9438
9597
|
// return EMPTY;
|
|
@@ -9624,7 +9783,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9624
9783
|
// //let recUrl=new URL(recUrlStr);
|
|
9625
9784
|
// return this.chunkedInddbAudioRequest(aCtx,recUrlStr);
|
|
9626
9785
|
// }
|
|
9627
|
-
fetchRecordingFileAudioBuffer(
|
|
9786
|
+
fetchRecordingFileAudioBuffer(projectName, recordingFile) {
|
|
9628
9787
|
let wobs = new Observable(observer => {
|
|
9629
9788
|
let recFileId = recordingFile.recordingFileId;
|
|
9630
9789
|
if (!recFileId) {
|
|
@@ -9632,36 +9791,38 @@ class RecordingService extends BasicRecordingService {
|
|
|
9632
9791
|
}
|
|
9633
9792
|
if (recordingFile.session && recFileId) {
|
|
9634
9793
|
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
9635
|
-
obs.subscribe(
|
|
9636
|
-
|
|
9637
|
-
|
|
9638
|
-
|
|
9639
|
-
|
|
9640
|
-
|
|
9641
|
-
|
|
9642
|
-
|
|
9643
|
-
|
|
9644
|
-
|
|
9645
|
-
|
|
9646
|
-
|
|
9647
|
-
|
|
9648
|
-
|
|
9649
|
-
|
|
9650
|
-
|
|
9651
|
-
if (err
|
|
9652
|
-
|
|
9653
|
-
|
|
9654
|
-
|
|
9794
|
+
obs.subscribe({
|
|
9795
|
+
next: resp => {
|
|
9796
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9797
|
+
if (resp.body) {
|
|
9798
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9799
|
+
observer.next(ab);
|
|
9800
|
+
observer.complete();
|
|
9801
|
+
}).catch(error => {
|
|
9802
|
+
observer.error(error);
|
|
9803
|
+
observer.complete();
|
|
9804
|
+
});
|
|
9805
|
+
}
|
|
9806
|
+
else {
|
|
9807
|
+
observer.error('Fetching audio file: response has no body');
|
|
9808
|
+
}
|
|
9809
|
+
}, error: (err) => {
|
|
9810
|
+
if (err instanceof HttpErrorResponse) {
|
|
9811
|
+
if (err.status == 404) {
|
|
9812
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9813
|
+
observer.next(null);
|
|
9814
|
+
observer.complete();
|
|
9815
|
+
}
|
|
9816
|
+
else {
|
|
9817
|
+
// all other states are errors
|
|
9818
|
+
observer.error(err);
|
|
9819
|
+
observer.complete();
|
|
9820
|
+
}
|
|
9655
9821
|
}
|
|
9656
9822
|
else {
|
|
9657
|
-
// all other states are errors
|
|
9658
9823
|
observer.error(err);
|
|
9659
|
-
observer.complete();
|
|
9660
9824
|
}
|
|
9661
9825
|
}
|
|
9662
|
-
else {
|
|
9663
|
-
observer.error(err);
|
|
9664
|
-
}
|
|
9665
9826
|
});
|
|
9666
9827
|
}
|
|
9667
9828
|
else {
|
|
@@ -9678,49 +9839,50 @@ class RecordingService extends BasicRecordingService {
|
|
|
9678
9839
|
}
|
|
9679
9840
|
if (recordingFile.session && recFileId) {
|
|
9680
9841
|
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
9681
|
-
obs.subscribe(resp => {
|
|
9682
|
-
|
|
9683
|
-
|
|
9684
|
-
|
|
9685
|
-
|
|
9686
|
-
|
|
9687
|
-
|
|
9688
|
-
|
|
9689
|
-
|
|
9690
|
-
|
|
9842
|
+
obs.subscribe({ next: resp => {
|
|
9843
|
+
//console.log("Fetched audio file. HTTP response status: "+resp.status+", type: "+resp.type+", byte length: "+ resp.body.byteLength);
|
|
9844
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9845
|
+
if (resp.body) {
|
|
9846
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9847
|
+
let abs = new AudioBufferSource(ab);
|
|
9848
|
+
let adh = new AudioDataHolder(abs);
|
|
9849
|
+
RecordingFileUtils.setAudioData(recordingFile, adh);
|
|
9850
|
+
if (this.debugDelay > 0) {
|
|
9851
|
+
window.setTimeout(() => {
|
|
9852
|
+
observer.next(recordingFile);
|
|
9853
|
+
observer.complete();
|
|
9854
|
+
}, this.debugDelay);
|
|
9855
|
+
}
|
|
9856
|
+
else {
|
|
9691
9857
|
observer.next(recordingFile);
|
|
9692
9858
|
observer.complete();
|
|
9693
|
-
}
|
|
9859
|
+
}
|
|
9860
|
+
}).catch(error => {
|
|
9861
|
+
observer.error(error);
|
|
9862
|
+
observer.complete();
|
|
9863
|
+
});
|
|
9864
|
+
}
|
|
9865
|
+
else {
|
|
9866
|
+
observer.error('Fetching audio file: response has no body');
|
|
9867
|
+
}
|
|
9868
|
+
},
|
|
9869
|
+
error: (err) => {
|
|
9870
|
+
if (err instanceof HttpErrorResponse) {
|
|
9871
|
+
if (err.status == 404) {
|
|
9872
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9873
|
+
observer.next(null);
|
|
9874
|
+
observer.complete();
|
|
9694
9875
|
}
|
|
9695
9876
|
else {
|
|
9696
|
-
|
|
9877
|
+
// all other states are errors
|
|
9878
|
+
observer.error(err);
|
|
9697
9879
|
observer.complete();
|
|
9698
9880
|
}
|
|
9699
|
-
}, error => {
|
|
9700
|
-
observer.error(error);
|
|
9701
|
-
observer.complete();
|
|
9702
|
-
});
|
|
9703
|
-
}
|
|
9704
|
-
else {
|
|
9705
|
-
observer.error('Fetching audio file: response has no body');
|
|
9706
|
-
}
|
|
9707
|
-
}, (err) => {
|
|
9708
|
-
if (err instanceof HttpErrorResponse) {
|
|
9709
|
-
if (err.status == 404) {
|
|
9710
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
9711
|
-
observer.next(null);
|
|
9712
|
-
observer.complete();
|
|
9713
9881
|
}
|
|
9714
9882
|
else {
|
|
9715
|
-
// all other states are errors
|
|
9716
9883
|
observer.error(err);
|
|
9717
|
-
observer.complete();
|
|
9718
9884
|
}
|
|
9719
|
-
}
|
|
9720
|
-
else {
|
|
9721
|
-
observer.error(err);
|
|
9722
|
-
}
|
|
9723
|
-
});
|
|
9885
|
+
} });
|
|
9724
9886
|
}
|
|
9725
9887
|
else {
|
|
9726
9888
|
observer.error();
|
|
@@ -9728,7 +9890,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9728
9890
|
});
|
|
9729
9891
|
return wobs;
|
|
9730
9892
|
}
|
|
9731
|
-
fetchSprRecordingFileAudioBuffer(
|
|
9893
|
+
fetchSprRecordingFileAudioBuffer(projectName, recordingFile) {
|
|
9732
9894
|
let wobs = new Observable(observer => {
|
|
9733
9895
|
if (recordingFile.session) {
|
|
9734
9896
|
let obs = this.fetchSprAudiofile(projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
@@ -9736,11 +9898,11 @@ class RecordingService extends BasicRecordingService {
|
|
|
9736
9898
|
next: resp => {
|
|
9737
9899
|
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9738
9900
|
if (resp.body) {
|
|
9739
|
-
|
|
9901
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9740
9902
|
//RecordingFileUtils.setAudioData(recordingFile,new AudioDataHolder(ab,null));
|
|
9741
9903
|
observer.next(ab);
|
|
9742
9904
|
observer.complete();
|
|
9743
|
-
}
|
|
9905
|
+
}).catch(error => {
|
|
9744
9906
|
observer.error(error);
|
|
9745
9907
|
observer.complete();
|
|
9746
9908
|
});
|
|
@@ -9768,14 +9930,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9768
9930
|
});
|
|
9769
9931
|
return wobs;
|
|
9770
9932
|
}
|
|
9771
|
-
fetchSprRecordingFileArrayAudioBuffer(
|
|
9933
|
+
fetchSprRecordingFileArrayAudioBuffer(projectName, recordingFile) {
|
|
9772
9934
|
let wobs = new Observable(observer => {
|
|
9773
9935
|
if (recordingFile.session) {
|
|
9774
9936
|
let baseUrl = this.sprAudioFileUrl(projectName, recordingFile);
|
|
9775
9937
|
if (baseUrl) {
|
|
9776
9938
|
if (recordingFile.samplerate) {
|
|
9777
9939
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9778
|
-
let obs = this.chunkedAudioRequestToArrayBuffer(
|
|
9940
|
+
let obs = this.chunkedAudioRequestToArrayBuffer(baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9779
9941
|
//let obs = this.fetchSprAudiofileArrayBuffer(aCtx,projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
9780
9942
|
let subscr = obs.subscribe({
|
|
9781
9943
|
next: aab => {
|
|
@@ -9812,14 +9974,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9812
9974
|
});
|
|
9813
9975
|
return wobs;
|
|
9814
9976
|
}
|
|
9815
|
-
fetchRecordingFileArrayAudioBuffer(
|
|
9977
|
+
fetchRecordingFileArrayAudioBuffer(projectName, recordingFile) {
|
|
9816
9978
|
let wobs = new Observable(observer => {
|
|
9817
9979
|
if (recordingFile.session) {
|
|
9818
9980
|
let baseUrl = this.audioFileUrl(projectName, recordingFile);
|
|
9819
9981
|
if (baseUrl) {
|
|
9820
9982
|
if (recordingFile.samplerate) {
|
|
9821
9983
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9822
|
-
let obs = this.chunkedAudioRequestToArrayBuffer(
|
|
9984
|
+
let obs = this.chunkedAudioRequestToArrayBuffer(baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9823
9985
|
//let obs = this.fetchSprAudiofileArrayBuffer(aCtx,projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
9824
9986
|
let subscr = obs.subscribe({
|
|
9825
9987
|
next: aab => {
|
|
@@ -9856,14 +10018,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9856
10018
|
});
|
|
9857
10019
|
return wobs;
|
|
9858
10020
|
}
|
|
9859
|
-
fetchSprRecordingFileIndDbAudioBuffer(
|
|
10021
|
+
fetchSprRecordingFileIndDbAudioBuffer(persistentAudioStorageTarget, projectName, recordingFile) {
|
|
9860
10022
|
let wobs = new Observable(observer => {
|
|
9861
10023
|
if (recordingFile.session) {
|
|
9862
10024
|
let baseUrl = this.sprAudioFileUrl(projectName, recordingFile);
|
|
9863
10025
|
if (baseUrl) {
|
|
9864
10026
|
if (recordingFile.samplerate) {
|
|
9865
10027
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9866
|
-
let obs = this.chunkedInddbAudioRequest(
|
|
10028
|
+
let obs = this.chunkedInddbAudioRequest(persistentAudioStorageTarget, baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9867
10029
|
let subscr = obs.subscribe({
|
|
9868
10030
|
next: aab => {
|
|
9869
10031
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -9899,14 +10061,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9899
10061
|
});
|
|
9900
10062
|
return wobs;
|
|
9901
10063
|
}
|
|
9902
|
-
fetchRecordingFileIndDbAudioBuffer(
|
|
10064
|
+
fetchRecordingFileIndDbAudioBuffer(persistentAudioStorageTarget, projectName, recordingFile) {
|
|
9903
10065
|
let wobs = new Observable(observer => {
|
|
9904
10066
|
if (recordingFile.session) {
|
|
9905
10067
|
let baseUrl = this.audioFileUrl(projectName, recordingFile);
|
|
9906
10068
|
if (baseUrl) {
|
|
9907
10069
|
if (recordingFile.samplerate) {
|
|
9908
10070
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9909
|
-
let obs = this.chunkedInddbAudioRequest(
|
|
10071
|
+
let obs = this.chunkedInddbAudioRequest(persistentAudioStorageTarget, baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9910
10072
|
let subscr = obs.subscribe({
|
|
9911
10073
|
next: aab => {
|
|
9912
10074
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -9942,14 +10104,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9942
10104
|
});
|
|
9943
10105
|
return wobs;
|
|
9944
10106
|
}
|
|
9945
|
-
fetchSprRecordingFileNetAudioBuffer(
|
|
10107
|
+
fetchSprRecordingFileNetAudioBuffer(projectName, recordingFile) {
|
|
9946
10108
|
let wobs = new Observable(observer => {
|
|
9947
10109
|
if (recordingFile.session) {
|
|
9948
10110
|
let baseUrl = this.sprAudioFileUrl(projectName, recordingFile);
|
|
9949
10111
|
if (baseUrl) {
|
|
9950
10112
|
let seconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9951
10113
|
if (recordingFile.samplerate) {
|
|
9952
|
-
let obs = this.chunkAudioRequestToNetAudioBuffer(
|
|
10114
|
+
let obs = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, recordingFile.samplerate, seconds, recordingFile.frames);
|
|
9953
10115
|
let subscr = obs.subscribe({
|
|
9954
10116
|
next: aab => {
|
|
9955
10117
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -9990,14 +10152,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9990
10152
|
});
|
|
9991
10153
|
return wobs;
|
|
9992
10154
|
}
|
|
9993
|
-
fetchRecordingFileNetAudioBuffer(
|
|
10155
|
+
fetchRecordingFileNetAudioBuffer(projectName, recordingFile) {
|
|
9994
10156
|
let wobs = new Observable(observer => {
|
|
9995
10157
|
if (recordingFile.session) {
|
|
9996
10158
|
let baseUrl = this.audioFileUrl(projectName, recordingFile);
|
|
9997
10159
|
if (baseUrl) {
|
|
9998
10160
|
let seconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9999
10161
|
if (recordingFile.samplerate) {
|
|
10000
|
-
let obs = this.chunkAudioRequestToNetAudioBuffer(
|
|
10162
|
+
let obs = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, recordingFile.samplerate, seconds, recordingFile.frames);
|
|
10001
10163
|
let subscr = obs.subscribe({
|
|
10002
10164
|
next: aab => {
|
|
10003
10165
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -10042,83 +10204,87 @@ class RecordingService extends BasicRecordingService {
|
|
|
10042
10204
|
let wobs = new Observable(observer => {
|
|
10043
10205
|
if (recordingFile.session) {
|
|
10044
10206
|
let obs = this.fetchSprAudiofile(projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
10045
|
-
obs.subscribe(
|
|
10046
|
-
|
|
10047
|
-
|
|
10207
|
+
obs.subscribe({
|
|
10208
|
+
next: resp => {
|
|
10209
|
+
//console.log("Fetched audio file. HTTP response status: "+resp.status+", type: "+resp.type+", byte length: "+ resp.body.byteLength);
|
|
10210
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
10211
|
+
if (resp.body) {
|
|
10212
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
10213
|
+
let abs = new AudioBufferSource(ab);
|
|
10214
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(abs));
|
|
10215
|
+
if (this.debugDelay > 0) {
|
|
10216
|
+
window.setTimeout(() => {
|
|
10217
|
+
observer.next(recordingFile);
|
|
10218
|
+
observer.complete();
|
|
10219
|
+
}, this.debugDelay);
|
|
10220
|
+
}
|
|
10221
|
+
else {
|
|
10222
|
+
observer.next(recordingFile);
|
|
10223
|
+
observer.complete();
|
|
10224
|
+
}
|
|
10225
|
+
}).catch(error => {
|
|
10226
|
+
observer.error(error);
|
|
10227
|
+
observer.complete();
|
|
10228
|
+
});
|
|
10229
|
+
}
|
|
10230
|
+
else {
|
|
10231
|
+
observer.error('Fetching audio file: response has no body');
|
|
10232
|
+
}
|
|
10233
|
+
},
|
|
10234
|
+
error: (err) => {
|
|
10235
|
+
if (err instanceof HttpErrorResponse && err.status == 404) {
|
|
10236
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
10237
|
+
observer.next(null);
|
|
10238
|
+
observer.complete();
|
|
10239
|
+
}
|
|
10240
|
+
else {
|
|
10241
|
+
// all other states are errors
|
|
10242
|
+
observer.error(err);
|
|
10243
|
+
}
|
|
10244
|
+
}
|
|
10245
|
+
});
|
|
10246
|
+
}
|
|
10247
|
+
else {
|
|
10248
|
+
observer.error();
|
|
10249
|
+
}
|
|
10250
|
+
});
|
|
10251
|
+
return wobs;
|
|
10252
|
+
}
|
|
10253
|
+
fetchRecordingFile(aCtx, projectName, sessId, itemcode, version) {
|
|
10254
|
+
let wobs = new Observable(observer => {
|
|
10255
|
+
let obs = this.fetchSprAudiofile(projectName, sessId, itemcode, version);
|
|
10256
|
+
obs.subscribe({ next: resp => {
|
|
10048
10257
|
if (resp.body) {
|
|
10049
|
-
|
|
10258
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
10050
10259
|
let abs = new AudioBufferSource(ab);
|
|
10051
|
-
|
|
10260
|
+
let adh = new AudioDataHolder(abs);
|
|
10261
|
+
let rf = new SprRecordingFile(sessId, itemcode, version, adh);
|
|
10052
10262
|
if (this.debugDelay > 0) {
|
|
10053
10263
|
window.setTimeout(() => {
|
|
10054
|
-
observer.next(
|
|
10264
|
+
observer.next(rf);
|
|
10055
10265
|
observer.complete();
|
|
10056
10266
|
}, this.debugDelay);
|
|
10057
10267
|
}
|
|
10058
10268
|
else {
|
|
10059
|
-
observer.next(
|
|
10269
|
+
observer.next(rf);
|
|
10060
10270
|
observer.complete();
|
|
10061
10271
|
}
|
|
10062
|
-
}
|
|
10063
|
-
observer.error(error);
|
|
10064
|
-
observer.complete();
|
|
10065
|
-
});
|
|
10272
|
+
}).catch((reason) => { observer.error(reason); });
|
|
10066
10273
|
}
|
|
10067
10274
|
else {
|
|
10068
|
-
observer.error(
|
|
10275
|
+
observer.error();
|
|
10069
10276
|
}
|
|
10070
|
-
},
|
|
10277
|
+
},
|
|
10278
|
+
error: (err) => {
|
|
10071
10279
|
if (err instanceof HttpErrorResponse && err.status == 404) {
|
|
10072
10280
|
// Interpret not as an error, the file ist not recorded yet
|
|
10073
10281
|
observer.next(null);
|
|
10074
10282
|
observer.complete();
|
|
10075
10283
|
}
|
|
10076
10284
|
else {
|
|
10077
|
-
// all other
|
|
10285
|
+
// all other errors are real errors
|
|
10078
10286
|
observer.error(err);
|
|
10079
10287
|
}
|
|
10080
|
-
});
|
|
10081
|
-
}
|
|
10082
|
-
else {
|
|
10083
|
-
observer.error();
|
|
10084
|
-
}
|
|
10085
|
-
});
|
|
10086
|
-
return wobs;
|
|
10087
|
-
}
|
|
10088
|
-
fetchRecordingFile(aCtx, projectName, sessId, itemcode, version) {
|
|
10089
|
-
let wobs = new Observable(observer => {
|
|
10090
|
-
let obs = this.fetchSprAudiofile(projectName, sessId, itemcode, version);
|
|
10091
|
-
obs.subscribe(resp => {
|
|
10092
|
-
// Do not use Promise version, which does not work with Safari 13
|
|
10093
|
-
if (resp.body) {
|
|
10094
|
-
aCtx.decodeAudioData(resp.body, ab => {
|
|
10095
|
-
let abs = new AudioBufferSource(ab);
|
|
10096
|
-
let adh = new AudioDataHolder(abs);
|
|
10097
|
-
let rf = new SprRecordingFile(sessId, itemcode, version, adh);
|
|
10098
|
-
if (this.debugDelay > 0) {
|
|
10099
|
-
window.setTimeout(() => {
|
|
10100
|
-
observer.next(rf);
|
|
10101
|
-
observer.complete();
|
|
10102
|
-
}, this.debugDelay);
|
|
10103
|
-
}
|
|
10104
|
-
else {
|
|
10105
|
-
observer.next(rf);
|
|
10106
|
-
observer.complete();
|
|
10107
|
-
}
|
|
10108
|
-
});
|
|
10109
|
-
}
|
|
10110
|
-
else {
|
|
10111
|
-
observer.error();
|
|
10112
|
-
}
|
|
10113
|
-
}, (err) => {
|
|
10114
|
-
if (err instanceof HttpErrorResponse && err.status == 404) {
|
|
10115
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
10116
|
-
observer.next(null);
|
|
10117
|
-
observer.complete();
|
|
10118
|
-
}
|
|
10119
|
-
else {
|
|
10120
|
-
// all other errors are real errors
|
|
10121
|
-
observer.error(err);
|
|
10122
10288
|
}
|
|
10123
10289
|
});
|
|
10124
10290
|
});
|
|
@@ -10138,23 +10304,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10138
10304
|
args: [SPEECHRECORDER_CONFIG]
|
|
10139
10305
|
}] }]; } });
|
|
10140
10306
|
|
|
10141
|
-
class AudioContextProvider {
|
|
10142
|
-
static audioContextInstance() {
|
|
10143
|
-
if (!this._audioContext) {
|
|
10144
|
-
let debugFail = false;
|
|
10145
|
-
if (!window.AudioContext || typeof window.AudioContext !== 'function' || debugFail) {
|
|
10146
|
-
throw new Error('Browser does not support Web Audio API!');
|
|
10147
|
-
this._audioContext = null;
|
|
10148
|
-
}
|
|
10149
|
-
else {
|
|
10150
|
-
this._audioContext = new window.AudioContext();
|
|
10151
|
-
}
|
|
10152
|
-
}
|
|
10153
|
-
return this._audioContext;
|
|
10154
|
-
}
|
|
10155
|
-
}
|
|
10156
|
-
AudioContextProvider._audioContext = null;
|
|
10157
|
-
|
|
10158
10307
|
class Item {
|
|
10159
10308
|
constructor(_promptAsString, _training, _recording) {
|
|
10160
10309
|
this._promptAsString = _promptAsString;
|
|
@@ -10577,7 +10726,7 @@ class UploadStatus {
|
|
|
10577
10726
|
constructor() {
|
|
10578
10727
|
this._awaitNewUpload = false;
|
|
10579
10728
|
this.spinnerMode = 'determinate';
|
|
10580
|
-
this.
|
|
10729
|
+
this.colorStatus = 'primary';
|
|
10581
10730
|
this._value = 100;
|
|
10582
10731
|
this.displayValue = null;
|
|
10583
10732
|
this.toolTipText = '';
|
|
@@ -10616,13 +10765,13 @@ class UploadStatus {
|
|
|
10616
10765
|
set status(status) {
|
|
10617
10766
|
this._status = status;
|
|
10618
10767
|
if ('accent' === status) {
|
|
10619
|
-
this.
|
|
10768
|
+
this.colorStatus = 'accent';
|
|
10620
10769
|
}
|
|
10621
10770
|
else if ('warn' === status) {
|
|
10622
|
-
this.
|
|
10771
|
+
this.colorStatus = 'warn';
|
|
10623
10772
|
}
|
|
10624
10773
|
else {
|
|
10625
|
-
this.
|
|
10774
|
+
this.colorStatus = 'primary';
|
|
10626
10775
|
}
|
|
10627
10776
|
this._updateSpinner();
|
|
10628
10777
|
}
|
|
@@ -10632,12 +10781,14 @@ class UploadStatus {
|
|
|
10632
10781
|
}
|
|
10633
10782
|
UploadStatus.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: UploadStatus, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10634
10783
|
UploadStatus.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: UploadStatus, selector: "app-uploadstatus", inputs: { value: "value", awaitNewUpload: "awaitNewUpload", status: "status" }, ngImport: i0, template: `
|
|
10635
|
-
<mat-progress-spinner [mode]="spinnerMode" [color]="
|
|
10784
|
+
<mat-progress-spinner [mode]="spinnerMode" [color]="colorStatus" [diameter]="30" [strokeWidth]="5" [value]="_value"
|
|
10785
|
+
[matTooltip]="toolTipText"></mat-progress-spinner>
|
|
10636
10786
|
`, isInline: true, styles: [":host{text-align:left}\n", "mat-progress-spinner{display:inline-block}\n"], dependencies: [{ kind: "component", type: i3$1.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "diameter", "strokeWidth", "mode", "value"], exportAs: ["matProgressSpinner"] }, { kind: "directive", type: i4.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }] });
|
|
10637
10787
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: UploadStatus, decorators: [{
|
|
10638
10788
|
type: Component,
|
|
10639
10789
|
args: [{ selector: 'app-uploadstatus', template: `
|
|
10640
|
-
<mat-progress-spinner [mode]="spinnerMode" [color]="
|
|
10790
|
+
<mat-progress-spinner [mode]="spinnerMode" [color]="colorStatus" [diameter]="30" [strokeWidth]="5" [value]="_value"
|
|
10791
|
+
[matTooltip]="toolTipText"></mat-progress-spinner>
|
|
10641
10792
|
`, styles: [":host{text-align:left}\n", "mat-progress-spinner{display:inline-block}\n"] }]
|
|
10642
10793
|
}], propDecorators: { value: [{
|
|
10643
10794
|
type: Input
|
|
@@ -10746,7 +10897,7 @@ class TransportPanel extends ResponsiveComponent {
|
|
|
10746
10897
|
}
|
|
10747
10898
|
}
|
|
10748
10899
|
}
|
|
10749
|
-
TransportPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TransportPanel, deps: [{ token: i1$
|
|
10900
|
+
TransportPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TransportPanel, deps: [{ token: i1$2.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
|
|
10750
10901
|
TransportPanel.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: TransportPanel, selector: "app-sprtransport", inputs: { readonly: "readonly", actions: "actions", navigationEnabled: "navigationEnabled", pausingEnabled: "pausingEnabled" }, usesInheritance: true, ngImport: i0, template: `
|
|
10751
10902
|
<button id="bwdBtn" *ngIf="navigationEnabled" (click)="actions.bwdAction.perform()" [disabled]="bwdDisabled()"
|
|
10752
10903
|
mat-raised-button>
|
|
@@ -10791,7 +10942,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10791
10942
|
</button>
|
|
10792
10943
|
|
|
10793
10944
|
`, styles: [":host{flex:20;align-self:center;width:100%;text-align:center;align-content:center;margin:0}\n", "div{display:inline;flex:0}\n", "button{touch-action:manipulation}\n"] }]
|
|
10794
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
10945
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; }, propDecorators: { readonly: [{
|
|
10795
10946
|
type: Input
|
|
10796
10947
|
}], actions: [{
|
|
10797
10948
|
type: Input
|
|
@@ -10863,7 +11014,7 @@ class ControlPanel extends ResponsiveComponent {
|
|
|
10863
11014
|
return this._ready;
|
|
10864
11015
|
}
|
|
10865
11016
|
}
|
|
10866
|
-
ControlPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ControlPanel, deps: [{ token: i1$
|
|
11017
|
+
ControlPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ControlPanel, deps: [{ token: i1$2.BreakpointObserver }, { token: i1$3.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
10867
11018
|
ControlPanel.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: ControlPanel, selector: "app-sprcontrolpanel", inputs: { readonly: "readonly", transportActions: "transportActions", processing: "processing", statusMsg: "statusMsg", statusAlertType: "statusAlertType", statusWaiting: "statusWaiting", uploadStatus: "uploadStatus", uploadProgress: "uploadProgress", currentRecording: "currentRecording", enableUploadRecordings: "enableUploadRecordings", navigationEnabled: "navigationEnabled", ready: "ready" }, viewQueries: [{ propertyName: "statusDisplay", first: true, predicate: StatusDisplay, descendants: true, static: true }, { propertyName: "transportPanel", first: true, predicate: TransportPanel, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
10868
11019
|
<div *ngIf="!screenXs" style="flex-direction: row" >
|
|
10869
11020
|
<app-sprstatusdisplay style="flex:0 0 0" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"
|
|
@@ -10873,9 +11024,9 @@ ControlPanel.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version:
|
|
|
10873
11024
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
10874
11025
|
<app-readystateindicator [ready]="_ready"></app-readystateindicator>
|
|
10875
11026
|
</div>
|
|
10876
|
-
<div *ngIf="screenXs"style="flex-direction: column" >
|
|
11027
|
+
<div *ngIf="screenXs" style="flex-direction: column" >
|
|
10877
11028
|
<div style="flex-direction: row" class="flexFill" >
|
|
10878
|
-
<app-sprstatusdisplay style="flex:10 0 0
|
|
11029
|
+
<app-sprstatusdisplay style="flex:10 0 0" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"
|
|
10879
11030
|
class="hidden-xs"></app-sprstatusdisplay>
|
|
10880
11031
|
<app-uploadstatus style="flex:0 0 0" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
10881
11032
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
@@ -10896,9 +11047,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10896
11047
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
10897
11048
|
<app-readystateindicator [ready]="_ready"></app-readystateindicator>
|
|
10898
11049
|
</div>
|
|
10899
|
-
<div *ngIf="screenXs"style="flex-direction: column" >
|
|
11050
|
+
<div *ngIf="screenXs" style="flex-direction: column" >
|
|
10900
11051
|
<div style="flex-direction: row" class="flexFill" >
|
|
10901
|
-
<app-sprstatusdisplay style="flex:10 0 0
|
|
11052
|
+
<app-sprstatusdisplay style="flex:10 0 0" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"
|
|
10902
11053
|
class="hidden-xs"></app-sprstatusdisplay>
|
|
10903
11054
|
<app-uploadstatus style="flex:0 0 0" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
10904
11055
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
@@ -10908,7 +11059,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10908
11059
|
|
|
10909
11060
|
</div>
|
|
10910
11061
|
`, styles: ["div{align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n"] }]
|
|
10911
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
11062
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i1$3.MatDialog }]; }, propDecorators: { statusDisplay: [{
|
|
10912
11063
|
type: ViewChild,
|
|
10913
11064
|
args: [StatusDisplay, { static: true }]
|
|
10914
11065
|
}], transportPanel: [{
|
|
@@ -11559,7 +11710,7 @@ class RecordingItemControls extends ResponsiveComponent {
|
|
|
11559
11710
|
// this.status = 'ERROR';
|
|
11560
11711
|
}
|
|
11561
11712
|
}
|
|
11562
|
-
RecordingItemControls.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingItemControls, deps: [{ token: i1$
|
|
11713
|
+
RecordingItemControls.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingItemControls, deps: [{ token: i1$2.BreakpointObserver }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
11563
11714
|
RecordingItemControls.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RecordingItemControls, selector: "spr-recordingitemcontrols", inputs: { audioSignalCollapsed: "audioSignalCollapsed", enableDownload: "enableDownload", peakDbLvl: "peakDbLvl", agc: "agc", disableAudioDetails: "disableAudioDetails", audioLoaded: "audioLoaded", playStartAction: "playStartAction", playStopAction: "playStopAction", displayLevelInfos: "displayLevelInfos" }, outputs: { onShowRecordingDetails: "onShowRecordingDetails", onDownloadRecording: "onDownloadRecording" }, usesInheritance: true, ngImport: i0, template: `
|
|
11564
11715
|
<button matTooltip="Start playback" (click)="playStartAction?.perform()"
|
|
11565
11716
|
[disabled]="playStartAction?.disabled"
|
|
@@ -11608,7 +11759,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
11608
11759
|
[style.color]="(peakDbLvl > warnDbLevel)?'red':'black'">{{peakDbLvl | number:'1.1-1'}} dB </span></td></tr>
|
|
11609
11760
|
<tr *ngIf="_agc"><td>AGC:</td><td><span matTooltip="Auto gain control">{{agcString}}</span></td></tr></table></div>
|
|
11610
11761
|
`, styles: [":host{flex:0;width:100%;background:darkgray;padding:4px;box-sizing:border-box;height:100%;display:flex;flex-direction:row;flex-wrap:nowrap}\n", "span{flex:0;font-weight:700;display:inline-block;white-space:nowrap;box-sizing:border-box}\n", "button{touch-action:manipulation}\n"] }]
|
|
11611
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
11762
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { audioSignalCollapsed: [{
|
|
11612
11763
|
type: Input
|
|
11613
11764
|
}], enableDownload: [{
|
|
11614
11765
|
type: Input
|
|
@@ -11689,7 +11840,7 @@ class RecordingItemDisplay extends ResponsiveComponent {
|
|
|
11689
11840
|
let peakDBVal = levelInfo.powerLevelDB();
|
|
11690
11841
|
if (this.peakDbLvl < peakDBVal) {
|
|
11691
11842
|
this.peakDbLvl = peakDBVal;
|
|
11692
|
-
// the event comes from outside
|
|
11843
|
+
// the event comes from outside an Angular zone
|
|
11693
11844
|
this.changeDetectorRef.detectChanges();
|
|
11694
11845
|
}
|
|
11695
11846
|
this.liveLevel.update(levelInfo);
|
|
@@ -11705,7 +11856,7 @@ class RecordingItemDisplay extends ResponsiveComponent {
|
|
|
11705
11856
|
this.changeDetectorRef.detectChanges();
|
|
11706
11857
|
}
|
|
11707
11858
|
}
|
|
11708
|
-
RecordingItemDisplay.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingItemDisplay, deps: [{ token: i1$
|
|
11859
|
+
RecordingItemDisplay.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingItemDisplay, deps: [{ token: i1$2.BreakpointObserver }, { token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
11709
11860
|
RecordingItemDisplay.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RecordingItemDisplay, selector: "spr-recordingitemdisplay", inputs: { streamingMode: "streamingMode", audioSignalCollapsed: "audioSignalCollapsed", enableDownload: "enableDownload", agc: "agc", playStartAction: "playStartAction", playStopAction: "playStopAction", displayAudioBuffer: "displayAudioBuffer", displayLevelInfos: "displayLevelInfos" }, outputs: { onShowRecordingDetails: "onShowRecordingDetails", onDownloadRecording: "onDownloadRecording" }, viewQueries: [{ propertyName: "liveLevel", first: true, predicate: LevelBar, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
11710
11861
|
<div [class]="{audioStatusDisplay:!screenXs,audioStatusDisplayXs:screenXs}">
|
|
11711
11862
|
<audio-levelbar style="flex:1 0 1%" [streamingMode]="streamingMode" [displayLevelInfos]="_displayLevelInfos"></audio-levelbar>
|
|
@@ -11720,7 +11871,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
11720
11871
|
<spr-recordingitemcontrols style="flex:0 0 0px" [audioLoaded]="displayAudioBuffer!==null" [playStartAction]="playStartAction" [playStopAction]="playStopAction" [peakDbLvl]="peakDbLvl" [agc]="_agc" (onShowRecordingDetails)="onShowRecordingDetails.emit()"></spr-recordingitemcontrols>
|
|
11721
11872
|
</div>
|
|
11722
11873
|
`, styles: ["div{width:100%;background:darkgray;padding:4px;box-sizing:border-box;flex-wrap:nowrap}\n", "audio-levelbar{box-sizing:border-box}\n", ".audioStatusDisplay{display:flex;flex-direction:row;height:100px;min-height:100px}\n", ".audioStatusDisplayXs{display:flex;flex-direction:column;height:125px;min-height:125px}\n"] }]
|
|
11723
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
11874
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { liveLevel: [{
|
|
11724
11875
|
type: ViewChild,
|
|
11725
11876
|
args: [LevelBar, { static: true }]
|
|
11726
11877
|
}], streamingMode: [{
|
|
@@ -12023,6 +12174,7 @@ let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
|
|
|
12023
12174
|
this._wakeLock = false;
|
|
12024
12175
|
this._selectedDeviceId = undefined;
|
|
12025
12176
|
this._channelCount = 2;
|
|
12177
|
+
this._allowEchoCancellation = false;
|
|
12026
12178
|
this._session = null;
|
|
12027
12179
|
this._recordingFile = null;
|
|
12028
12180
|
this.startedDate = null;
|
|
@@ -12064,6 +12216,12 @@ let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
|
|
|
12064
12216
|
this.streamLevelMeasure = new StreamLevelMeasure();
|
|
12065
12217
|
this.selCaptureDeviceId = null;
|
|
12066
12218
|
}
|
|
12219
|
+
get allowEchoCancellation() {
|
|
12220
|
+
return this._allowEchoCancellation;
|
|
12221
|
+
}
|
|
12222
|
+
set allowEchoCancellation(value) {
|
|
12223
|
+
this._allowEchoCancellation = value;
|
|
12224
|
+
}
|
|
12067
12225
|
get maxAutoNetMemStoreSamples() {
|
|
12068
12226
|
return this._maxAutoNetMemStoreSamples;
|
|
12069
12227
|
}
|
|
@@ -12448,7 +12606,7 @@ let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
|
|
|
12448
12606
|
else {
|
|
12449
12607
|
console.log("Open session with default audio device for " + this._channelCount + " channels");
|
|
12450
12608
|
}
|
|
12451
|
-
this.ac.open(this._channelCount, this._selectedDeviceId, this._autoGainControlConfigs);
|
|
12609
|
+
this.ac.open(this._channelCount, this._selectedDeviceId, this._autoGainControlConfigs, this._allowEchoCancellation);
|
|
12452
12610
|
}
|
|
12453
12611
|
else {
|
|
12454
12612
|
this.ac.start();
|
|
@@ -12804,6 +12962,7 @@ class SessionManager extends BasicRecorder {
|
|
|
12804
12962
|
this.bpo = bpo;
|
|
12805
12963
|
this.renderer = renderer;
|
|
12806
12964
|
this.recFileService = recFileService;
|
|
12965
|
+
this.offlineAudioContext = null;
|
|
12807
12966
|
this.enableUploadRecordings = true;
|
|
12808
12967
|
this.enableDownloadRecordings = false;
|
|
12809
12968
|
this.status = 0 /* BLOCKED */;
|
|
@@ -12860,37 +13019,58 @@ class SessionManager extends BasicRecorder {
|
|
|
12860
13019
|
this.transportActions.nextAction.disabled = true;
|
|
12861
13020
|
this.transportActions.pauseAction.disabled = true;
|
|
12862
13021
|
this.playStartAction.disabled = true;
|
|
12863
|
-
let context
|
|
12864
|
-
try {
|
|
12865
|
-
|
|
12866
|
-
}
|
|
12867
|
-
|
|
12868
|
-
|
|
12869
|
-
|
|
12870
|
-
|
|
12871
|
-
|
|
12872
|
-
|
|
12873
|
-
|
|
12874
|
-
|
|
12875
|
-
|
|
12876
|
-
|
|
12877
|
-
|
|
12878
|
-
|
|
12879
|
-
|
|
12880
|
-
|
|
12881
|
-
|
|
12882
|
-
|
|
12883
|
-
|
|
12884
|
-
|
|
12885
|
-
|
|
12886
|
-
|
|
13022
|
+
// let context:AudioContext|null=null;
|
|
13023
|
+
// try {
|
|
13024
|
+
// context = AudioContextProvider.audioContextInstance();
|
|
13025
|
+
// } catch (err) {
|
|
13026
|
+
// this.status = Status.ERROR;
|
|
13027
|
+
// let errMsg = 'Unknown error';
|
|
13028
|
+
// if(err instanceof Error){
|
|
13029
|
+
// errMsg=err.message;
|
|
13030
|
+
// }
|
|
13031
|
+
// this.statusMsg = 'ERROR: ' + errMsg;
|
|
13032
|
+
// this.statusAlertType = 'error';
|
|
13033
|
+
// this.dialog.open(MessageDialog, {
|
|
13034
|
+
// data: {
|
|
13035
|
+
// type: 'error',
|
|
13036
|
+
// title: 'Error',
|
|
13037
|
+
// msg: errMsg,
|
|
13038
|
+
// advice: 'Please use a supported browser.',
|
|
13039
|
+
// }
|
|
13040
|
+
// });
|
|
13041
|
+
// return;
|
|
13042
|
+
// }
|
|
13043
|
+
// if(context) {
|
|
13044
|
+
// console.info("State of audio context: " + context.state)
|
|
13045
|
+
// }else{
|
|
13046
|
+
// console.info("No audio context available!");
|
|
13047
|
+
// }
|
|
13048
|
+
// if (!context || !navigator.mediaDevices) {
|
|
13049
|
+
// this.status = Status.ERROR;
|
|
13050
|
+
// let errMsg = 'Browser does not support Media streams!';
|
|
13051
|
+
// this.statusMsg = 'ERROR: ' + errMsg;
|
|
13052
|
+
// this.statusAlertType = 'error';
|
|
13053
|
+
// this.dialog.open(MessageDialog, {
|
|
13054
|
+
// data: {
|
|
13055
|
+
// type: 'error',
|
|
13056
|
+
// title: 'Error',
|
|
13057
|
+
// msg: errMsg,
|
|
13058
|
+
// advice: 'Please use a supported browser.',
|
|
13059
|
+
// }
|
|
13060
|
+
// });
|
|
13061
|
+
// return;
|
|
13062
|
+
// } else {
|
|
13063
|
+
this.ac = new AudioCapture();
|
|
13064
|
+
if (this.ac) {
|
|
13065
|
+
this.transportActions.startAction.onAction = () => this.startItem();
|
|
13066
|
+
this.ac.listener = this;
|
|
13067
|
+
this.configureStreamCaptureStream();
|
|
13068
|
+
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
13069
|
+
//this.ac.listDevices();
|
|
12887
13070
|
}
|
|
12888
13071
|
else {
|
|
12889
|
-
|
|
12890
|
-
|
|
12891
|
-
if (!context || !navigator.mediaDevices) {
|
|
12892
|
-
this.status = 9 /* ERROR */;
|
|
12893
|
-
let errMsg = 'Browser does not support Media streams!';
|
|
13072
|
+
this.transportActions.startAction.disabled = true;
|
|
13073
|
+
let errMsg = 'Browser does not support Media/Audio API!';
|
|
12894
13074
|
this.statusMsg = 'ERROR: ' + errMsg;
|
|
12895
13075
|
this.statusAlertType = 'error';
|
|
12896
13076
|
this.dialog.open(MessageDialog, {
|
|
@@ -12903,38 +13083,13 @@ class SessionManager extends BasicRecorder {
|
|
|
12903
13083
|
});
|
|
12904
13084
|
return;
|
|
12905
13085
|
}
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
//this.ac.listDevices();
|
|
12914
|
-
}
|
|
12915
|
-
else {
|
|
12916
|
-
this.transportActions.startAction.disabled = true;
|
|
12917
|
-
let errMsg = 'Browser does not support Media/Audio API!';
|
|
12918
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
12919
|
-
this.statusAlertType = 'error';
|
|
12920
|
-
this.dialog.open(MessageDialog, {
|
|
12921
|
-
data: {
|
|
12922
|
-
type: 'error',
|
|
12923
|
-
title: 'Error',
|
|
12924
|
-
msg: errMsg,
|
|
12925
|
-
advice: 'Please use a supported browser.',
|
|
12926
|
-
}
|
|
12927
|
-
});
|
|
12928
|
-
return;
|
|
12929
|
-
}
|
|
12930
|
-
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
12931
|
-
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
12932
|
-
this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
12933
|
-
this.transportActions.fwdAction.onAction = () => this.nextItem();
|
|
12934
|
-
this.transportActions.fwdNextAction.onAction = () => this.nextUnrecordedItem();
|
|
12935
|
-
this.transportActions.bwdAction.onAction = () => this.prevItem();
|
|
12936
|
-
this.playStartAction.onAction = () => this.controlAudioPlayer?.start();
|
|
12937
|
-
}
|
|
13086
|
+
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
13087
|
+
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
13088
|
+
this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
13089
|
+
this.transportActions.fwdAction.onAction = () => this.nextItem();
|
|
13090
|
+
this.transportActions.fwdNextAction.onAction = () => this.nextUnrecordedItem();
|
|
13091
|
+
this.transportActions.bwdAction.onAction = () => this.prevItem();
|
|
13092
|
+
this.playStartAction.onAction = () => this.controlAudioPlayer?.start();
|
|
12938
13093
|
this.startStopSignalState = 4 /* OFF */;
|
|
12939
13094
|
}
|
|
12940
13095
|
onKeyPress(ke) {
|
|
@@ -13241,7 +13396,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13241
13396
|
}
|
|
13242
13397
|
else {
|
|
13243
13398
|
//console.debug("Fetch audio and store to indexed db...");
|
|
13244
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileIndDbAudioBuffer(this.
|
|
13399
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileIndDbAudioBuffer(this._persistentAudioStorageTarget, this._session.project, rf).subscribe({
|
|
13245
13400
|
next: (iab) => {
|
|
13246
13401
|
//console.debug("Sessionmanager: Received inddb audio buffer: "+iab);
|
|
13247
13402
|
nextIab = iab;
|
|
@@ -13283,7 +13438,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13283
13438
|
// Fetch chunked audio buffer from network
|
|
13284
13439
|
let nextNetAb = null;
|
|
13285
13440
|
//console.debug("Fetch chunked audio from network");
|
|
13286
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileNetAudioBuffer(this.
|
|
13441
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileNetAudioBuffer(this._session.project, rf).subscribe({
|
|
13287
13442
|
next: (netAb) => {
|
|
13288
13443
|
//console.debug("Sessionmanager: Received net audio buffer: "+netAb);
|
|
13289
13444
|
nextNetAb = netAb;
|
|
@@ -13325,7 +13480,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13325
13480
|
// Fetch chunked array audio buffer
|
|
13326
13481
|
let nextAab = null;
|
|
13327
13482
|
//console.debug("Fetch audio and store to (chunked) array buffer...");
|
|
13328
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileArrayAudioBuffer(this.
|
|
13483
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileArrayAudioBuffer(this._session.project, rf).subscribe({
|
|
13329
13484
|
next: (aab) => {
|
|
13330
13485
|
nextAab = aab;
|
|
13331
13486
|
},
|
|
@@ -13363,7 +13518,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13363
13518
|
else {
|
|
13364
13519
|
// Fetch regular audio buffer
|
|
13365
13520
|
//console.debug("Fetch audio and store to audio buffer...");
|
|
13366
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this.
|
|
13521
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this._session.project, rf).subscribe({
|
|
13367
13522
|
next: (ab) => {
|
|
13368
13523
|
this.liveLevelDisplayState = State.READY;
|
|
13369
13524
|
let fabDh = null;
|
|
@@ -13750,7 +13905,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13750
13905
|
const sr = this.ac.currentSampleRate;
|
|
13751
13906
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
13752
13907
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
13753
|
-
let netAb = new NetAudioBuffer(this.
|
|
13908
|
+
let netAb = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
13754
13909
|
as = netAb;
|
|
13755
13910
|
if (this.uploadSet) {
|
|
13756
13911
|
//let rp=new ReadyProvider();
|
|
@@ -13797,7 +13952,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13797
13952
|
const sr = this.ac.currentSampleRate;
|
|
13798
13953
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
13799
13954
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
13800
|
-
const netAb = new NetAudioBuffer(this.
|
|
13955
|
+
const netAb = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
13801
13956
|
as = netAb;
|
|
13802
13957
|
if (this.uploadSet) {
|
|
13803
13958
|
this.uploadSet.onDone = (uploadSet) => {
|
|
@@ -13835,8 +13990,8 @@ class SessionManager extends BasicRecorder {
|
|
|
13835
13990
|
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
13836
13991
|
// TODO duplicate conversion for manual download
|
|
13837
13992
|
//console.log("Build wav writer...");
|
|
13838
|
-
this.processingRecording = true;
|
|
13839
13993
|
if (ab) {
|
|
13994
|
+
this.processingRecording = true;
|
|
13840
13995
|
let ww = new WavWriter();
|
|
13841
13996
|
//new REST API URL
|
|
13842
13997
|
let apiEndPoint = '';
|
|
@@ -13971,7 +14126,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13971
14126
|
}
|
|
13972
14127
|
}
|
|
13973
14128
|
}
|
|
13974
|
-
SessionManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionManager, deps: [{ token: i1$
|
|
14129
|
+
SessionManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionManager, deps: [{ token: i1$2.BreakpointObserver }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i1$3.MatDialog }, { token: SessionService }, { token: RecordingService }, { token: SpeechRecorderUploader }, { token: SPEECHRECORDER_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
13975
14130
|
SessionManager.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: SessionManager, selector: "app-sprrecordingsession", inputs: { projectName: "projectName", dataSaved: "dataSaved" }, host: { listeners: { "window:keypress": "onKeyPress($event)", "window:keydown": "onKeyDown($event)" } }, providers: [SessionService], viewQueries: [{ propertyName: "prompting", first: true, predicate: Prompting, descendants: true, static: true }, { propertyName: "liveLevelDisplay", first: true, predicate: LevelBar, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
13976
14131
|
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
13977
14132
|
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
@@ -14074,7 +14229,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
14074
14229
|
</div>
|
|
14075
14230
|
</div>
|
|
14076
14231
|
`, styles: [":host{flex:2;background:lightgrey;display:flex;flex-direction:column;margin:0;padding:0;min-height:0px;overflow:hidden}\n", ".ricontrols{display:flex;padding:4px;box-sizing:border-box;height:100%;flex-direction:row;justify-content:flex-end;align-items:center;align-content:center}\n", ".dark{background:darkgray}\n", ".controlpanel{display:flex;flex-direction:row;align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n", ".audioStatusDisplay{display:flex;flex-direction:row;height:100px;min-height:100px}\n", ".audioStatusDisplayXs{display:flex;flex-direction:column;height:125px;min-height:125px}\n"] }]
|
|
14077
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
14232
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1$3.MatDialog }, { type: SessionService }, { type: RecordingService }, { type: SpeechRecorderUploader }, { type: SpeechRecorderConfig, decorators: [{
|
|
14078
14233
|
type: Inject,
|
|
14079
14234
|
args: [SPEECHRECORDER_CONFIG]
|
|
14080
14235
|
}] }]; }, propDecorators: { projectName: [{
|
|
@@ -14344,18 +14499,10 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14344
14499
|
console.error(errMsg);
|
|
14345
14500
|
}
|
|
14346
14501
|
ngOnInit() {
|
|
14347
|
-
|
|
14348
|
-
|
|
14349
|
-
|
|
14350
|
-
|
|
14351
|
-
}
|
|
14352
|
-
this.sm.controlAudioPlayer = this.controlAudioPlayer;
|
|
14353
|
-
this.sm.statusAlertType = 'info';
|
|
14354
|
-
this.sm.statusMsg = 'Player initialized.';
|
|
14355
|
-
}
|
|
14356
|
-
catch (err) {
|
|
14357
|
-
this.handleError(err);
|
|
14358
|
-
}
|
|
14502
|
+
this.controlAudioPlayer = new AudioPlayer(this);
|
|
14503
|
+
this.sm.controlAudioPlayer = this.controlAudioPlayer;
|
|
14504
|
+
this.sm.statusAlertType = 'info';
|
|
14505
|
+
this.sm.statusMsg = 'Player initialized.';
|
|
14359
14506
|
}
|
|
14360
14507
|
ngAfterViewInit() {
|
|
14361
14508
|
// let wakeLockSupp=('wakeLock' in navigator);
|
|
@@ -14520,7 +14667,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14520
14667
|
}
|
|
14521
14668
|
else {
|
|
14522
14669
|
// all this attempts to customize the message do not work anymore (for security reasons)!!
|
|
14523
|
-
|
|
14670
|
+
const message = "Please do not leave the page, until all recordings are uploaded!";
|
|
14524
14671
|
alert(message);
|
|
14525
14672
|
e = e || window.event;
|
|
14526
14673
|
if (e) {
|
|
@@ -14612,6 +14759,9 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14612
14759
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
14613
14760
|
console.info("Project requested recording channel count: " + chCnt);
|
|
14614
14761
|
this.sm.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
14762
|
+
if (project.allowEchoCancellation !== undefined) {
|
|
14763
|
+
this.sm.allowEchoCancellation = project.allowEchoCancellation;
|
|
14764
|
+
}
|
|
14615
14765
|
if (project.chunkedRecording === true) {
|
|
14616
14766
|
console.debug("Enable chunked upload: chunkSize: " + BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS);
|
|
14617
14767
|
this.sm.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
|
|
@@ -14644,7 +14794,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14644
14794
|
projUrl = window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/wikispeech/rest/projects/?sessionId=' + this.sessionId;
|
|
14645
14795
|
}
|
|
14646
14796
|
if (projUrl) {
|
|
14647
|
-
|
|
14797
|
+
const pLoader = new XMLHttpRequest();
|
|
14648
14798
|
pLoader.open("GET", projUrl, true);
|
|
14649
14799
|
pLoader.setRequestHeader('Accept', 'application/json');
|
|
14650
14800
|
pLoader.responseType = "json";
|
|
@@ -14679,7 +14829,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14679
14829
|
this.sm.statusMsg = 'ERROR: Recording.';
|
|
14680
14830
|
}
|
|
14681
14831
|
}
|
|
14682
|
-
SpeechrecorderngComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngComponent, deps: [{ token:
|
|
14832
|
+
SpeechrecorderngComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngComponent, deps: [{ token: i4$2.ActivatedRoute }, { token: i4$2.Router }, { token: i0.ChangeDetectorRef }, { token: SessionService }, { token: ProjectService }, { token: ScriptService }, { token: RecordingService }, { token: SpeechRecorderUploader }], target: i0.ɵɵFactoryTarget.Component });
|
|
14683
14833
|
SpeechrecorderngComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: SpeechrecorderngComponent, selector: "app-speechrecorder", providers: [SessionService], viewQueries: [{ propertyName: "sm", first: true, predicate: SessionManager, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
14684
14834
|
<app-sprrecordingsession [projectName]="project?.name" [dataSaved]="dataSaved"></app-sprrecordingsession>
|
|
14685
14835
|
`, isInline: true, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0}\n"], dependencies: [{ kind: "component", type: SessionManager, selector: "app-sprrecordingsession", inputs: ["projectName", "dataSaved"] }] });
|
|
@@ -14688,7 +14838,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
14688
14838
|
args: [{ selector: 'app-speechrecorder', providers: [SessionService], template: `
|
|
14689
14839
|
<app-sprrecordingsession [projectName]="project?.name" [dataSaved]="dataSaved"></app-sprrecordingsession>
|
|
14690
14840
|
`, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0}\n"] }]
|
|
14691
|
-
}], ctorParameters: function () { return [{ type:
|
|
14841
|
+
}], ctorParameters: function () { return [{ type: i4$2.ActivatedRoute }, { type: i4$2.Router }, { type: i0.ChangeDetectorRef }, { type: SessionService }, { type: ProjectService }, { type: ScriptService }, { type: RecordingService }, { type: SpeechRecorderUploader }]; }, propDecorators: { sm: [{
|
|
14692
14842
|
type: ViewChild,
|
|
14693
14843
|
args: [SessionManager, { static: true }]
|
|
14694
14844
|
}] } });
|
|
@@ -14708,10 +14858,8 @@ class AudioDisplayPlayer {
|
|
|
14708
14858
|
this.ref = ref;
|
|
14709
14859
|
this.eRef = eRef;
|
|
14710
14860
|
this._audioUrl = null;
|
|
14711
|
-
this.aCtx = null;
|
|
14712
14861
|
this._audioClip = null;
|
|
14713
14862
|
this.currentLoader = null;
|
|
14714
|
-
//console.log("constructor: "+this.ac);
|
|
14715
14863
|
this.parentE = this.eRef.nativeElement;
|
|
14716
14864
|
this.playStartAction = new Action("Start");
|
|
14717
14865
|
this.playSelectionAction = new Action("Play selected");
|
|
@@ -14719,26 +14867,18 @@ class AudioDisplayPlayer {
|
|
|
14719
14867
|
this.status = "Player created.";
|
|
14720
14868
|
}
|
|
14721
14869
|
ngOnInit() {
|
|
14722
|
-
//console.log("OnInit: "+this.ac);
|
|
14723
14870
|
this.zoomSelectedAction = this.audioDisplayScrollPane.zoomSelectedAction;
|
|
14724
14871
|
this.zoomFitToPanelAction = this.audioDisplayScrollPane.zoomFitToPanelAction;
|
|
14725
14872
|
this.zoomOutAction = this.audioDisplayScrollPane.zoomOutAction;
|
|
14726
14873
|
this.zoomInAction = this.audioDisplayScrollPane.zoomInAction;
|
|
14727
|
-
|
|
14728
|
-
this.aCtx = AudioContextProvider.audioContextInstance();
|
|
14729
|
-
if (this.aCtx) {
|
|
14730
|
-
this.ap = new AudioPlayer(this.aCtx, this);
|
|
14731
|
-
}
|
|
14732
|
-
}
|
|
14733
|
-
catch (err) {
|
|
14734
|
-
if (err instanceof Error) {
|
|
14735
|
-
this.status = err.message;
|
|
14736
|
-
}
|
|
14737
|
-
}
|
|
14874
|
+
this.ap = new AudioPlayer(this);
|
|
14738
14875
|
}
|
|
14739
14876
|
ngAfterViewInit() {
|
|
14740
|
-
if (this.
|
|
14741
|
-
this.playStartAction.onAction = () =>
|
|
14877
|
+
if (this.ap) {
|
|
14878
|
+
this.playStartAction.onAction = () => {
|
|
14879
|
+
console.debug("Start action, player: " + this.ap);
|
|
14880
|
+
this.ap?.start();
|
|
14881
|
+
};
|
|
14742
14882
|
this.playSelectionAction.onAction = () => this.ap?.startSelected();
|
|
14743
14883
|
this.playStopAction.onAction = () => this.ap?.stop();
|
|
14744
14884
|
}
|
|
@@ -14803,15 +14943,12 @@ class AudioDisplayPlayer {
|
|
|
14803
14943
|
//console.debug("Loaded");
|
|
14804
14944
|
this.status = 'Audio file loaded.';
|
|
14805
14945
|
//console.debug("Received data ", data.byteLength);
|
|
14806
|
-
|
|
14807
|
-
|
|
14808
|
-
|
|
14809
|
-
|
|
14810
|
-
|
|
14811
|
-
|
|
14812
|
-
this.audioClip = new AudioClip(adh);
|
|
14813
|
-
});
|
|
14814
|
-
}
|
|
14946
|
+
AudioContextProvider.decodeAudioData(data).then(audioBuffer => {
|
|
14947
|
+
//console.debug("Audio Buffer Samplerate: ", audioBuffer.sampleRate)
|
|
14948
|
+
let as = new AudioBufferSource(audioBuffer);
|
|
14949
|
+
let adh = new AudioDataHolder(as);
|
|
14950
|
+
this.audioClip = new AudioClip(adh);
|
|
14951
|
+
});
|
|
14815
14952
|
}
|
|
14816
14953
|
set audioData(audioData) {
|
|
14817
14954
|
this.audioDisplayScrollPane.audioData = audioData;
|
|
@@ -14894,7 +15031,7 @@ class AudioDisplayPlayer {
|
|
|
14894
15031
|
this.status = 'ERROR';
|
|
14895
15032
|
}
|
|
14896
15033
|
}
|
|
14897
|
-
AudioDisplayPlayer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioDisplayPlayer, deps: [{ token:
|
|
15034
|
+
AudioDisplayPlayer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioDisplayPlayer, deps: [{ token: i4$2.ActivatedRoute }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
14898
15035
|
AudioDisplayPlayer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AudioDisplayPlayer, selector: "app-audiodisplayplayer", inputs: { playStartAction: "playStartAction", playStopAction: "playStopAction", playSelectionAction: "playSelectionAction", autoPlayOnSelectToggleAction: "autoPlayOnSelectToggleAction", audioData: "audioData", audioClip: "audioClip" }, viewQueries: [{ propertyName: "audioDisplayScrollPane", first: true, predicate: AudioDisplayScrollPane, descendants: true, static: true }], ngImport: i0, template: `
|
|
14899
15036
|
|
|
14900
15037
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
@@ -14925,7 +15062,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
14925
15062
|
[zoomSelectedAction]="zoomSelectedAction"
|
|
14926
15063
|
[zoomFitToPanelAction]="zoomFitToPanelAction"></audio-display-control><p>{{status}}
|
|
14927
15064
|
`, styles: [":host{display:flex;flex-direction:column;position:absolute;bottom:0;height:100%;width:100%;overflow:hidden;padding:20px;z-index:5;box-sizing:border-box;background-color:#000000bf}\n"] }]
|
|
14928
|
-
}], ctorParameters: function () { return [{ type:
|
|
15065
|
+
}], ctorParameters: function () { return [{ type: i4$2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { playStartAction: [{
|
|
14929
15066
|
type: Input
|
|
14930
15067
|
}], playStopAction: [{
|
|
14931
15068
|
type: Input
|
|
@@ -15071,41 +15208,42 @@ class RecordingFileService extends BasicRecordingService {
|
|
|
15071
15208
|
});
|
|
15072
15209
|
}
|
|
15073
15210
|
// TODO test
|
|
15074
|
-
fetchAndApplyRecordingFile(
|
|
15211
|
+
fetchAndApplyRecordingFile(recordingFile) {
|
|
15075
15212
|
let wobs = new Observable(observer => {
|
|
15076
15213
|
if (recordingFile.recordingFileId) {
|
|
15077
15214
|
let obs = this.fetchAudiofile(recordingFile.recordingFileId);
|
|
15078
|
-
obs.subscribe(resp => {
|
|
15079
|
-
|
|
15080
|
-
|
|
15081
|
-
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15215
|
+
obs.subscribe({ next: resp => {
|
|
15216
|
+
if (resp.body) {
|
|
15217
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
15218
|
+
let as = new AudioBufferSource(ab);
|
|
15219
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(as));
|
|
15220
|
+
if (this.debugDelay > 0) {
|
|
15221
|
+
window.setTimeout(() => {
|
|
15222
|
+
observer.next(recordingFile);
|
|
15223
|
+
observer.complete();
|
|
15224
|
+
}, this.debugDelay);
|
|
15225
|
+
}
|
|
15226
|
+
else {
|
|
15086
15227
|
observer.next(recordingFile);
|
|
15087
15228
|
observer.complete();
|
|
15088
|
-
}
|
|
15089
|
-
}
|
|
15090
|
-
|
|
15091
|
-
|
|
15092
|
-
|
|
15093
|
-
|
|
15094
|
-
|
|
15095
|
-
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
|
|
15103
|
-
|
|
15104
|
-
|
|
15105
|
-
|
|
15106
|
-
// all other states are errors
|
|
15107
|
-
observer.error(error);
|
|
15108
|
-
observer.complete();
|
|
15229
|
+
}
|
|
15230
|
+
}).catch(reason => { observer.error(reason); });
|
|
15231
|
+
}
|
|
15232
|
+
else {
|
|
15233
|
+
observer.error('Received no audio data!');
|
|
15234
|
+
}
|
|
15235
|
+
},
|
|
15236
|
+
error: (error) => {
|
|
15237
|
+
if (error.status == 404) {
|
|
15238
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
15239
|
+
observer.next(null);
|
|
15240
|
+
observer.complete();
|
|
15241
|
+
}
|
|
15242
|
+
else {
|
|
15243
|
+
// all other states are errors
|
|
15244
|
+
observer.error(error);
|
|
15245
|
+
observer.complete();
|
|
15246
|
+
}
|
|
15109
15247
|
}
|
|
15110
15248
|
});
|
|
15111
15249
|
}
|
|
@@ -15119,82 +15257,40 @@ class RecordingFileService extends BasicRecordingService {
|
|
|
15119
15257
|
let wobs = new Observable(observer => {
|
|
15120
15258
|
let rf = null;
|
|
15121
15259
|
let rfDescrObs = this.recordingFileDescrObserver(recordingFileId);
|
|
15122
|
-
rfDescrObs.subscribe(value => {
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15130
|
-
|
|
15131
|
-
|
|
15132
|
-
|
|
15133
|
-
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
|
|
15143
|
-
|
|
15260
|
+
rfDescrObs.subscribe({ next: value => {
|
|
15261
|
+
rf = value;
|
|
15262
|
+
}, error: (error) => {
|
|
15263
|
+
observer.error(error);
|
|
15264
|
+
}, complete: () => {
|
|
15265
|
+
let rfAudioObs = this.fetchAudiofile(recordingFileId);
|
|
15266
|
+
rfAudioObs.subscribe({
|
|
15267
|
+
next: resp => {
|
|
15268
|
+
// Do not use Promise version, which does not work with Safari 13
|
|
15269
|
+
if (resp.body) {
|
|
15270
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
15271
|
+
if (rf) {
|
|
15272
|
+
let as = new AudioBufferSource(ab);
|
|
15273
|
+
RecordingFileUtils.setAudioData(rf, new AudioDataHolder(as));
|
|
15274
|
+
}
|
|
15275
|
+
else {
|
|
15276
|
+
observer.error('Recording file object null');
|
|
15277
|
+
}
|
|
15278
|
+
if (this.debugDelay > 0) {
|
|
15279
|
+
window.setTimeout(() => {
|
|
15280
|
+
observer.next(rf);
|
|
15281
|
+
observer.complete();
|
|
15282
|
+
}, this.debugDelay);
|
|
15283
|
+
}
|
|
15284
|
+
else {
|
|
15285
|
+
observer.next(rf);
|
|
15286
|
+
observer.complete();
|
|
15287
|
+
}
|
|
15288
|
+
}).catch(reason => { observer.error(reason); });
|
|
15144
15289
|
}
|
|
15145
15290
|
else {
|
|
15146
|
-
observer.
|
|
15147
|
-
observer.complete();
|
|
15148
|
-
}
|
|
15149
|
-
});
|
|
15150
|
-
}
|
|
15151
|
-
else {
|
|
15152
|
-
observer.error('Received no audio data');
|
|
15153
|
-
}
|
|
15154
|
-
}, (error) => {
|
|
15155
|
-
if (error.status == 404) {
|
|
15156
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
15157
|
-
observer.next(null);
|
|
15158
|
-
observer.complete();
|
|
15159
|
-
}
|
|
15160
|
-
else {
|
|
15161
|
-
// all other states are errors
|
|
15162
|
-
observer.error(error);
|
|
15163
|
-
observer.complete();
|
|
15164
|
-
}
|
|
15165
|
-
});
|
|
15166
|
-
});
|
|
15167
|
-
});
|
|
15168
|
-
return wobs;
|
|
15169
|
-
}
|
|
15170
|
-
fetchSprRecordingFile(aCtx, recordingFileId) {
|
|
15171
|
-
let wobs = new Observable(observer => {
|
|
15172
|
-
let rf = null;
|
|
15173
|
-
let rfDescrObs = this.sprRecordingFileDescrObserver(recordingFileId);
|
|
15174
|
-
rfDescrObs.subscribe(value => {
|
|
15175
|
-
rf = value;
|
|
15176
|
-
}, (error) => {
|
|
15177
|
-
observer.error(error);
|
|
15178
|
-
}, () => {
|
|
15179
|
-
let sampleCnt = null;
|
|
15180
|
-
if (rf && rf.channels && rf.frames) {
|
|
15181
|
-
sampleCnt = rf.channels * rf.frames;
|
|
15182
|
-
}
|
|
15183
|
-
// TODO use download storage type depending on sample count of file
|
|
15184
|
-
if (rf && rf.samplerate && sampleCnt != null && sampleCnt > this._maxAutoNetMemStoreSamples) {
|
|
15185
|
-
const baseUrl = this.recoFileUrl(recordingFileId);
|
|
15186
|
-
const obNetAb = this.chunkAudioRequestToNetAudioBuffer(aCtx, baseUrl, 0, rf?.samplerate, BasicRecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS, rf.frames);
|
|
15187
|
-
obNetAb.subscribe({
|
|
15188
|
-
next: (nab) => {
|
|
15189
|
-
let adh = new AudioDataHolder(nab);
|
|
15190
|
-
if (rf) {
|
|
15191
|
-
RecordingFileUtils.setAudioData(rf, adh);
|
|
15192
|
-
observer.next(rf);
|
|
15291
|
+
observer.error('Received no audio data');
|
|
15193
15292
|
}
|
|
15194
15293
|
},
|
|
15195
|
-
complete: () => {
|
|
15196
|
-
observer.complete();
|
|
15197
|
-
},
|
|
15198
15294
|
error: (error) => {
|
|
15199
15295
|
if (error.status == 404) {
|
|
15200
15296
|
// Interpret not as an error, the file ist not recorded yet
|
|
@@ -15209,47 +15305,97 @@ class RecordingFileService extends BasicRecordingService {
|
|
|
15209
15305
|
}
|
|
15210
15306
|
});
|
|
15211
15307
|
}
|
|
15212
|
-
|
|
15213
|
-
|
|
15214
|
-
|
|
15215
|
-
|
|
15216
|
-
|
|
15217
|
-
|
|
15308
|
+
});
|
|
15309
|
+
});
|
|
15310
|
+
return wobs;
|
|
15311
|
+
}
|
|
15312
|
+
fetchSprRecordingFile(recordingFileId) {
|
|
15313
|
+
let wobs = new Observable(observer => {
|
|
15314
|
+
let rf = null;
|
|
15315
|
+
let rfDescrObs = this.sprRecordingFileDescrObserver(recordingFileId);
|
|
15316
|
+
rfDescrObs.subscribe({ next: value => {
|
|
15317
|
+
rf = value;
|
|
15318
|
+
},
|
|
15319
|
+
error: (error) => {
|
|
15320
|
+
observer.error(error);
|
|
15321
|
+
}, complete: () => {
|
|
15322
|
+
let sampleCnt = null;
|
|
15323
|
+
if (rf && rf.channels && rf.frames) {
|
|
15324
|
+
sampleCnt = rf.channels * rf.frames;
|
|
15325
|
+
}
|
|
15326
|
+
// TODO use download storage type depending on sample count of file
|
|
15327
|
+
if (rf && rf.samplerate && sampleCnt != null && sampleCnt > this._maxAutoNetMemStoreSamples) {
|
|
15328
|
+
const baseUrl = this.recoFileUrl(recordingFileId);
|
|
15329
|
+
const obNetAb = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, rf?.samplerate, BasicRecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS, rf.frames);
|
|
15330
|
+
obNetAb.subscribe({
|
|
15331
|
+
next: (nab) => {
|
|
15332
|
+
let adh = new AudioDataHolder(nab);
|
|
15218
15333
|
if (rf) {
|
|
15219
|
-
let as = new AudioBufferSource(ab);
|
|
15220
|
-
let adh = new AudioDataHolder(as);
|
|
15221
15334
|
RecordingFileUtils.setAudioData(rf, adh);
|
|
15335
|
+
observer.next(rf);
|
|
15336
|
+
}
|
|
15337
|
+
},
|
|
15338
|
+
complete: () => {
|
|
15339
|
+
observer.complete();
|
|
15340
|
+
},
|
|
15341
|
+
error: (error) => {
|
|
15342
|
+
if (error.status == 404) {
|
|
15343
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
15344
|
+
observer.next(null);
|
|
15345
|
+
observer.complete();
|
|
15222
15346
|
}
|
|
15223
15347
|
else {
|
|
15224
|
-
|
|
15348
|
+
// all other states are errors
|
|
15349
|
+
observer.error(error);
|
|
15350
|
+
observer.complete();
|
|
15225
15351
|
}
|
|
15226
|
-
|
|
15227
|
-
|
|
15228
|
-
|
|
15229
|
-
|
|
15230
|
-
|
|
15352
|
+
}
|
|
15353
|
+
});
|
|
15354
|
+
}
|
|
15355
|
+
else {
|
|
15356
|
+
let rfAudioObs = this.fetchAudiofile(recordingFileId);
|
|
15357
|
+
rfAudioObs.subscribe({ next: resp => {
|
|
15358
|
+
// Do not use Promise version, which does not work with Safari 13
|
|
15359
|
+
if (resp.body) {
|
|
15360
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
15361
|
+
if (rf) {
|
|
15362
|
+
let as = new AudioBufferSource(ab);
|
|
15363
|
+
let adh = new AudioDataHolder(as);
|
|
15364
|
+
RecordingFileUtils.setAudioData(rf, adh);
|
|
15365
|
+
}
|
|
15366
|
+
else {
|
|
15367
|
+
observer.error('Recording file object null');
|
|
15368
|
+
}
|
|
15369
|
+
if (this.debugDelay > 0) {
|
|
15370
|
+
window.setTimeout(() => {
|
|
15371
|
+
observer.next(rf);
|
|
15372
|
+
observer.complete();
|
|
15373
|
+
}, this.debugDelay);
|
|
15374
|
+
}
|
|
15375
|
+
else {
|
|
15376
|
+
observer.next(rf);
|
|
15377
|
+
observer.complete();
|
|
15378
|
+
}
|
|
15379
|
+
}).catch(reason => { observer.error(reason); });
|
|
15231
15380
|
}
|
|
15232
15381
|
else {
|
|
15233
|
-
observer.
|
|
15382
|
+
observer.error('Received no audio data');
|
|
15383
|
+
}
|
|
15384
|
+
},
|
|
15385
|
+
error: (error) => {
|
|
15386
|
+
if (error.status == 404) {
|
|
15387
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
15388
|
+
observer.next(null);
|
|
15234
15389
|
observer.complete();
|
|
15235
15390
|
}
|
|
15236
|
-
|
|
15237
|
-
|
|
15238
|
-
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
observer.next(null);
|
|
15245
|
-
observer.complete();
|
|
15246
|
-
}
|
|
15247
|
-
else {
|
|
15248
|
-
// all other states are errors
|
|
15249
|
-
observer.error(error);
|
|
15250
|
-
observer.complete();
|
|
15251
|
-
}
|
|
15252
|
-
});
|
|
15391
|
+
else {
|
|
15392
|
+
// all other states are errors
|
|
15393
|
+
observer.error(error);
|
|
15394
|
+
observer.complete();
|
|
15395
|
+
}
|
|
15396
|
+
}
|
|
15397
|
+
});
|
|
15398
|
+
}
|
|
15253
15399
|
}
|
|
15254
15400
|
});
|
|
15255
15401
|
});
|
|
@@ -15301,7 +15447,7 @@ RecordingFileNaviComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0
|
|
|
15301
15447
|
<legend>Versions</legend>
|
|
15302
15448
|
<mat-progress-spinner *ngIf="naviInfoLoading" mode="indeterminate" [diameter]="15"></mat-progress-spinner>
|
|
15303
15449
|
<select *ngIf="!naviInfoLoading" [disabled]="versions==null || versions.length==1" (change)="selectVersionChange($event)">
|
|
15304
|
-
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<
|
|
15450
|
+
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<ng-container *ngIf="i==0"> (latest)</ng-container></option>
|
|
15305
15451
|
</select>
|
|
15306
15452
|
</fieldset>
|
|
15307
15453
|
<fieldset>
|
|
@@ -15336,7 +15482,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
15336
15482
|
<legend>Versions</legend>
|
|
15337
15483
|
<mat-progress-spinner *ngIf="naviInfoLoading" mode="indeterminate" [diameter]="15"></mat-progress-spinner>
|
|
15338
15484
|
<select *ngIf="!naviInfoLoading" [disabled]="versions==null || versions.length==1" (change)="selectVersionChange($event)">
|
|
15339
|
-
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<
|
|
15485
|
+
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<ng-container *ngIf="i==0"> (latest)</ng-container></option>
|
|
15340
15486
|
</select>
|
|
15341
15487
|
</fieldset>
|
|
15342
15488
|
<fieldset>
|
|
@@ -15388,9 +15534,9 @@ class RecordingFileMetaComponent {
|
|
|
15388
15534
|
constructor() {
|
|
15389
15535
|
this.sessionId = null;
|
|
15390
15536
|
this._recordingFile = null;
|
|
15391
|
-
this.stateLoading = false;
|
|
15392
15537
|
this.itemCode = null;
|
|
15393
15538
|
this.uuid = null;
|
|
15539
|
+
this.stateLoading = false;
|
|
15394
15540
|
}
|
|
15395
15541
|
get recordingFile() {
|
|
15396
15542
|
return this._recordingFile;
|
|
@@ -15498,7 +15644,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
15498
15644
|
</mat-card-content>
|
|
15499
15645
|
</mat-card>
|
|
15500
15646
|
` }]
|
|
15501
|
-
}], propDecorators: { sessionId: [{
|
|
15647
|
+
}], ctorParameters: function () { return []; }, propDecorators: { sessionId: [{
|
|
15502
15648
|
type: Input
|
|
15503
15649
|
}], stateLoading: [{
|
|
15504
15650
|
type: Input
|
|
@@ -15519,7 +15665,6 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15519
15665
|
this.ref = ref;
|
|
15520
15666
|
this.eRef = eRef;
|
|
15521
15667
|
this.dialog = dialog;
|
|
15522
|
-
//protected _recordingFileId: string | number = null;
|
|
15523
15668
|
this.sessionId = null;
|
|
15524
15669
|
this.sessionIdFromRoute = null;
|
|
15525
15670
|
this.availRecFiles = null;
|
|
@@ -15528,9 +15673,11 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15528
15673
|
this.recordingFileVersion = null;
|
|
15529
15674
|
this.routedByQueryParam = false;
|
|
15530
15675
|
this.posInList = null;
|
|
15531
|
-
this.audioFetching = false;
|
|
15532
|
-
this.naviInfoLoading = false;
|
|
15533
15676
|
this.parentE = this.eRef.nativeElement;
|
|
15677
|
+
// TODO Should be initialized with false, but this causes in debug mode:
|
|
15678
|
+
// ERROR Error: NG0100: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: 'false'. Current value: 'true'. Find more at https://angular.io/errors/NG0100
|
|
15679
|
+
this.audioFetching = true;
|
|
15680
|
+
this.naviInfoLoading = false;
|
|
15534
15681
|
this.firstAction = new Action('First');
|
|
15535
15682
|
this.firstAction.onAction = () => {
|
|
15536
15683
|
this.posInList = 0;
|
|
@@ -15696,10 +15843,9 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15696
15843
|
this.recordingFile = null;
|
|
15697
15844
|
this.posInList = null;
|
|
15698
15845
|
this.updateActions();
|
|
15699
|
-
|
|
15700
|
-
|
|
15701
|
-
|
|
15702
|
-
this.recordingFileService.fetchSprRecordingFile(audioContext, rfId).subscribe(value => {
|
|
15846
|
+
this.audioFetching = true;
|
|
15847
|
+
this.recordingFileService.fetchSprRecordingFile(rfId).subscribe({
|
|
15848
|
+
next: value => {
|
|
15703
15849
|
this.audioFetching = false;
|
|
15704
15850
|
this.status = 'Audio file loaded.';
|
|
15705
15851
|
let clip = null;
|
|
@@ -15737,11 +15883,11 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15737
15883
|
}
|
|
15738
15884
|
this.audioClip = clip;
|
|
15739
15885
|
this.loadedRecfile();
|
|
15740
|
-
}, error1 => {
|
|
15886
|
+
}, error: error1 => {
|
|
15741
15887
|
this.audioFetching = false;
|
|
15742
15888
|
this.status = 'Error loading audio file!';
|
|
15743
|
-
}
|
|
15744
|
-
}
|
|
15889
|
+
}
|
|
15890
|
+
});
|
|
15745
15891
|
}
|
|
15746
15892
|
loadedRecfile() {
|
|
15747
15893
|
if (this.recordingFile && !this.sessionId) {
|
|
@@ -15767,7 +15913,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15767
15913
|
this.lastAction.disabled = (this.posInList == null || itemCnt == null || this.posInList >= itemCnt - 1);
|
|
15768
15914
|
}
|
|
15769
15915
|
loadSession(sessionId) {
|
|
15770
|
-
// load session and recording file
|
|
15916
|
+
// load session and recording file metadata only when on init and when session changes
|
|
15771
15917
|
if (sessionId != this.sessionId) {
|
|
15772
15918
|
// tell UI that we are working...
|
|
15773
15919
|
this.naviInfoLoading = true;
|
|
@@ -15805,7 +15951,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15805
15951
|
else {
|
|
15806
15952
|
// rec file with itemcode already exists, add (push) this version ...
|
|
15807
15953
|
exRfsForIc.push(rfd);
|
|
15808
|
-
//
|
|
15954
|
+
// ... and sort latest version (highest version number) to lowest index
|
|
15809
15955
|
exRfsForIc.sort((rfd1, rfd2) => {
|
|
15810
15956
|
return rfd2.version - rfd1.version;
|
|
15811
15957
|
});
|
|
@@ -15859,7 +16005,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15859
16005
|
}
|
|
15860
16006
|
}
|
|
15861
16007
|
}
|
|
15862
|
-
RecordingFileViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileViewComponent, deps: [{ token: RecordingFileService }, { token: RecordingService }, { token: SessionService }, { token:
|
|
16008
|
+
RecordingFileViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileViewComponent, deps: [{ token: RecordingFileService }, { token: RecordingService }, { token: SessionService }, { token: i4$2.Router }, { token: i4$2.ActivatedRoute }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i1$3.MatDialog }], target: i0.ɵɵFactoryTarget.Component });
|
|
15863
16009
|
RecordingFileViewComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RecordingFileViewComponent, selector: "app-audiodisplayplayer", viewQueries: [{ propertyName: "ac", first: true, predicate: AudioDisplayScrollPane, descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
15864
16010
|
|
|
15865
16011
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
@@ -15898,7 +16044,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
15898
16044
|
<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>
|
|
15899
16045
|
</div>
|
|
15900
16046
|
`, 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"] }]
|
|
15901
|
-
}], ctorParameters: function () { return [{ type: RecordingFileService }, { type: RecordingService }, { type: SessionService }, { type:
|
|
16047
|
+
}], ctorParameters: function () { return [{ type: RecordingFileService }, { type: RecordingService }, { type: SessionService }, { type: i4$2.Router }, { type: i4$2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i1$3.MatDialog }]; }, propDecorators: { ac: [{
|
|
15902
16048
|
type: ViewChild,
|
|
15903
16049
|
args: [AudioDisplayScrollPane]
|
|
15904
16050
|
}] } });
|
|
@@ -15963,27 +16109,28 @@ class RecordingFileUI extends RecordingFileViewComponent {
|
|
|
15963
16109
|
sf = s.startFrame;
|
|
15964
16110
|
ef = s.endFrame;
|
|
15965
16111
|
}
|
|
15966
|
-
this.recordingFileService.saveEditSelection(this.recordingFile.recordingFileId, sr, sf, ef).subscribe((value) => {
|
|
15967
|
-
|
|
15968
|
-
|
|
15969
|
-
|
|
15970
|
-
|
|
15971
|
-
|
|
15972
|
-
|
|
15973
|
-
|
|
15974
|
-
|
|
15975
|
-
|
|
15976
|
-
|
|
15977
|
-
|
|
15978
|
-
|
|
15979
|
-
|
|
15980
|
-
|
|
16112
|
+
this.recordingFileService.saveEditSelection(this.recordingFile.recordingFileId, sr, sf, ef).subscribe({ next: (value) => { },
|
|
16113
|
+
error: () => {
|
|
16114
|
+
this.dialog.open(MessageDialog, {
|
|
16115
|
+
data: {
|
|
16116
|
+
type: 'error',
|
|
16117
|
+
title: 'Save selection edit error',
|
|
16118
|
+
msg: "Could not save edit selection to WikiSpeech server!",
|
|
16119
|
+
advice: "Please check network connection and server state."
|
|
16120
|
+
}
|
|
16121
|
+
});
|
|
16122
|
+
}, complete: () => {
|
|
16123
|
+
// Or use returned selection value from server?
|
|
16124
|
+
this.savedEditSelection = s;
|
|
16125
|
+
this.editSaved = true;
|
|
16126
|
+
this.snackBar.open('Selection edit saved successfully.', 'OK', { duration: 1500 });
|
|
16127
|
+
}
|
|
15981
16128
|
});
|
|
15982
16129
|
}
|
|
15983
16130
|
}
|
|
15984
16131
|
}
|
|
15985
16132
|
}
|
|
15986
|
-
RecordingFileUI.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileUI, deps: [{ token: RecordingFileService }, { token: RecordingService }, { token: SessionService }, { token:
|
|
16133
|
+
RecordingFileUI.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileUI, deps: [{ token: RecordingFileService }, { token: RecordingService }, { token: SessionService }, { token: i4$2.Router }, { token: i4$2.ActivatedRoute }, { token: i0.ChangeDetectorRef }, { token: i0.ElementRef }, { token: i1$3.MatDialog }, { token: i6.MatSnackBar }], target: i0.ɵɵFactoryTarget.Component });
|
|
15987
16134
|
RecordingFileUI.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RecordingFileUI, selector: "app-audiodisplayplayer", usesInheritance: true, ngImport: i0, template: `
|
|
15988
16135
|
<h1>Recording file editing</h1>
|
|
15989
16136
|
<p>On export or delivery the editing selection of the recording file is cut out. If no editing selection is applied the original file is exported.</p>
|
|
@@ -16028,7 +16175,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
16028
16175
|
|
|
16029
16176
|
<button mat-raised-button color="accent" (click)="applySelection()" [disabled]="editSaved">{{this.applyButtonText()}}</button>
|
|
16030
16177
|
`, 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"] }]
|
|
16031
|
-
}], ctorParameters: function () { return [{ type: RecordingFileService }, { type: RecordingService }, { type: SessionService }, { type:
|
|
16178
|
+
}], ctorParameters: function () { return [{ type: RecordingFileService }, { type: RecordingService }, { type: SessionService }, { type: i4$2.Router }, { type: i4$2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }, { type: i1$3.MatDialog }, { type: i6.MatSnackBar }]; } });
|
|
16032
16179
|
|
|
16033
16180
|
class MediaUtils {
|
|
16034
16181
|
static toMediaTime(timeInSeconds) {
|
|
@@ -16165,7 +16312,7 @@ RecordingList.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version:
|
|
|
16165
16312
|
</mat-card-content>
|
|
16166
16313
|
</mat-card>
|
|
16167
16314
|
|
|
16168
|
-
`, isInline: true, styles: [".monospaced{font-family:monospace}.mat-cell,.mat-header-cell{padding-left:5px;padding-right:5px}.mat-card,.mat-card-header,.mat-card-content{width:auto}.flexForm{display:flex;flex-direction:column;width:auto}.flexFill{margin:0;width:100%;height:100%;min-width:100%;min-height:100%}\n", ":host{position:relative;margin:0;padding:0;background:lightgrey;width:100%;flex:1;overflow-y:auto;min-height:0px}\n", ".selected{font-weight:700}\n"], dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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"] }, { kind: "component", type: i3$2.MatCard, selector: "mat-card", exportAs: ["matCard"] }, { kind: "component", type: i3$2.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i3$2.MatCardContent, selector: "mat-card-content, [mat-card-content], [matCardContent]" }, { kind: "component", type: i4$
|
|
16315
|
+
`, isInline: true, styles: [".monospaced{font-family:monospace}.mat-cell,.mat-header-cell{padding-left:5px;padding-right:5px}.mat-card,.mat-card-header,.mat-card-content{width:auto}.flexForm{display:flex;flex-direction:column;width:auto}.flexFill{margin:0;width:100%;height:100%;min-width:100%;min-height:100%}\n", ":host{position:relative;margin:0;padding:0;background:lightgrey;width:100%;flex:1;overflow-y:auto;min-height:0px}\n", ".selected{font-weight:700}\n"], dependencies: [{ kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i3.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"] }, { kind: "component", type: i3$2.MatCard, selector: "mat-card", exportAs: ["matCard"] }, { kind: "component", type: i3$2.MatCardHeader, selector: "mat-card-header" }, { kind: "directive", type: i3$2.MatCardContent, selector: "mat-card-content, [mat-card-content], [matCardContent]" }, { kind: "component", type: i4$3.MatTable, selector: "mat-table, table[mat-table]", exportAs: ["matTable"] }, { kind: "directive", type: i4$3.MatHeaderCellDef, selector: "[matHeaderCellDef]" }, { kind: "directive", type: i4$3.MatHeaderRowDef, selector: "[matHeaderRowDef]", inputs: ["matHeaderRowDef", "matHeaderRowDefSticky"] }, { kind: "directive", type: i4$3.MatColumnDef, selector: "[matColumnDef]", inputs: ["sticky", "matColumnDef"] }, { kind: "directive", type: i4$3.MatCellDef, selector: "[matCellDef]" }, { kind: "directive", type: i4$3.MatRowDef, selector: "[matRowDef]", inputs: ["matRowDefColumns", "matRowDefWhen"] }, { kind: "directive", type: i4$3.MatHeaderCell, selector: "mat-header-cell, th[mat-header-cell]" }, { kind: "directive", type: i4$3.MatCell, selector: "mat-cell, td[mat-cell]" }, { kind: "component", type: i4$3.MatHeaderRow, selector: "mat-header-row, tr[mat-header-row]", exportAs: ["matHeaderRow"] }, { kind: "component", type: i4$3.MatRow, selector: "mat-row, tr[mat-row]", exportAs: ["matRow"] }, { kind: "directive", type: ScrollIntoViewDirective, selector: "[scrollIntoViewToBottom]", inputs: ["scrollIntoViewToBottom"] }, { kind: "pipe", type: i1$1.DatePipe, name: "date" }] });
|
|
16169
16316
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingList, decorators: [{
|
|
16170
16317
|
type: Component,
|
|
16171
16318
|
args: [{ selector: 'app-recordinglist', template: `
|
|
@@ -16246,7 +16393,7 @@ class RecorderCombiPane extends ResponsiveComponent {
|
|
|
16246
16393
|
this.recordingListComp.selectTop();
|
|
16247
16394
|
}
|
|
16248
16395
|
}
|
|
16249
|
-
RecorderCombiPane.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecorderCombiPane, deps: [{ token: i1$
|
|
16396
|
+
RecorderCombiPane.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecorderCombiPane, deps: [{ token: i1$2.BreakpointObserver }], target: i0.ɵɵFactoryTarget.Component });
|
|
16250
16397
|
RecorderCombiPane.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RecorderCombiPane, selector: "app-recordercombipane", inputs: { selectDisabled: "selectDisabled", selectedRecordingFile: "selectedRecordingFile", audioSignalCollapsed: "audioSignalCollapsed", displayAudioClip: "displayAudioClip", playStartAction: "playStartAction", playSelectionAction: "playSelectionAction", autoPlayOnSelectToggleAction: "autoPlayOnSelectToggleAction", playStopAction: "playStopAction" }, outputs: { selectedRecordingFileChanged: "selectedRecordingFileChanged" }, viewQueries: [{ propertyName: "recordingListComp", first: true, predicate: RecordingList, descendants: true }, { propertyName: "audioDisplay", first: true, predicate: AudioDisplay, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
16251
16398
|
<div class="scrollList">
|
|
16252
16399
|
<app-recordinglist [selectedRecordingFile]="selectedRecordingFile" [selectDisabled]="selectDisabled" (selectedRecordingFileChanged)="selectRecordingFile($event)"></app-recordinglist>
|
|
@@ -16275,7 +16422,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
16275
16422
|
[playStopAction]="playStopAction"></app-audiodisplay>
|
|
16276
16423
|
</div>
|
|
16277
16424
|
`, styles: [".monospaced{font-family:monospace}.mat-cell,.mat-header-cell{padding-left:5px;padding-right:5px}.mat-card,.mat-card-header,.mat-card-content{width:auto}.flexForm{display:flex;flex-direction:column;width:auto}.flexFill{margin:0;width:100%;height:100%;min-width:100%;min-height:100%}\n", ":host{background-color:#ff0;position:relative;margin:0;padding:0;background:lightgrey;width:100%;flex:1;min-height:0px}\n", ".scrollList{margin:0;padding:0;background:lightgrey;width:100%;height:100%;overflow-y:auto}\n", ".collapsable{display:none;position:absolute;z-index:5}\n", ".collapsable.active{display:flex;position:absolute;bottom:0;height:90%;width:100%;overflow:hidden;padding:0;z-index:200;box-sizing:border-box;background-color:#0000}\n"] }]
|
|
16278
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
16425
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; }, propDecorators: { recordingListComp: [{
|
|
16279
16426
|
type: ViewChild,
|
|
16280
16427
|
args: [RecordingList]
|
|
16281
16428
|
}], selectDisabled: [{
|
|
@@ -16302,11 +16449,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
16302
16449
|
}] } });
|
|
16303
16450
|
|
|
16304
16451
|
class AudioRecorder extends BasicRecorder {
|
|
16305
|
-
constructor(bpo, changeDetectorRef, renderer,
|
|
16452
|
+
constructor(bpo, changeDetectorRef, renderer, dialog, sessionService, recFileService, uploader, config) {
|
|
16306
16453
|
super(bpo, changeDetectorRef, dialog, sessionService, uploader, config);
|
|
16307
16454
|
this.bpo = bpo;
|
|
16308
16455
|
this.renderer = renderer;
|
|
16309
|
-
this.route = route;
|
|
16310
16456
|
this.recFileService = recFileService;
|
|
16311
16457
|
this.uploader = uploader;
|
|
16312
16458
|
this._project = null;
|
|
@@ -16351,38 +16497,17 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16351
16497
|
this.transportActions.nextAction.disabled = true;
|
|
16352
16498
|
this.transportActions.pauseAction.disabled = true;
|
|
16353
16499
|
this.playStartAction.disabled = true;
|
|
16354
|
-
|
|
16355
|
-
|
|
16356
|
-
|
|
16357
|
-
|
|
16358
|
-
|
|
16359
|
-
|
|
16360
|
-
this.
|
|
16361
|
-
let errMsg = 'Unknown error';
|
|
16362
|
-
if (err instanceof Error) {
|
|
16363
|
-
errMsg = err.message;
|
|
16364
|
-
}
|
|
16365
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
16366
|
-
this.statusAlertType = 'error';
|
|
16367
|
-
this.dialog.open(MessageDialog, {
|
|
16368
|
-
data: {
|
|
16369
|
-
type: 'error',
|
|
16370
|
-
title: 'Error',
|
|
16371
|
-
msg: errMsg,
|
|
16372
|
-
advice: 'Please use a supported browser.',
|
|
16373
|
-
}
|
|
16374
|
-
});
|
|
16375
|
-
return;
|
|
16376
|
-
}
|
|
16377
|
-
if (context) {
|
|
16378
|
-
console.info("State of audio context: " + context.state);
|
|
16500
|
+
this.ac = new AudioCapture();
|
|
16501
|
+
if (this.ac) {
|
|
16502
|
+
this.transportActions.startAction.onAction = () => this.startItem();
|
|
16503
|
+
this.ac.listener = this;
|
|
16504
|
+
this.configureStreamCaptureStream();
|
|
16505
|
+
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
16506
|
+
//this.ac.listDevices();
|
|
16379
16507
|
}
|
|
16380
16508
|
else {
|
|
16381
|
-
|
|
16382
|
-
|
|
16383
|
-
if (!context || !navigator.mediaDevices) {
|
|
16384
|
-
this.status = 5 /* ERROR */;
|
|
16385
|
-
let errMsg = 'Browser does not support Media streams!';
|
|
16509
|
+
this.transportActions.startAction.disabled = true;
|
|
16510
|
+
let errMsg = 'Browser does not support Media/Audio API!';
|
|
16386
16511
|
this.statusMsg = 'ERROR: ' + errMsg;
|
|
16387
16512
|
this.statusAlertType = 'error';
|
|
16388
16513
|
this.dialog.open(MessageDialog, {
|
|
@@ -16395,36 +16520,10 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16395
16520
|
});
|
|
16396
16521
|
return;
|
|
16397
16522
|
}
|
|
16398
|
-
|
|
16399
|
-
|
|
16400
|
-
|
|
16401
|
-
|
|
16402
|
-
this.transportActions.startAction.onAction = () => this.startItem();
|
|
16403
|
-
this.ac.listener = this;
|
|
16404
|
-
this.configureStreamCaptureStream();
|
|
16405
|
-
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
16406
|
-
//this.ac.listDevices();
|
|
16407
|
-
}
|
|
16408
|
-
else {
|
|
16409
|
-
this.transportActions.startAction.disabled = true;
|
|
16410
|
-
let errMsg = 'Browser does not support Media/Audio API!';
|
|
16411
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
16412
|
-
this.statusAlertType = 'error';
|
|
16413
|
-
this.dialog.open(MessageDialog, {
|
|
16414
|
-
data: {
|
|
16415
|
-
type: 'error',
|
|
16416
|
-
title: 'Error',
|
|
16417
|
-
msg: errMsg,
|
|
16418
|
-
advice: 'Please use a supported browser.',
|
|
16419
|
-
}
|
|
16420
|
-
});
|
|
16421
|
-
return;
|
|
16422
|
-
}
|
|
16423
|
-
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
16424
|
-
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
16425
|
-
//this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
16426
|
-
this.playStartAction.onAction = () => this.controlAudioPlayer?.start();
|
|
16427
|
-
}
|
|
16523
|
+
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
16524
|
+
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
16525
|
+
//this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
16526
|
+
this.playStartAction.onAction = () => this.controlAudioPlayer?.start();
|
|
16428
16527
|
this.uploader.listener = (ue) => {
|
|
16429
16528
|
this.uploadUpdate(ue);
|
|
16430
16529
|
};
|
|
@@ -16533,6 +16632,9 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16533
16632
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
16534
16633
|
console.info("Project requested recording channel count: " + chCnt);
|
|
16535
16634
|
this.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
16635
|
+
if (project.allowEchoCancellation !== undefined) {
|
|
16636
|
+
this.allowEchoCancellation = project.allowEchoCancellation;
|
|
16637
|
+
}
|
|
16536
16638
|
if (project.chunkedRecording === true) {
|
|
16537
16639
|
this.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
|
|
16538
16640
|
}
|
|
@@ -16733,7 +16835,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16733
16835
|
}
|
|
16734
16836
|
else {
|
|
16735
16837
|
//console.debug("Fetch audio and store to indexed db...");
|
|
16736
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileIndDbAudioBuffer(this.
|
|
16838
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileIndDbAudioBuffer(this._persistentAudioStorageTarget, this._session.project, rf).subscribe({
|
|
16737
16839
|
next: (iab) => {
|
|
16738
16840
|
//console.debug("Sessionmanager: Received inddb audio buffer: "+iab);
|
|
16739
16841
|
nextIab = iab;
|
|
@@ -16776,7 +16878,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16776
16878
|
// Fetch chunked audio buffer from network
|
|
16777
16879
|
let nextNetAb = null;
|
|
16778
16880
|
//console.debug("Fetch chunked audio from network");
|
|
16779
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileNetAudioBuffer(this.
|
|
16881
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileNetAudioBuffer(this._session.project, rf).subscribe({
|
|
16780
16882
|
next: (netAb) => {
|
|
16781
16883
|
//console.debug("Sessionmanager: Received net audio buffer: "+netAb);
|
|
16782
16884
|
nextNetAb = netAb;
|
|
@@ -16821,7 +16923,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16821
16923
|
// Fetch chunked array audio buffer
|
|
16822
16924
|
let nextAab = null;
|
|
16823
16925
|
//console.debug("Fetch audio and store to (chunked) array buffer...");
|
|
16824
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileArrayAudioBuffer(this.
|
|
16926
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileArrayAudioBuffer(this._session.project, rf).subscribe({
|
|
16825
16927
|
next: (aab) => {
|
|
16826
16928
|
nextAab = aab;
|
|
16827
16929
|
},
|
|
@@ -16858,7 +16960,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16858
16960
|
});
|
|
16859
16961
|
}
|
|
16860
16962
|
else {
|
|
16861
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileAudioBuffer(this.
|
|
16963
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileAudioBuffer(this._session.project, rf).subscribe({
|
|
16862
16964
|
next: ab => {
|
|
16863
16965
|
this.liveLevelDisplayState = State.READY;
|
|
16864
16966
|
let fabDh = null;
|
|
@@ -16997,7 +17099,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16997
17099
|
this.transportActions.pauseAction.disabled = true;
|
|
16998
17100
|
this.statusAlertType = 'info';
|
|
16999
17101
|
this.statusMsg = 'Recorded.';
|
|
17000
|
-
let
|
|
17102
|
+
let ab = null;
|
|
17001
17103
|
if (this.ac) {
|
|
17002
17104
|
let adh = null;
|
|
17003
17105
|
let as = null;
|
|
@@ -17029,7 +17131,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17029
17131
|
const sr = this.ac.currentSampleRate;
|
|
17030
17132
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
17031
17133
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
17032
|
-
let netAs = new NetAudioBuffer(this.
|
|
17134
|
+
let netAs = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
17033
17135
|
as = netAs;
|
|
17034
17136
|
if (this.uploadSet) {
|
|
17035
17137
|
this.uploadSet.onDone = (uploadSet) => {
|
|
@@ -17076,7 +17178,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17076
17178
|
const sr = this.ac.currentSampleRate;
|
|
17077
17179
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
17078
17180
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
17079
|
-
let netAs = new NetAudioBuffer(this.
|
|
17181
|
+
let netAs = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
17080
17182
|
as = netAs;
|
|
17081
17183
|
if (this.uploadSet) {
|
|
17082
17184
|
this.uploadSet.onDone = (uploadSet) => {
|
|
@@ -17095,7 +17197,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17095
17197
|
as = this.ac.audioBufferArray();
|
|
17096
17198
|
}
|
|
17097
17199
|
else {
|
|
17098
|
-
|
|
17200
|
+
ab = this.ac.audioBuffer();
|
|
17099
17201
|
if (ab) {
|
|
17100
17202
|
as = new AudioBufferSource(ab);
|
|
17101
17203
|
}
|
|
@@ -17115,7 +17217,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17115
17217
|
RecordingFileUtils.setAudioData(rf, adh);
|
|
17116
17218
|
this.recorderCombiPane.addRecFile(rf);
|
|
17117
17219
|
// Upload if upload enabled and not in chunked upload mode
|
|
17118
|
-
if (this.enableUploadRecordings && this._uploadChunkSizeSeconds === null && rf != null &&
|
|
17220
|
+
if (this.enableUploadRecordings && this._uploadChunkSizeSeconds === null && AudioStorageType.MEM_ENTIRE === this._clientAudioStorageType && rf != null && ab != null) {
|
|
17119
17221
|
let apiEndPoint = '';
|
|
17120
17222
|
if (this.config && this.config.apiEndPoint) {
|
|
17121
17223
|
apiEndPoint = this.config.apiEndPoint;
|
|
@@ -17130,7 +17232,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17130
17232
|
// TODO duplicate conversion for manual download
|
|
17131
17233
|
this.processingRecording = true;
|
|
17132
17234
|
let ww = new WavWriter();
|
|
17133
|
-
ww.writeAsync(
|
|
17235
|
+
ww.writeAsync(ab, (wavFile) => {
|
|
17134
17236
|
this.postRecordingMultipart(wavFile, recUrl, rf);
|
|
17135
17237
|
this.processingRecording = false;
|
|
17136
17238
|
this.updateWakeLock();
|
|
@@ -17214,7 +17316,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17214
17316
|
}
|
|
17215
17317
|
}
|
|
17216
17318
|
}
|
|
17217
|
-
AudioRecorder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioRecorder, deps: [{ token: i1$
|
|
17319
|
+
AudioRecorder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioRecorder, deps: [{ token: i1$2.BreakpointObserver }, { token: i0.ChangeDetectorRef }, { token: i0.Renderer2 }, { token: i1$3.MatDialog }, { token: SessionService }, { token: RecordingService }, { token: SpeechRecorderUploader }, { token: SPEECHRECORDER_CONFIG }], target: i0.ɵɵFactoryTarget.Component });
|
|
17218
17320
|
AudioRecorder.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AudioRecorder, selector: "app-audiorecorder", inputs: { projectName: "projectName", dataSaved: "dataSaved" }, host: { listeners: { "window:keypress": "onKeyPress($event)", "window:keydown": "onKeyDown($event)" } }, providers: [SessionService], viewQueries: [{ propertyName: "recorderCombiPane", first: true, predicate: RecorderCombiPane, descendants: true, static: true }, { propertyName: "liveLevelDisplay", first: true, predicate: LevelBar, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
17219
17321
|
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
17220
17322
|
<app-warningbar [show]="isDefaultAudioTestSession()"
|
|
@@ -17335,7 +17437,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
17335
17437
|
</div>
|
|
17336
17438
|
</div>
|
|
17337
17439
|
`, 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{display:flex;flex-direction:row;align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n", ".startstop{width:100%;flex:1 0 30%;align-items:center;text-align:center;align-content:center}\n", ".startstopscreenxs{width:100%;flex:1 0 100%;align-items:center;text-align:center;align-content:center}\n", ".bigbutton{min-width:70px;min-height:50px;font-size:50px;border-radius:20px}\n", ".audioStatusDisplay{display:flex;flex-direction:row;height:100px;min-height:100px}\n", ".audioStatusDisplayXs{display:flex;flex-direction:column;height:125px;min-height:125px}\n"] }]
|
|
17338
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
17440
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1$3.MatDialog }, { type: SessionService }, { type: RecordingService }, { type: SpeechRecorderUploader }, { type: SpeechRecorderConfig, decorators: [{
|
|
17339
17441
|
type: Inject,
|
|
17340
17442
|
args: [SPEECHRECORDER_CONFIG]
|
|
17341
17443
|
}] }]; }, propDecorators: { projectName: [{
|
|
@@ -17366,11 +17468,7 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
17366
17468
|
this.uploader = uploader;
|
|
17367
17469
|
}
|
|
17368
17470
|
ngOnInit() {
|
|
17369
|
-
|
|
17370
|
-
let audioContext = AudioContextProvider.audioContextInstance();
|
|
17371
|
-
if (audioContext) {
|
|
17372
|
-
this.controlAudioPlayer = new AudioPlayer(audioContext, this.ar);
|
|
17373
|
-
}
|
|
17471
|
+
this.controlAudioPlayer = new AudioPlayer(this.ar);
|
|
17374
17472
|
this.ar.controlAudioPlayer = this.controlAudioPlayer;
|
|
17375
17473
|
//TODO Duplicate code in SpeechRecorderComponent
|
|
17376
17474
|
window.addEventListener('beforeunload', (e) => {
|
|
@@ -17380,7 +17478,7 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
17380
17478
|
}
|
|
17381
17479
|
else {
|
|
17382
17480
|
// all this attempts to customize the message do not work anymore (for security reasons)!!
|
|
17383
|
-
|
|
17481
|
+
const message = "Please do not leave the page, until all recordings are uploaded!";
|
|
17384
17482
|
alert(message);
|
|
17385
17483
|
e = e || window.event;
|
|
17386
17484
|
if (e) {
|
|
@@ -17480,7 +17578,7 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
17480
17578
|
return this.dataSaved && !this.ar.isActive();
|
|
17481
17579
|
}
|
|
17482
17580
|
}
|
|
17483
|
-
AudioRecorderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioRecorderComponent, deps: [{ token:
|
|
17581
|
+
AudioRecorderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioRecorderComponent, deps: [{ token: i4$2.ActivatedRoute }, { token: i4$2.Router }, { token: i0.ChangeDetectorRef }, { token: SessionService }, { token: ProjectService }, { token: SpeechRecorderUploader }], target: i0.ɵɵFactoryTarget.Component });
|
|
17484
17582
|
AudioRecorderComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: AudioRecorderComponent, selector: "app-audiorecorder-comp", providers: [SessionService], viewQueries: [{ propertyName: "ar", first: true, predicate: AudioRecorder, descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: `
|
|
17485
17583
|
<app-audiorecorder [projectName]="_project?.name" [dataSaved]="dataSaved"></app-audiorecorder>
|
|
17486
17584
|
`, isInline: true, styles: [":host{flex:2;display:flex;height:100%;flex-direction:column;min-height:0}\n"], dependencies: [{ kind: "component", type: AudioRecorder, selector: "app-audiorecorder", inputs: ["projectName", "dataSaved"] }] });
|
|
@@ -17489,7 +17587,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
17489
17587
|
args: [{ selector: 'app-audiorecorder-comp', providers: [SessionService], template: `
|
|
17490
17588
|
<app-audiorecorder [projectName]="_project?.name" [dataSaved]="dataSaved"></app-audiorecorder>
|
|
17491
17589
|
`, styles: [":host{flex:2;display:flex;height:100%;flex-direction:column;min-height:0}\n"] }]
|
|
17492
|
-
}], ctorParameters: function () { return [{ type:
|
|
17590
|
+
}], ctorParameters: function () { return [{ type: i4$2.ActivatedRoute }, { type: i4$2.Router }, { type: i0.ChangeDetectorRef }, { type: SessionService }, { type: ProjectService }, { type: SpeechRecorderUploader }]; }, propDecorators: { ar: [{
|
|
17493
17591
|
type: ViewChild,
|
|
17494
17592
|
args: [AudioRecorder, { static: true }]
|
|
17495
17593
|
}] } });
|
|
@@ -17525,7 +17623,7 @@ class SpeechrecorderngModule {
|
|
|
17525
17623
|
}
|
|
17526
17624
|
SpeechrecorderngModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
17527
17625
|
SpeechrecorderngModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngModule, declarations: [AudioSignal, Sonagram, ScrollPaneHorizontal, AudioClipUIContainer, AudioDisplayScrollPane, AudioDisplay, AudioDisplayPlayer, AudioDisplayControl, LevelBar, Progress, SimpleTrafficLight, Recinstructions, Prompter, PromptContainer, PromptingContainer, Prompting, StatusDisplay,
|
|
17528
|
-
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder], imports: [
|
|
17626
|
+
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder], imports: [i4$2.RouterModule, 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] });
|
|
17529
17627
|
SpeechrecorderngModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngModule, providers: [SessionService, ProjectService, ScriptService, RecordingService, RecordingFileService, SpeechRecorderUploader], imports: [RouterModule.forChild(SPR_ROUTES), CommonModule, MatIconModule, MatButtonModule, MatDialogModule, MatProgressBarModule, MatProgressSpinnerModule, MatTooltipModule, HttpClientModule, MatCheckboxModule, MatCardModule, MatDividerModule, MatGridListModule, MatTableModule, MatInputModule, MatSelectModule, MatSnackBarModule, MatMenuModule] });
|
|
17530
17628
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngModule, decorators: [{
|
|
17531
17629
|
type: NgModule,
|
|
@@ -17538,7 +17636,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
17538
17636
|
}]
|
|
17539
17637
|
}] });
|
|
17540
17638
|
|
|
17541
|
-
const VERSION = '3.
|
|
17639
|
+
const VERSION = '3.6.0';
|
|
17542
17640
|
|
|
17543
17641
|
/*
|
|
17544
17642
|
* Public API Surface of speechrecorderng
|