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
|
}
|
|
@@ -947,7 +947,7 @@ class ArrayAudioBufferSourceNode extends AudioSourceNode {
|
|
|
947
947
|
}
|
|
948
948
|
};
|
|
949
949
|
}
|
|
950
|
-
fillBuffer(
|
|
950
|
+
fillBuffer() {
|
|
951
951
|
if (this._arrayAudioBuffer && this._audioInputStream && this._aisBufs) {
|
|
952
952
|
let filled = this.filledFrames;
|
|
953
953
|
let bufLen = 0;
|
|
@@ -1746,7 +1746,7 @@ const aswpStr = "\n" +
|
|
|
1746
1746
|
"\n" +
|
|
1747
1747
|
" let copied=0;\n" +
|
|
1748
1748
|
" do{\n" +
|
|
1749
|
-
" if(this.currentAudioBufferAvail
|
|
1749
|
+
" if(this.currentAudioBufferAvail===0){\n" +
|
|
1750
1750
|
" let nxtBuff=this.audioBuffers.shift();\n" +
|
|
1751
1751
|
" if(nxtBuff){\n" +
|
|
1752
1752
|
" this.currentAudioBuffer=nxtBuff;\n" +
|
|
@@ -1982,9 +1982,8 @@ class IndexedDbAudioBufferSourceNode extends AudioSourceNode {
|
|
|
1982
1982
|
}
|
|
1983
1983
|
|
|
1984
1984
|
class NetAudioBuffer extends BasicAudioSource {
|
|
1985
|
-
constructor(
|
|
1985
|
+
constructor(_recFileService, _baseUrl, _channelCount, _sampleRate, _chunkFrameLen, _frameLen, _uuid = null, _orgFetchChunkFrameLen = _chunkFrameLen) {
|
|
1986
1986
|
super();
|
|
1987
|
-
this._audioContext = _audioContext;
|
|
1988
1987
|
this._recFileService = _recFileService;
|
|
1989
1988
|
this._baseUrl = _baseUrl;
|
|
1990
1989
|
this._channelCount = _channelCount;
|
|
@@ -2002,9 +2001,6 @@ class NetAudioBuffer extends BasicAudioSource {
|
|
|
2002
2001
|
get recFileService() {
|
|
2003
2002
|
return this._recFileService;
|
|
2004
2003
|
}
|
|
2005
|
-
get audioContext() {
|
|
2006
|
-
return this._audioContext;
|
|
2007
|
-
}
|
|
2008
2004
|
get baseUrl() {
|
|
2009
2005
|
return this._baseUrl;
|
|
2010
2006
|
}
|
|
@@ -2042,8 +2038,8 @@ class NetAudioBuffer extends BasicAudioSource {
|
|
|
2042
2038
|
toString() {
|
|
2043
2039
|
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();
|
|
2044
2040
|
}
|
|
2045
|
-
static fromChunkAudioBuffer(
|
|
2046
|
-
let nab = new NetAudioBuffer(
|
|
2041
|
+
static fromChunkAudioBuffer(recordingsService, baseUrl, ab, frameLen, orgFetchChunkFrameLen = ab.length) {
|
|
2042
|
+
let nab = new NetAudioBuffer(recordingsService, baseUrl, ab.numberOfChannels, ab.sampleRate, ab.length, frameLen, null, orgFetchChunkFrameLen);
|
|
2047
2043
|
nab.ready();
|
|
2048
2044
|
return nab;
|
|
2049
2045
|
}
|
|
@@ -2086,7 +2082,7 @@ class NetRandomAccessAudioStream {
|
|
|
2086
2082
|
}
|
|
2087
2083
|
chunk(baseUrl, ci, cb, errCb) {
|
|
2088
2084
|
let startFrame = ci * this._netAb.orgFetchChunkFrameLen;
|
|
2089
|
-
this._netAb.recFileService.chunkAudioRequest(
|
|
2085
|
+
this._netAb.recFileService.chunkAudioRequest(baseUrl, startFrame, this._netAb.orgFetchChunkFrameLen).subscribe({
|
|
2090
2086
|
next: (chDl) => {
|
|
2091
2087
|
if (chDl) {
|
|
2092
2088
|
const ab = chDl.decodedAudioBuffer;
|
|
@@ -2493,6 +2489,87 @@ class NetAudioBufferSourceNode extends AudioSourceNode {
|
|
|
2493
2489
|
}
|
|
2494
2490
|
}
|
|
2495
2491
|
|
|
2492
|
+
class AudioContextProvider {
|
|
2493
|
+
static audioContextInstance() {
|
|
2494
|
+
var _a;
|
|
2495
|
+
if (!this._audioContext) {
|
|
2496
|
+
let debugFail = false;
|
|
2497
|
+
if (!window.AudioContext || typeof window.AudioContext !== 'function' || debugFail) {
|
|
2498
|
+
this._audioContext = null;
|
|
2499
|
+
throw new Error('Browser does not support Web Audio API!');
|
|
2500
|
+
}
|
|
2501
|
+
else {
|
|
2502
|
+
console.debug("Get new audio context...");
|
|
2503
|
+
this._audioContext = new window.AudioContext();
|
|
2504
|
+
console.debug("Created new audio context.");
|
|
2505
|
+
this._audioContext.addEventListener('statechange', () => {
|
|
2506
|
+
var _a;
|
|
2507
|
+
console.debug("Audio context state changed: " + ((_a = this._audioContext) === null || _a === void 0 ? void 0 : _a.state));
|
|
2508
|
+
});
|
|
2509
|
+
console.debug("Created new audio context with state: " + ((_a = this._audioContext) === null || _a === void 0 ? void 0 : _a.state));
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
return this._audioContext;
|
|
2513
|
+
}
|
|
2514
|
+
// public static audioContextInstanceRunning(audioContext?:AudioContext):Promise<AudioContext>{
|
|
2515
|
+
//
|
|
2516
|
+
// return new Promise<AudioContext>((resolve,reject)=>{
|
|
2517
|
+
// let aCtx=audioContext?audioContext:AudioContextProvider.audioContextInstance();
|
|
2518
|
+
// if(aCtx) {
|
|
2519
|
+
// if(aCtx.state==='closed') {
|
|
2520
|
+
// reject(new Error('Audio context already closed.'));
|
|
2521
|
+
// }else if(aCtx.state==='running') {
|
|
2522
|
+
// resolve(aCtx);
|
|
2523
|
+
// }else{
|
|
2524
|
+
// aCtx.resume().then(() => {
|
|
2525
|
+
// if(aCtx) {
|
|
2526
|
+
// resolve(aCtx);
|
|
2527
|
+
// }else{
|
|
2528
|
+
// reject(new Error('Could not get audio context'));
|
|
2529
|
+
// }
|
|
2530
|
+
// }).catch(() => {
|
|
2531
|
+
// reject(new Error('Could not resume audio context'));
|
|
2532
|
+
// })
|
|
2533
|
+
// }
|
|
2534
|
+
// }else{
|
|
2535
|
+
// reject(new Error('Could not get audio context from browser'));
|
|
2536
|
+
// }
|
|
2537
|
+
// });
|
|
2538
|
+
// }
|
|
2539
|
+
// public static decodeAudioData(data:ArrayBuffer,audioContext?:AudioContext):Promise<AudioBuffer>{
|
|
2540
|
+
// return new Promise<AudioBuffer>((resolve,reject)=>{
|
|
2541
|
+
// // decodeAudioData requires an audio context in running state
|
|
2542
|
+
// AudioContextProvider.audioContextInstanceRunning(audioContext).then(
|
|
2543
|
+
// (aCtx)=>{
|
|
2544
|
+
// // Do not use Promise version, which does not work with Safari 13
|
|
2545
|
+
// aCtx.decodeAudioData(data,decodedData => {
|
|
2546
|
+
// resolve(decodedData);
|
|
2547
|
+
// },(reason) => {
|
|
2548
|
+
// reject(reason);
|
|
2549
|
+
// });
|
|
2550
|
+
// }
|
|
2551
|
+
// ).catch((reason)=>{
|
|
2552
|
+
// reject(reason);
|
|
2553
|
+
// })
|
|
2554
|
+
// })
|
|
2555
|
+
// }
|
|
2556
|
+
static decodeAudioData(data) {
|
|
2557
|
+
return new Promise((resolve, reject) => {
|
|
2558
|
+
if (!this._offlineAudioContext) {
|
|
2559
|
+
this._offlineAudioContext = new OfflineAudioContext(1, 44100, 44100);
|
|
2560
|
+
}
|
|
2561
|
+
// Do not use Promise version, which does not work with Safari 13
|
|
2562
|
+
this._offlineAudioContext.decodeAudioData(data, decodedData => {
|
|
2563
|
+
resolve(decodedData);
|
|
2564
|
+
}, (reason) => {
|
|
2565
|
+
reject(reason);
|
|
2566
|
+
});
|
|
2567
|
+
});
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
AudioContextProvider._audioContext = null;
|
|
2571
|
+
AudioContextProvider._offlineAudioContext = null;
|
|
2572
|
+
|
|
2496
2573
|
var EventType;
|
|
2497
2574
|
(function (EventType) {
|
|
2498
2575
|
EventType[EventType["CLOSED"] = 0] = "CLOSED";
|
|
@@ -2516,8 +2593,9 @@ class AudioPlayerEvent {
|
|
|
2516
2593
|
}
|
|
2517
2594
|
}
|
|
2518
2595
|
class AudioPlayer {
|
|
2519
|
-
constructor(
|
|
2596
|
+
constructor(listener) {
|
|
2520
2597
|
this.running = false;
|
|
2598
|
+
this.context = null;
|
|
2521
2599
|
this.ready = false;
|
|
2522
2600
|
this._audioClip = null;
|
|
2523
2601
|
this._audioSource = null;
|
|
@@ -2525,7 +2603,6 @@ class AudioPlayer {
|
|
|
2525
2603
|
this.sourceAudioWorkletNode = null;
|
|
2526
2604
|
this.playStartTime = null;
|
|
2527
2605
|
this.timerVar = null;
|
|
2528
|
-
this.context = context;
|
|
2529
2606
|
this.listener = listener;
|
|
2530
2607
|
this.bufSize = AudioPlayer.DEFAULT_BUFSIZE;
|
|
2531
2608
|
this.n = navigator;
|
|
@@ -2542,15 +2619,23 @@ class AudioPlayer {
|
|
|
2542
2619
|
this._stopAction = new Action('Stop');
|
|
2543
2620
|
this._stopAction.disabled = true;
|
|
2544
2621
|
this._stopAction.onAction = () => this.stop();
|
|
2545
|
-
this.context.addEventListener('statechange', (ev) => {
|
|
2546
|
-
if (this.context.state !== 'running') {
|
|
2547
|
-
this.stop();
|
|
2548
|
-
}
|
|
2549
|
-
});
|
|
2550
2622
|
}
|
|
2551
2623
|
get autoPlayOnSelectToggleAction() {
|
|
2552
2624
|
return this._autoPlayOnSelectToggleAction;
|
|
2553
2625
|
}
|
|
2626
|
+
_audioContext() {
|
|
2627
|
+
if (!this.context) {
|
|
2628
|
+
this.context = AudioContextProvider.audioContextInstance();
|
|
2629
|
+
if (this.context) {
|
|
2630
|
+
this.context.addEventListener('statechange', (ev) => {
|
|
2631
|
+
if (this.context && this.context.state !== 'running') {
|
|
2632
|
+
this.stop();
|
|
2633
|
+
}
|
|
2634
|
+
});
|
|
2635
|
+
}
|
|
2636
|
+
}
|
|
2637
|
+
return this.context;
|
|
2638
|
+
}
|
|
2554
2639
|
get startAction() {
|
|
2555
2640
|
return this._startAction;
|
|
2556
2641
|
}
|
|
@@ -2569,9 +2654,9 @@ class AudioPlayer {
|
|
|
2569
2654
|
chs = audioDataHolder.numberOfChannels;
|
|
2570
2655
|
if (chs > 0) {
|
|
2571
2656
|
length = audioDataHolder.frameLen;
|
|
2572
|
-
if (chs > this.context.destination.maxChannelCount) {
|
|
2573
|
-
|
|
2574
|
-
}
|
|
2657
|
+
//if (chs > this.context.destination.maxChannelCount) {
|
|
2658
|
+
// // TODO exception
|
|
2659
|
+
//}
|
|
2575
2660
|
}
|
|
2576
2661
|
this.audioSource = audioDataHolder.audioSource;
|
|
2577
2662
|
audioClip.addSelectionObserver((ac) => {
|
|
@@ -2591,16 +2676,11 @@ class AudioPlayer {
|
|
|
2591
2676
|
set audioSource(value) {
|
|
2592
2677
|
this.stop();
|
|
2593
2678
|
this._audioSource = value;
|
|
2594
|
-
if (this._audioSource
|
|
2595
|
-
|
|
2596
|
-
|
|
2597
|
-
|
|
2598
|
-
|
|
2599
|
-
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
else {
|
|
2603
|
-
this._loadSourceWorkletAndInitStart();
|
|
2679
|
+
if (this._audioSource) {
|
|
2680
|
+
this.ready = true;
|
|
2681
|
+
this.updateStartActions();
|
|
2682
|
+
if (this.listener) {
|
|
2683
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
2604
2684
|
}
|
|
2605
2685
|
}
|
|
2606
2686
|
else {
|
|
@@ -2612,24 +2692,27 @@ class AudioPlayer {
|
|
|
2612
2692
|
}
|
|
2613
2693
|
}
|
|
2614
2694
|
_loadSourceWorkletAndInitStart() {
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
|
|
2620
|
-
this.listener
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
|
|
2626
|
-
this.listener
|
|
2627
|
-
|
|
2628
|
-
|
|
2629
|
-
|
|
2695
|
+
if (this.context) {
|
|
2696
|
+
AudioSourceWorkletModuleLoader.loadModule(this.context).then(() => {
|
|
2697
|
+
//console.debug("Player ready. ( by Player::_loadSourceWorkletAndInitStart()");
|
|
2698
|
+
this.ready = true;
|
|
2699
|
+
this.updateStartActions();
|
|
2700
|
+
if (this.listener) {
|
|
2701
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.READY));
|
|
2702
|
+
}
|
|
2703
|
+
}).catch((error) => {
|
|
2704
|
+
this.ready = false;
|
|
2705
|
+
this.updateStartActions();
|
|
2706
|
+
if (this.listener) {
|
|
2707
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.CLOSED));
|
|
2708
|
+
}
|
|
2709
|
+
console.error('Could not add module ' + error);
|
|
2710
|
+
});
|
|
2711
|
+
}
|
|
2630
2712
|
}
|
|
2631
2713
|
_startAudioSourceWorkletNode() {
|
|
2632
|
-
|
|
2714
|
+
this._loadSourceWorkletAndInitStart();
|
|
2715
|
+
if (this.context && this.sourceAudioWorkletNode) {
|
|
2633
2716
|
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
2634
2717
|
let msg = 'Unknwon error';
|
|
2635
2718
|
if (ev instanceof ErrorEvent) {
|
|
@@ -2656,16 +2739,25 @@ class AudioPlayer {
|
|
|
2656
2739
|
}
|
|
2657
2740
|
}
|
|
2658
2741
|
start() {
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2742
|
+
this._audioContext();
|
|
2743
|
+
if (this.context) {
|
|
2744
|
+
if (!this._startAction.disabled && !this.running) {
|
|
2745
|
+
if (this.context.state === 'suspended') {
|
|
2746
|
+
this.context.resume().then(() => {
|
|
2747
|
+
this._start();
|
|
2748
|
+
}).catch((reason) => {
|
|
2749
|
+
console.error(reason.message());
|
|
2750
|
+
throw reason;
|
|
2751
|
+
});
|
|
2752
|
+
}
|
|
2753
|
+
else if (this.context.state === 'closed') {
|
|
2754
|
+
const msg = 'Error: Cannot start playback. Audio context is already closed!';
|
|
2755
|
+
console.error(msg);
|
|
2756
|
+
throw new Error(msg);
|
|
2757
|
+
}
|
|
2758
|
+
else {
|
|
2662
2759
|
this._start();
|
|
2663
|
-
}
|
|
2664
|
-
console.error('Could not resume audio context: ' + reason);
|
|
2665
|
-
});
|
|
2666
|
-
}
|
|
2667
|
-
else {
|
|
2668
|
-
this._start();
|
|
2760
|
+
}
|
|
2669
2761
|
}
|
|
2670
2762
|
}
|
|
2671
2763
|
}
|
|
@@ -2690,9 +2782,12 @@ class AudioPlayer {
|
|
|
2690
2782
|
}
|
|
2691
2783
|
}
|
|
2692
2784
|
startSelectionDisabled() {
|
|
2693
|
-
return !(this._audioClip &&
|
|
2785
|
+
return !(this._audioClip && !this.startAction.disabled && this._audioClip.selection);
|
|
2694
2786
|
}
|
|
2695
2787
|
_start(playSelection = false) {
|
|
2788
|
+
if (!this.context) {
|
|
2789
|
+
throw new Error("Could not get audio context!");
|
|
2790
|
+
}
|
|
2696
2791
|
if (this._audioSource instanceof AudioBufferSource) {
|
|
2697
2792
|
this.sourceBufferNode = this.context.createBufferSource();
|
|
2698
2793
|
this.sourceBufferNode.buffer = this._audioSource.audioBuffer;
|
|
@@ -2723,68 +2818,90 @@ class AudioPlayer {
|
|
|
2723
2818
|
}
|
|
2724
2819
|
}
|
|
2725
2820
|
else if (this._audioSource instanceof ArrayAudioBuffer || this._audioSource instanceof IndexedDbAudioBuffer || this._audioSource instanceof NetAudioBuffer) {
|
|
2726
|
-
this.
|
|
2727
|
-
|
|
2728
|
-
|
|
2729
|
-
|
|
2730
|
-
|
|
2731
|
-
|
|
2732
|
-
|
|
2733
|
-
const iasn = new IndexedDbAudioBufferSourceNode(this.context);
|
|
2734
|
-
iasn.inddbAudioBuffer = this._audioSource;
|
|
2735
|
-
this.sourceAudioWorkletNode = iasn;
|
|
2736
|
-
}
|
|
2737
|
-
else if (this._audioSource instanceof NetAudioBuffer) {
|
|
2738
|
-
const nabsn = new NetAudioBufferSourceNode(this.context);
|
|
2739
|
-
nabsn.netAudioBuffer = this._audioSource;
|
|
2740
|
-
this.sourceAudioWorkletNode = nabsn;
|
|
2741
|
-
}
|
|
2742
|
-
if (this.sourceAudioWorkletNode) {
|
|
2743
|
-
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
2744
|
-
let msg = 'Unknwon error';
|
|
2745
|
-
if (ev instanceof ErrorEvent) {
|
|
2746
|
-
msg = ev.message;
|
|
2821
|
+
AudioSourceWorkletModuleLoader.loadModule(this.context).then(() => {
|
|
2822
|
+
this.playStartTime = null;
|
|
2823
|
+
if (this.context) {
|
|
2824
|
+
if (this._audioSource instanceof ArrayAudioBuffer) {
|
|
2825
|
+
const aabsn = new ArrayAudioBufferSourceNode(this.context);
|
|
2826
|
+
aabsn.arrayAudioBuffer = this._audioSource;
|
|
2827
|
+
this.sourceAudioWorkletNode = aabsn;
|
|
2747
2828
|
}
|
|
2748
|
-
|
|
2749
|
-
|
|
2750
|
-
|
|
2829
|
+
else if (this._audioSource instanceof IndexedDbAudioBuffer) {
|
|
2830
|
+
const iasn = new IndexedDbAudioBufferSourceNode(this.context);
|
|
2831
|
+
iasn.inddbAudioBuffer = this._audioSource;
|
|
2832
|
+
this.sourceAudioWorkletNode = iasn;
|
|
2833
|
+
}
|
|
2834
|
+
else if (this._audioSource instanceof NetAudioBuffer) {
|
|
2835
|
+
const nabsn = new NetAudioBufferSourceNode(this.context);
|
|
2836
|
+
nabsn.netAudioBuffer = this._audioSource;
|
|
2837
|
+
this.sourceAudioWorkletNode = nabsn;
|
|
2838
|
+
}
|
|
2839
|
+
if (this.sourceAudioWorkletNode) {
|
|
2840
|
+
this.sourceAudioWorkletNode.onprocessorerror = (ev) => {
|
|
2841
|
+
let msg = 'Unknwon error';
|
|
2842
|
+
if (ev instanceof ErrorEvent) {
|
|
2843
|
+
msg = ev.message;
|
|
2844
|
+
}
|
|
2845
|
+
console.error("Audio source worklet error: " + msg);
|
|
2846
|
+
if (this.listener) {
|
|
2847
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.ERROR));
|
|
2848
|
+
}
|
|
2849
|
+
};
|
|
2850
|
+
this.sourceAudioWorkletNode.connect(this.context.destination); // this already starts playing
|
|
2851
|
+
this.sourceAudioWorkletNode.onended = () => this.onended();
|
|
2852
|
+
this.running = true;
|
|
2853
|
+
const ac = this._audioClip;
|
|
2854
|
+
let offset = 0;
|
|
2855
|
+
if (playSelection && ac && ac.selection) {
|
|
2856
|
+
const s = ac.selection;
|
|
2857
|
+
const sr = ac.audioDataHolder.sampleRate;
|
|
2858
|
+
offset = s.leftFrame / sr;
|
|
2859
|
+
const stopPosInsecs = s.rightFrame / sr;
|
|
2860
|
+
const dur = stopPosInsecs - offset;
|
|
2861
|
+
this.sourceAudioWorkletNode.start(0, offset, dur);
|
|
2862
|
+
}
|
|
2863
|
+
else {
|
|
2864
|
+
this.sourceAudioWorkletNode.start();
|
|
2865
|
+
}
|
|
2866
|
+
//this.playStartTime = this.context.currentTime - offset;
|
|
2867
|
+
this._startAction.disabled = true;
|
|
2868
|
+
this._startSelectionAction.disabled = true;
|
|
2869
|
+
this._stopAction.disabled = false;
|
|
2870
|
+
if (this.listener) {
|
|
2871
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.STARTED));
|
|
2872
|
+
}
|
|
2751
2873
|
}
|
|
2752
|
-
};
|
|
2753
|
-
this.sourceAudioWorkletNode.connect(this.context.destination); // this already starts playing
|
|
2754
|
-
this.sourceAudioWorkletNode.onended = () => this.onended();
|
|
2755
|
-
this.running = true;
|
|
2756
|
-
const ac = this._audioClip;
|
|
2757
|
-
let offset = 0;
|
|
2758
|
-
if (playSelection && ac && ac.selection) {
|
|
2759
|
-
const s = ac.selection;
|
|
2760
|
-
const sr = ac.audioDataHolder.sampleRate;
|
|
2761
|
-
offset = s.leftFrame / sr;
|
|
2762
|
-
const stopPosInsecs = s.rightFrame / sr;
|
|
2763
|
-
const dur = stopPosInsecs - offset;
|
|
2764
|
-
this.sourceAudioWorkletNode.start(0, offset, dur);
|
|
2765
|
-
}
|
|
2766
|
-
else {
|
|
2767
|
-
this.sourceAudioWorkletNode.start();
|
|
2768
2874
|
}
|
|
2769
|
-
|
|
2770
|
-
|
|
2771
|
-
this.
|
|
2772
|
-
this.
|
|
2875
|
+
}).catch((error) => {
|
|
2876
|
+
console.error(error.message);
|
|
2877
|
+
this.ready = false;
|
|
2878
|
+
this.updateStartActions();
|
|
2773
2879
|
if (this.listener) {
|
|
2774
|
-
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.
|
|
2880
|
+
this.listener.audioPlayerUpdate(new AudioPlayerEvent(EventType.CLOSED));
|
|
2775
2881
|
}
|
|
2776
|
-
|
|
2882
|
+
throw error;
|
|
2883
|
+
});
|
|
2777
2884
|
}
|
|
2778
2885
|
}
|
|
2779
2886
|
startSelected() {
|
|
2887
|
+
this._audioContext();
|
|
2888
|
+
if (!this.context) {
|
|
2889
|
+
throw new Error("Could not get audio context!");
|
|
2890
|
+
}
|
|
2780
2891
|
if (!this._startAction.disabled && !this.running) {
|
|
2781
|
-
if (this.context.state
|
|
2892
|
+
if (this.context.state === 'suspended') {
|
|
2782
2893
|
this.context.resume().then(() => {
|
|
2783
2894
|
this._start(true);
|
|
2784
2895
|
}).catch((reason) => {
|
|
2785
|
-
console.error(
|
|
2896
|
+
console.error(reason.message);
|
|
2897
|
+
throw reason;
|
|
2786
2898
|
});
|
|
2787
2899
|
}
|
|
2900
|
+
else if (this.context.state === 'closed') {
|
|
2901
|
+
const msg = 'Error: Cannot start playback of selection. Audio context is already closed!';
|
|
2902
|
+
console.error(msg);
|
|
2903
|
+
throw new Error(msg);
|
|
2904
|
+
}
|
|
2788
2905
|
else {
|
|
2789
2906
|
this._start(true);
|
|
2790
2907
|
}
|
|
@@ -2821,7 +2938,7 @@ class AudioPlayer {
|
|
|
2821
2938
|
}
|
|
2822
2939
|
get playPositionTime() {
|
|
2823
2940
|
let ppt = null;
|
|
2824
|
-
if (this.playStartTime !== null) {
|
|
2941
|
+
if (this.context && this.playStartTime !== null) {
|
|
2825
2942
|
ppt = this.context.currentTime - this.playStartTime;
|
|
2826
2943
|
}
|
|
2827
2944
|
else if (this.sourceAudioWorkletNode) {
|
|
@@ -3163,8 +3280,10 @@ const awpStr = "class AudioCaptureInterceptorProcessor extends AudioWorkletProce
|
|
|
3163
3280
|
"\n" +
|
|
3164
3281
|
"registerProcessor('capture-interceptor',AudioCaptureInterceptorProcessor);\n";
|
|
3165
3282
|
class AudioCapture {
|
|
3166
|
-
|
|
3283
|
+
//private context:AudioContext|null=null;
|
|
3284
|
+
constructor() {
|
|
3167
3285
|
this._maxAutoNetMemStoreSamples = AudioCapture.DEFAULT_MAX_NET_AUTO_MEM_STORE_SAMPLES;
|
|
3286
|
+
this.context = null;
|
|
3168
3287
|
this._recUUID = null;
|
|
3169
3288
|
this.agcStatus = null;
|
|
3170
3289
|
this.bufferingNode = null;
|
|
@@ -3179,13 +3298,7 @@ class AudioCapture {
|
|
|
3179
3298
|
this.persisted = true;
|
|
3180
3299
|
this.persistError = null;
|
|
3181
3300
|
this.inddbAudioBuffer = null;
|
|
3182
|
-
this.context = context;
|
|
3183
3301
|
this.n = navigator;
|
|
3184
|
-
this.context.addEventListener('statechange', (ev) => {
|
|
3185
|
-
if (this.context.state !== 'running') {
|
|
3186
|
-
this.close();
|
|
3187
|
-
}
|
|
3188
|
-
});
|
|
3189
3302
|
}
|
|
3190
3303
|
get maxAutoNetMemStoreSamples() {
|
|
3191
3304
|
return this._maxAutoNetMemStoreSamples;
|
|
@@ -3214,6 +3327,19 @@ class AudioCapture {
|
|
|
3214
3327
|
get opened() {
|
|
3215
3328
|
return this._opened;
|
|
3216
3329
|
}
|
|
3330
|
+
_audioContext() {
|
|
3331
|
+
if (!this.context) {
|
|
3332
|
+
this.context = AudioContextProvider.audioContextInstance();
|
|
3333
|
+
if (this.context) {
|
|
3334
|
+
this.context.addEventListener('statechange', () => {
|
|
3335
|
+
if (this.context && this.context.state !== 'running') {
|
|
3336
|
+
this.close();
|
|
3337
|
+
}
|
|
3338
|
+
});
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3341
|
+
return this.context;
|
|
3342
|
+
}
|
|
3217
3343
|
initData() {
|
|
3218
3344
|
if (!this._recUUID) {
|
|
3219
3345
|
this._recUUID = UUID.generate();
|
|
@@ -3328,119 +3454,137 @@ class AudioCapture {
|
|
|
3328
3454
|
}
|
|
3329
3455
|
}
|
|
3330
3456
|
addCaptureInterceptor() {
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
this.listener
|
|
3340
|
-
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
|
|
3347
|
-
|
|
3348
|
-
|
|
3349
|
-
|
|
3350
|
-
|
|
3351
|
-
|
|
3352
|
-
let chunk = new Array(chs);
|
|
3353
|
-
const samples = this.framesRecorded * chs;
|
|
3354
|
-
if ((AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this.audioStorageType || AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this.audioStorageType) && this.data && samples > this._maxAutoNetMemStoreSamples) {
|
|
3355
|
-
this.data = null;
|
|
3356
|
-
}
|
|
3357
|
-
//console.debug("Data initialized: "+(this.data!=null));
|
|
3358
|
-
for (let ch = 0; ch < chs; ch++) {
|
|
3359
|
-
//console.debug("Data ch initialized: "+(this.data !=null && this.data[ch] !=null));
|
|
3360
|
-
if (ch < this.channelCount) {
|
|
3361
|
-
if (dt.data[ch]) {
|
|
3362
|
-
let fa = new Float32Array(dt.data[ch]);
|
|
3363
|
-
if (this.data && this.data[ch]) {
|
|
3364
|
-
this.data[ch].push(fa);
|
|
3365
|
-
}
|
|
3366
|
-
chunk[ch] = fa;
|
|
3367
|
-
// Use samples of channel 0 to count frames (samples)
|
|
3368
|
-
if (ch == 0) {
|
|
3369
|
-
this.framesRecorded += fa.length;
|
|
3370
|
-
}
|
|
3371
|
-
}
|
|
3457
|
+
if (this.context) {
|
|
3458
|
+
const awn = new AudioWorkletNode(this.context, 'capture-interceptor');
|
|
3459
|
+
awn.onprocessorerror = (ev) => {
|
|
3460
|
+
let msg = 'Unknwon error';
|
|
3461
|
+
if (ev instanceof ErrorEvent) {
|
|
3462
|
+
msg = ev.message;
|
|
3463
|
+
}
|
|
3464
|
+
console.error("Capture audio worklet error: " + msg);
|
|
3465
|
+
if (this.listener) {
|
|
3466
|
+
this.listener.error(msg);
|
|
3467
|
+
}
|
|
3468
|
+
};
|
|
3469
|
+
let awnPt = awn.port;
|
|
3470
|
+
if (awnPt) {
|
|
3471
|
+
awnPt.onmessage = (ev) => {
|
|
3472
|
+
if (this.capturing) {
|
|
3473
|
+
let dt = ev.data;
|
|
3474
|
+
let chs = dt.chs;
|
|
3475
|
+
let adaLen = dt.data.length;
|
|
3476
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
3477
|
+
console.debug('Received data from worklet: ' + chs + ' ' + dt.len + ' Data chs: ' + adaLen);
|
|
3372
3478
|
}
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
this.
|
|
3377
|
-
// // Random test error:
|
|
3378
|
-
// if(Math.random()>0.98) {
|
|
3379
|
-
// throw new Error('Test');
|
|
3380
|
-
// }
|
|
3479
|
+
let chunk = new Array(chs);
|
|
3480
|
+
const samples = this.framesRecorded * chs;
|
|
3481
|
+
if ((AudioStorageType.MEM_ENTIRE_AUTO_NET_CHUNKED === this.audioStorageType || AudioStorageType.MEM_CHUNKED_AUTO_NET_CHUNKED === this.audioStorageType) && this.data && samples > this._maxAutoNetMemStoreSamples) {
|
|
3482
|
+
this.data = null;
|
|
3381
3483
|
}
|
|
3382
|
-
|
|
3383
|
-
|
|
3384
|
-
|
|
3385
|
-
|
|
3386
|
-
|
|
3387
|
-
|
|
3484
|
+
//console.debug("Data initialized: "+(this.data!=null));
|
|
3485
|
+
for (let ch = 0; ch < chs; ch++) {
|
|
3486
|
+
//console.debug("Data ch initialized: "+(this.data !=null && this.data[ch] !=null));
|
|
3487
|
+
if (ch < this.channelCount) {
|
|
3488
|
+
if (dt.data[ch]) {
|
|
3489
|
+
let fa = new Float32Array(dt.data[ch]);
|
|
3490
|
+
if (this.data && this.data[ch]) {
|
|
3491
|
+
this.data[ch].push(fa);
|
|
3492
|
+
}
|
|
3493
|
+
chunk[ch] = fa;
|
|
3494
|
+
// Use samples of channel 0 to count frames (samples)
|
|
3495
|
+
if (ch == 0) {
|
|
3496
|
+
this.framesRecorded += fa.length;
|
|
3497
|
+
}
|
|
3498
|
+
}
|
|
3388
3499
|
}
|
|
3389
|
-
|
|
3500
|
+
}
|
|
3501
|
+
if (this.audioOutStream) {
|
|
3390
3502
|
try {
|
|
3391
|
-
this.
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3503
|
+
this.audioOutStream.write(chunk);
|
|
3504
|
+
// // Random test error:
|
|
3505
|
+
// if(Math.random()>0.98) {
|
|
3506
|
+
// throw new Error('Test');
|
|
3507
|
+
// }
|
|
3395
3508
|
}
|
|
3396
|
-
|
|
3397
|
-
if (
|
|
3398
|
-
|
|
3399
|
-
if (err instanceof DOMException) {
|
|
3400
|
-
errExpl = ': ' + err.name + ': ' + err.message;
|
|
3401
|
-
}
|
|
3402
|
-
this.listener.error("Could not handle recorded audio data" + errExpl, "Please try to record again.");
|
|
3509
|
+
catch (err) {
|
|
3510
|
+
if (err instanceof Error) {
|
|
3511
|
+
this.persistError = err;
|
|
3403
3512
|
}
|
|
3404
3513
|
else {
|
|
3405
|
-
this.
|
|
3514
|
+
this.persistError = new Error('Error handling recorded audio data');
|
|
3515
|
+
}
|
|
3516
|
+
console.error("Capture error: " + err);
|
|
3517
|
+
try {
|
|
3518
|
+
this.stop();
|
|
3519
|
+
}
|
|
3520
|
+
catch (err2) {
|
|
3521
|
+
console.error("Capture next error (ignored): " + err2);
|
|
3522
|
+
}
|
|
3523
|
+
finally {
|
|
3524
|
+
if (this.listener) {
|
|
3525
|
+
let errExpl = '';
|
|
3526
|
+
if (err instanceof DOMException) {
|
|
3527
|
+
errExpl = ': ' + err.name + ': ' + err.message;
|
|
3528
|
+
}
|
|
3529
|
+
this.listener.error("Could not handle recorded audio data" + errExpl, "Please try to record again.");
|
|
3530
|
+
}
|
|
3531
|
+
else {
|
|
3532
|
+
this.close();
|
|
3533
|
+
}
|
|
3406
3534
|
}
|
|
3407
3535
|
}
|
|
3408
3536
|
}
|
|
3537
|
+
if (AudioStorageType.DB_CHUNKED === this._audioStorageType && this._persistentAudioStorageTarget) {
|
|
3538
|
+
this.store();
|
|
3539
|
+
}
|
|
3409
3540
|
}
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
this._opened = true;
|
|
3424
|
-
if (this.listener) {
|
|
3425
|
-
this.listener.opened();
|
|
3541
|
+
};
|
|
3542
|
+
}
|
|
3543
|
+
// Tried to fix that Safari does not record the second channel
|
|
3544
|
+
// Does not help
|
|
3545
|
+
//awn.channelCount=this.channelCount;
|
|
3546
|
+
//awn.channelCountMode='explicit';
|
|
3547
|
+
//console.debug('Channel count explicitly set to '+this.channelCount);
|
|
3548
|
+
this.bufferingNode = awn;
|
|
3549
|
+
//this.bufferingNode.channelCount=this.channelCount;
|
|
3550
|
+
this._opened = true;
|
|
3551
|
+
if (this.listener) {
|
|
3552
|
+
this.listener.opened();
|
|
3553
|
+
}
|
|
3426
3554
|
}
|
|
3427
3555
|
}
|
|
3428
|
-
open(channelCount, selDeviceId, autoGainControlConfigs) {
|
|
3556
|
+
open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation) {
|
|
3429
3557
|
//console.debug("Capture open: ctx state: "+this.context.state);
|
|
3430
|
-
|
|
3558
|
+
this.context = this._audioContext();
|
|
3559
|
+
if (!this.context) {
|
|
3560
|
+
throw new Error("Could not get audio context!");
|
|
3561
|
+
}
|
|
3562
|
+
if (this.context.state === 'suspended') {
|
|
3431
3563
|
//console.debug("Capture open: Resume context");
|
|
3432
3564
|
this.context.resume().then(() => {
|
|
3433
3565
|
//console.debug("Capture open (ctx resumed): ctx state: "+this.context.state);
|
|
3434
|
-
this._open(channelCount, selDeviceId, autoGainControlConfigs);
|
|
3566
|
+
this._open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation);
|
|
3567
|
+
}).catch((err) => {
|
|
3568
|
+
console.error(err.message);
|
|
3569
|
+
throw err;
|
|
3435
3570
|
});
|
|
3436
3571
|
}
|
|
3572
|
+
else if (this.context.state === 'closed') {
|
|
3573
|
+
const msg = 'Error on start capture: The audio context is already closed.';
|
|
3574
|
+
console.error(msg);
|
|
3575
|
+
throw new Error(msg);
|
|
3576
|
+
}
|
|
3437
3577
|
else {
|
|
3438
|
-
this._open(channelCount, selDeviceId, autoGainControlConfigs);
|
|
3578
|
+
this._open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation);
|
|
3439
3579
|
}
|
|
3440
3580
|
}
|
|
3441
|
-
_open(channelCount, selDeviceId, autoGainControlConfigs) {
|
|
3581
|
+
_open(channelCount, selDeviceId, autoGainControlConfigs, allowEchoCancellation) {
|
|
3442
3582
|
this.channelCount = channelCount;
|
|
3443
3583
|
this.framesRecorded = 0;
|
|
3584
|
+
this.context = this._audioContext();
|
|
3585
|
+
if (!this.context) {
|
|
3586
|
+
throw new Error("Could not get audio context!");
|
|
3587
|
+
}
|
|
3444
3588
|
//var msc = new AudioStreamConstr();
|
|
3445
3589
|
// var msc={};
|
|
3446
3590
|
//msc.video = false;
|
|
@@ -3548,7 +3692,7 @@ class AudioCapture {
|
|
|
3548
3692
|
audio: {
|
|
3549
3693
|
deviceId: selDeviceId,
|
|
3550
3694
|
channelCount: channelCount,
|
|
3551
|
-
|
|
3695
|
+
echoCancellation: allowEchoCancellation ? undefined : false
|
|
3552
3696
|
},
|
|
3553
3697
|
video: false,
|
|
3554
3698
|
};
|
|
@@ -3559,106 +3703,109 @@ class AudioCapture {
|
|
|
3559
3703
|
console.debug("Audio capture, AGC: " + this.agcStatus);
|
|
3560
3704
|
let ump = navigator.mediaDevices.getUserMedia(msc);
|
|
3561
3705
|
ump.then((s) => {
|
|
3562
|
-
this.
|
|
3563
|
-
|
|
3564
|
-
|
|
3565
|
-
let
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3569
|
-
|
|
3570
|
-
|
|
3571
|
-
|
|
3572
|
-
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
let
|
|
3579
|
-
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
|
|
3583
|
-
|
|
3584
|
-
|
|
3585
|
-
|
|
3586
|
-
|
|
3587
|
-
|
|
3588
|
-
|
|
3589
|
-
|
|
3590
|
-
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3599
|
-
|
|
3600
|
-
|
|
3601
|
-
//
|
|
3602
|
-
|
|
3603
|
-
|
|
3604
|
-
|
|
3605
|
-
//
|
|
3606
|
-
|
|
3607
|
-
|
|
3608
|
-
else {
|
|
3609
|
-
// Register capture interceptor module
|
|
3610
|
-
let audioWorkletModuleBlob = new Blob([awpStr], { type: 'text/javascript' });
|
|
3611
|
-
let audioWorkletModuleBlobUrl = window.URL.createObjectURL(audioWorkletModuleBlob);
|
|
3612
|
-
this.context.audioWorklet.addModule(audioWorkletModuleBlobUrl).then(() => {
|
|
3613
|
-
AudioCapture.captureInterceptorModuleRegistered = true;
|
|
3706
|
+
if (this.context) {
|
|
3707
|
+
this.stream = s;
|
|
3708
|
+
let aTracks = s.getAudioTracks();
|
|
3709
|
+
for (let i = 0; i < aTracks.length; i++) {
|
|
3710
|
+
let aTrack = aTracks[i];
|
|
3711
|
+
console.info("Track audio info: id: " + aTrack.id + " kind: " + aTrack.kind + " label: \"" + aTrack.label + "\"");
|
|
3712
|
+
let mtrSts = aTrack.getSettings();
|
|
3713
|
+
// Typescript lib.dom.ts MediaTrackSettings.channelCount is missing
|
|
3714
|
+
// https://github.com/mdn/browser-compat-data/blob/5493d8f937e05b2ddbd41b99f5bdfad4a1f2ed85/api/MediaTrackSettings.json
|
|
3715
|
+
//@ts-ignore
|
|
3716
|
+
console.info("Track audio settings: Ch cnt: " + mtrSts.channelCount + ", AGC: " + mtrSts.autoGainControl + ", Echo cancell.: " + mtrSts.echoCancellation);
|
|
3717
|
+
if (mtrSts.autoGainControl) {
|
|
3718
|
+
this.agcStatus = mtrSts.autoGainControl;
|
|
3719
|
+
}
|
|
3720
|
+
console.debug("Echo cancellation: " + mtrSts.echoCancellation);
|
|
3721
|
+
}
|
|
3722
|
+
let vTracks = s.getVideoTracks();
|
|
3723
|
+
for (let i = 0; i < vTracks.length; i++) {
|
|
3724
|
+
let vTrack = vTracks[i];
|
|
3725
|
+
console.info("Track video info: id: " + vTrack.id + " kind: " + vTrack.kind + " label: " + vTrack.label);
|
|
3726
|
+
}
|
|
3727
|
+
this.mediaStream = this.context.createMediaStreamSource(s);
|
|
3728
|
+
// stream channel count ( is always 2 !)
|
|
3729
|
+
let streamChannelCount = this.mediaStream.channelCount;
|
|
3730
|
+
console.info("Stream channel count: " + streamChannelCount);
|
|
3731
|
+
// is not set!!
|
|
3732
|
+
//this.currentSampleRate = this.mediaStream.sampleRate;
|
|
3733
|
+
this.currentSampleRate = this.context.sampleRate;
|
|
3734
|
+
console.info("Source audio node: channels: " + streamChannelCount + " samplerate: " + this.currentSampleRate);
|
|
3735
|
+
if (this.audioOutStream) {
|
|
3736
|
+
this.audioOutStream.setFormat(this.channelCount, this.currentSampleRate);
|
|
3737
|
+
}
|
|
3738
|
+
// W3C -> new name is createScriptProcessor
|
|
3739
|
+
//
|
|
3740
|
+
// Again deprecated, but AudioWorker not yet implemented in stable releases (June 2016)
|
|
3741
|
+
// AudioWorker is now AudioWorkletProcessor ... (May 2017)
|
|
3742
|
+
// Update 12-2020:
|
|
3743
|
+
// The ScriptProcessorNode Interface - DEPRECATED
|
|
3744
|
+
// Update 06-2021
|
|
3745
|
+
// AudioWorkletProcessor is here to stay. Web Audio API has now Recommendation status !
|
|
3746
|
+
if (this.context.audioWorklet) {
|
|
3747
|
+
//const workletFileName = ('file-loader!./interceptor_worklet.js');
|
|
3748
|
+
//const workletFileName = 'http://localhost:4200/assets/interceptor_worklet.js';
|
|
3749
|
+
//console.log(awpStr);
|
|
3750
|
+
if (AudioCapture.captureInterceptorModuleRegistered) {
|
|
3751
|
+
// Required capture interceptor module already registered
|
|
3614
3752
|
this.addCaptureInterceptor();
|
|
3615
|
-
}
|
|
3616
|
-
|
|
3617
|
-
|
|
3753
|
+
}
|
|
3754
|
+
else {
|
|
3755
|
+
// Register capture interceptor module
|
|
3756
|
+
let audioWorkletModuleBlob = new Blob([awpStr], { type: 'text/javascript' });
|
|
3757
|
+
let audioWorkletModuleBlobUrl = window.URL.createObjectURL(audioWorkletModuleBlob);
|
|
3758
|
+
this.context.audioWorklet.addModule(audioWorkletModuleBlobUrl).then(() => {
|
|
3759
|
+
AudioCapture.captureInterceptorModuleRegistered = true;
|
|
3760
|
+
this.addCaptureInterceptor();
|
|
3761
|
+
}).catch((error) => {
|
|
3762
|
+
console.log('Could not add module ' + error);
|
|
3763
|
+
});
|
|
3764
|
+
}
|
|
3618
3765
|
}
|
|
3619
|
-
|
|
3620
|
-
|
|
3621
|
-
|
|
3622
|
-
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3766
|
+
else if (this.context.createScriptProcessor) {
|
|
3767
|
+
// The ScriptProcessorNode Interface - DEPRECATED Only as fallback
|
|
3768
|
+
// TODO should we use streamChannelCount or channelCount here ?
|
|
3769
|
+
let scriptProcessorNode = this.context.createScriptProcessor(AudioCapture.BUFFER_SIZE, streamChannelCount, streamChannelCount);
|
|
3770
|
+
this.bufferingNode = scriptProcessorNode;
|
|
3771
|
+
let c = 0;
|
|
3772
|
+
if (scriptProcessorNode.onaudioprocess) {
|
|
3773
|
+
scriptProcessorNode.onaudioprocess = (e) => {
|
|
3774
|
+
if (this.capturing) {
|
|
3775
|
+
let inBuffer = e.inputBuffer;
|
|
3776
|
+
// only process requested count of channels
|
|
3777
|
+
let currentBuffers = new Array(channelCount);
|
|
3778
|
+
for (let ch = 0; ch < channelCount; ch++) {
|
|
3779
|
+
let chSamples = inBuffer.getChannelData(ch);
|
|
3780
|
+
let chSamplesCopy = chSamples.slice(0);
|
|
3781
|
+
currentBuffers[ch] = chSamplesCopy.slice(0);
|
|
3782
|
+
if (this.data) {
|
|
3783
|
+
this.data[ch].push(chSamplesCopy);
|
|
3784
|
+
}
|
|
3785
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
3786
|
+
console.debug("Process " + chSamplesCopy.length + " samples.");
|
|
3787
|
+
}
|
|
3788
|
+
this.framesRecorded += chSamplesCopy.length;
|
|
3638
3789
|
}
|
|
3639
|
-
|
|
3640
|
-
|
|
3790
|
+
c++;
|
|
3791
|
+
if (this.audioOutStream) {
|
|
3792
|
+
this.audioOutStream.write(currentBuffers);
|
|
3641
3793
|
}
|
|
3642
|
-
this.framesRecorded += chSamplesCopy.length;
|
|
3643
|
-
}
|
|
3644
|
-
c++;
|
|
3645
|
-
if (this.audioOutStream) {
|
|
3646
|
-
this.audioOutStream.write(currentBuffers);
|
|
3647
3794
|
}
|
|
3795
|
+
};
|
|
3796
|
+
this._opened = true;
|
|
3797
|
+
if (this.listener) {
|
|
3798
|
+
this.listener.opened();
|
|
3648
3799
|
}
|
|
3649
|
-
}
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
this.listener.opened();
|
|
3800
|
+
}
|
|
3801
|
+
else {
|
|
3802
|
+
this.listener.error('Browser does not support audio processing (ScriptProcessor.onaudioprocess method not found)!');
|
|
3653
3803
|
}
|
|
3654
3804
|
}
|
|
3655
3805
|
else {
|
|
3656
|
-
this.listener.error('Browser does not support audio processing (
|
|
3806
|
+
this.listener.error('Browser does not support audio processing (neither AudioWorkletProcessor nor ScriptProcessor)!');
|
|
3657
3807
|
}
|
|
3658
3808
|
}
|
|
3659
|
-
else {
|
|
3660
|
-
this.listener.error('Browser does not support audio processing (neither AudioWorkletProcessor nor ScriptProcessor)!');
|
|
3661
|
-
}
|
|
3662
3809
|
}, (e) => {
|
|
3663
3810
|
console.error(e + " Error name: " + e.name);
|
|
3664
3811
|
if (this.listener) {
|
|
@@ -3679,36 +3826,42 @@ class AudioCapture {
|
|
|
3679
3826
|
});
|
|
3680
3827
|
}
|
|
3681
3828
|
_start() {
|
|
3682
|
-
this.
|
|
3683
|
-
|
|
3684
|
-
this.audioOutStream
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
this.listener
|
|
3829
|
+
if (this.context) {
|
|
3830
|
+
this.initData();
|
|
3831
|
+
if (this.audioOutStream) {
|
|
3832
|
+
this.audioOutStream.nextStream();
|
|
3833
|
+
}
|
|
3834
|
+
this.capturing = true;
|
|
3835
|
+
if (this.bufferingNode) {
|
|
3836
|
+
this.mediaStream.connect(this.bufferingNode);
|
|
3837
|
+
this.bufferingNode.connect(this.context.destination);
|
|
3838
|
+
}
|
|
3839
|
+
if (this.listener) {
|
|
3840
|
+
this.listener.started();
|
|
3841
|
+
}
|
|
3693
3842
|
}
|
|
3694
3843
|
}
|
|
3695
3844
|
start() {
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
}
|
|
3700
|
-
else {
|
|
3701
|
-
console.debug("Capture start: audio context not running, state: " + aSt + ", resuming...");
|
|
3702
|
-
this.context.resume().then(() => {
|
|
3703
|
-
console.debug("Capture start: audio context resumed, starting...");
|
|
3845
|
+
if (this.context) {
|
|
3846
|
+
const aSt = this.context.state;
|
|
3847
|
+
if (aSt === 'running') {
|
|
3704
3848
|
this._start();
|
|
3705
|
-
}
|
|
3849
|
+
}
|
|
3850
|
+
else {
|
|
3851
|
+
console.debug("Capture start: audio context not running, state: " + aSt + ", resuming...");
|
|
3852
|
+
this.context.resume().then(() => {
|
|
3853
|
+
console.debug("Capture start: audio context resumed, starting...");
|
|
3854
|
+
this._start();
|
|
3855
|
+
});
|
|
3856
|
+
}
|
|
3706
3857
|
}
|
|
3707
3858
|
}
|
|
3708
3859
|
stop() {
|
|
3709
3860
|
if (this.disconnectStreams && this.bufferingNode) {
|
|
3710
3861
|
this.mediaStream.disconnect(this.bufferingNode);
|
|
3711
|
-
|
|
3862
|
+
if (this.context) {
|
|
3863
|
+
this.bufferingNode.disconnect(this.context.destination);
|
|
3864
|
+
}
|
|
3712
3865
|
}
|
|
3713
3866
|
try {
|
|
3714
3867
|
if (this.audioOutStream) {
|
|
@@ -3831,7 +3984,7 @@ class AudioCapture {
|
|
|
3831
3984
|
}
|
|
3832
3985
|
audioBuffer() {
|
|
3833
3986
|
let ab = null;
|
|
3834
|
-
if (this.data) {
|
|
3987
|
+
if (this.context && this.data) {
|
|
3835
3988
|
let frameLen = 0;
|
|
3836
3989
|
let ch0Data = this.data[0];
|
|
3837
3990
|
for (let ch0Chk of ch0Data) {
|
|
@@ -4533,7 +4686,7 @@ class Uploader {
|
|
|
4533
4686
|
si += v.size;
|
|
4534
4687
|
}
|
|
4535
4688
|
else if (typeof v === 'string') {
|
|
4536
|
-
// encode to
|
|
4689
|
+
// encode to UTF-8 to get upload size
|
|
4537
4690
|
si += this.te.encode().length;
|
|
4538
4691
|
}
|
|
4539
4692
|
});
|
|
@@ -4571,35 +4724,38 @@ class Uploader {
|
|
|
4571
4724
|
// pipe(timeout()) is not the same as xhr.timeout
|
|
4572
4725
|
let uploadedUpload = null;
|
|
4573
4726
|
//console.debug("Post upload: "+ul)
|
|
4574
|
-
this.http.post(ul.url, ul.data, { withCredentials: this.withCredentials }).pipe(timeout(timeoVal)).subscribe(
|
|
4575
|
-
|
|
4576
|
-
|
|
4577
|
-
|
|
4578
|
-
|
|
4579
|
-
|
|
4580
|
-
|
|
4581
|
-
|
|
4582
|
-
|
|
4583
|
-
|
|
4584
|
-
|
|
4585
|
-
|
|
4586
|
-
|
|
4587
|
-
|
|
4588
|
-
|
|
4589
|
-
|
|
4590
|
-
|
|
4591
|
-
|
|
4592
|
-
|
|
4593
|
-
|
|
4594
|
-
|
|
4727
|
+
this.http.post(ul.url, ul.data, { withCredentials: this.withCredentials }).pipe(timeout(timeoVal)).subscribe({
|
|
4728
|
+
next: (data) => {
|
|
4729
|
+
uploadedUpload = ul;
|
|
4730
|
+
//console.debug('Next method called for upload: '+uploadedUpload)
|
|
4731
|
+
},
|
|
4732
|
+
error: (err) => {
|
|
4733
|
+
if (err.error instanceof Error) {
|
|
4734
|
+
// A client-side or network error occurred. Handle it accordingly.
|
|
4735
|
+
console.error('Upload error occurred:', err.error.message);
|
|
4736
|
+
}
|
|
4737
|
+
else {
|
|
4738
|
+
// The backend returned an unsuccessful response code.
|
|
4739
|
+
// The response body may contain clues as to what went wrong,
|
|
4740
|
+
console.error(`Upload error: Server returned code ${err.status}`);
|
|
4741
|
+
}
|
|
4742
|
+
this.processError(ul);
|
|
4743
|
+
}, complete: () => {
|
|
4744
|
+
//console.debug('Upload complete method called')
|
|
4745
|
+
if (uploadedUpload) {
|
|
4746
|
+
if (this.DEBUG_DELAY > 0) {
|
|
4747
|
+
window.setTimeout(() => {
|
|
4748
|
+
this.uploadDone(ul);
|
|
4749
|
+
}, this.DEBUG_DELAY);
|
|
4750
|
+
}
|
|
4751
|
+
else {
|
|
4752
|
+
this.uploadDone(uploadedUpload);
|
|
4753
|
+
}
|
|
4595
4754
|
}
|
|
4596
4755
|
else {
|
|
4597
|
-
|
|
4756
|
+
console.error('Upload post complete, but upload not set in next method!');
|
|
4598
4757
|
}
|
|
4599
4758
|
}
|
|
4600
|
-
else {
|
|
4601
|
-
console.error('Upload post complete, but upload not set in next method!');
|
|
4602
|
-
}
|
|
4603
4759
|
});
|
|
4604
4760
|
}
|
|
4605
4761
|
processError(ul) {
|
|
@@ -4613,7 +4769,7 @@ class Uploader {
|
|
|
4613
4769
|
// set retry timer
|
|
4614
4770
|
this.retryTimerId = window.setTimeout(() => {
|
|
4615
4771
|
this.retryTimerRunning = false;
|
|
4616
|
-
//console.debug("Upload retry timer
|
|
4772
|
+
//console.debug("Upload retry timer expired. Continue processing...")
|
|
4617
4773
|
this.process();
|
|
4618
4774
|
}, this.RETRY_DELAY);
|
|
4619
4775
|
this.retryTimerRunning = true;
|
|
@@ -4707,12 +4863,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
4707
4863
|
* Created by klausj on 17.06.2017.
|
|
4708
4864
|
*/
|
|
4709
4865
|
class ProjectService {
|
|
4710
|
-
constructor(http,
|
|
4866
|
+
constructor(http, platformLocation, config) {
|
|
4711
4867
|
this.http = http;
|
|
4712
|
-
this.
|
|
4868
|
+
this.platformLocation = platformLocation;
|
|
4713
4869
|
this.config = config;
|
|
4714
4870
|
this.withCredentials = false;
|
|
4715
|
-
console.log("Base Href: " +
|
|
4871
|
+
console.log("Base Href: " + platformLocation.getBaseHrefFromDOM());
|
|
4716
4872
|
let apiEndPoint = '';
|
|
4717
4873
|
if (config && config.apiEndPoint) {
|
|
4718
4874
|
apiEndPoint = config.apiEndPoint;
|
|
@@ -4797,14 +4953,17 @@ class SessionService {
|
|
|
4797
4953
|
let wrapObs = new Observable(subscriber => {
|
|
4798
4954
|
this._uploadCount++;
|
|
4799
4955
|
let obs = this.http.patch(sesssUrl, body, { withCredentials: this.withCredentials });
|
|
4800
|
-
obs.subscribe(
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
4805
|
-
|
|
4806
|
-
|
|
4807
|
-
|
|
4956
|
+
obs.subscribe({
|
|
4957
|
+
next: (value) => {
|
|
4958
|
+
subscriber.next(value);
|
|
4959
|
+
},
|
|
4960
|
+
error: error => {
|
|
4961
|
+
this._uploadCount--;
|
|
4962
|
+
subscriber.error(error);
|
|
4963
|
+
}, complete: () => {
|
|
4964
|
+
this._uploadCount--;
|
|
4965
|
+
subscriber.complete();
|
|
4966
|
+
}
|
|
4808
4967
|
});
|
|
4809
4968
|
});
|
|
4810
4969
|
return wrapObs;
|
|
@@ -7423,7 +7582,7 @@ AudioClipUIContainer.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", v
|
|
|
7423
7582
|
<audio-signal [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-signal>
|
|
7424
7583
|
<audio-sonagram [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-sonagram>
|
|
7425
7584
|
</div>
|
|
7426
|
-
`, 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;
|
|
7585
|
+
`, 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" }] });
|
|
7427
7586
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioClipUIContainer, decorators: [{
|
|
7428
7587
|
type: Component,
|
|
7429
7588
|
args: [{ selector: 'app-audio', template: `
|
|
@@ -7433,7 +7592,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
7433
7592
|
<audio-signal [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-signal>
|
|
7434
7593
|
<audio-sonagram [pointerPosition]="pointer" [selecting]="selecting" [selection]="selection" (pointerPositionEventEmitter)="pointerPositionChanged($event)" (selectingEventEmitter)="selectingChanged($event)" (selectedEventEmitter)="selectionChanged($event)"></audio-sonagram>
|
|
7435
7594
|
</div>
|
|
7436
|
-
`, 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;
|
|
7595
|
+
`, 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"] }]
|
|
7437
7596
|
}], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { canvasRef: [{
|
|
7438
7597
|
type: ViewChild,
|
|
7439
7598
|
args: ['divider', { static: true }]
|
|
@@ -7747,8 +7906,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
7747
7906
|
}] } });
|
|
7748
7907
|
|
|
7749
7908
|
class AudioDisplay {
|
|
7750
|
-
constructor(
|
|
7751
|
-
this.route = route;
|
|
7909
|
+
constructor(ref, eRef) {
|
|
7752
7910
|
this.ref = ref;
|
|
7753
7911
|
this.eRef = eRef;
|
|
7754
7912
|
this._audioClip = null;
|
|
@@ -7811,7 +7969,7 @@ class AudioDisplay {
|
|
|
7811
7969
|
this.status = 'ERROR';
|
|
7812
7970
|
}
|
|
7813
7971
|
}
|
|
7814
|
-
AudioDisplay.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioDisplay, deps: [{ token:
|
|
7972
|
+
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 });
|
|
7815
7973
|
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: `
|
|
7816
7974
|
|
|
7817
7975
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
@@ -7842,7 +8000,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
7842
8000
|
[zoomSelectedAction]="zoomSelectedAction"
|
|
7843
8001
|
[zoomFitToPanelAction]="zoomFitToPanelAction"></audio-display-control>
|
|
7844
8002
|
`, 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"] }]
|
|
7845
|
-
}], ctorParameters: function () { return [{ type:
|
|
8003
|
+
}], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { playStartAction: [{
|
|
7846
8004
|
type: Input
|
|
7847
8005
|
}], playStopAction: [{
|
|
7848
8006
|
type: Input
|
|
@@ -7873,11 +8031,11 @@ class ResponsiveComponent {
|
|
|
7873
8031
|
});
|
|
7874
8032
|
}
|
|
7875
8033
|
}
|
|
7876
|
-
ResponsiveComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ResponsiveComponent, deps: [{ token: i1$
|
|
8034
|
+
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 });
|
|
7877
8035
|
ResponsiveComponent.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "14.2.12", type: ResponsiveComponent, ngImport: i0 });
|
|
7878
8036
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ResponsiveComponent, decorators: [{
|
|
7879
8037
|
type: Directive
|
|
7880
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
8038
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; } });
|
|
7881
8039
|
|
|
7882
8040
|
class ScrollIntoViewDirective {
|
|
7883
8041
|
constructor(elRef) {
|
|
@@ -8557,7 +8715,7 @@ class Prompting extends ResponsiveComponent {
|
|
|
8557
8715
|
this.onPrevItem.emit();
|
|
8558
8716
|
}
|
|
8559
8717
|
}
|
|
8560
|
-
Prompting.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: Prompting, deps: [{ token: i1$
|
|
8718
|
+
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 });
|
|
8561
8719
|
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: `
|
|
8562
8720
|
|
|
8563
8721
|
<app-simpletrafficlight [status]="startStopSignalState"></app-simpletrafficlight>
|
|
@@ -8606,7 +8764,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
8606
8764
|
|
|
8607
8765
|
|
|
8608
8766
|
`, 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"] }]
|
|
8609
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
8767
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; }, propDecorators: { simpleTrafficLight: [{
|
|
8610
8768
|
type: ViewChild,
|
|
8611
8769
|
args: [SimpleTrafficLight, { static: true }]
|
|
8612
8770
|
}], audioDisplay: [{
|
|
@@ -8657,7 +8815,7 @@ class SessionFinishedDialog {
|
|
|
8657
8815
|
this.dialogRef.close();
|
|
8658
8816
|
}
|
|
8659
8817
|
}
|
|
8660
|
-
SessionFinishedDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionFinishedDialog, deps: [{ token: i1$
|
|
8818
|
+
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 });
|
|
8661
8819
|
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>
|
|
8662
8820
|
<div mat-dialog-content>
|
|
8663
8821
|
|
|
@@ -8667,7 +8825,7 @@ SessionFinishedDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0",
|
|
|
8667
8825
|
<div mat-dialog-actions>
|
|
8668
8826
|
<button mat-button (click)="closeDialog()">OK</button>
|
|
8669
8827
|
</div>
|
|
8670
|
-
`, 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$
|
|
8828
|
+
`, 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"] }] });
|
|
8671
8829
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionFinishedDialog, decorators: [{
|
|
8672
8830
|
type: Component,
|
|
8673
8831
|
args: [{
|
|
@@ -8684,7 +8842,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
8684
8842
|
`
|
|
8685
8843
|
}]
|
|
8686
8844
|
}], ctorParameters: function () {
|
|
8687
|
-
return [{ type: i1$
|
|
8845
|
+
return [{ type: i1$3.MatDialogRef }, { type: undefined, decorators: [{
|
|
8688
8846
|
type: Inject,
|
|
8689
8847
|
args: [MAT_DIALOG_DATA]
|
|
8690
8848
|
}] }];
|
|
@@ -8699,7 +8857,7 @@ class MessageDialog {
|
|
|
8699
8857
|
this.dialogRef.close();
|
|
8700
8858
|
}
|
|
8701
8859
|
}
|
|
8702
|
-
MessageDialog.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MessageDialog, deps: [{ token: i1$
|
|
8860
|
+
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 });
|
|
8703
8861
|
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>
|
|
8704
8862
|
<mat-icon *ngIf="data.type==='warning'" [style.color]="'yellow'">warning</mat-icon>{{data.title}}</h1>
|
|
8705
8863
|
<div mat-dialog-content>
|
|
@@ -8711,7 +8869,7 @@ MessageDialog.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version:
|
|
|
8711
8869
|
<div mat-dialog-actions>
|
|
8712
8870
|
<button mat-button (click)="closeDialog()">OK</button>
|
|
8713
8871
|
</div>
|
|
8714
|
-
`, 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$
|
|
8872
|
+
`, 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"] }] });
|
|
8715
8873
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: MessageDialog, decorators: [{
|
|
8716
8874
|
type: Component,
|
|
8717
8875
|
args: [{
|
|
@@ -8730,7 +8888,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
8730
8888
|
`
|
|
8731
8889
|
}]
|
|
8732
8890
|
}], ctorParameters: function () {
|
|
8733
|
-
return [{ type: i1$
|
|
8891
|
+
return [{ type: i1$3.MatDialogRef }, { type: undefined, decorators: [{
|
|
8734
8892
|
type: Inject,
|
|
8735
8893
|
args: [MAT_DIALOG_DATA]
|
|
8736
8894
|
}] }];
|
|
@@ -9022,7 +9180,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9022
9180
|
withCredentials: this.withCredentials
|
|
9023
9181
|
});
|
|
9024
9182
|
}
|
|
9025
|
-
chunkAudioRequest(
|
|
9183
|
+
chunkAudioRequest(baseAudioUrl, startFrame = 0, frameLength) {
|
|
9026
9184
|
let ausps = new URLSearchParams();
|
|
9027
9185
|
ausps.set('startFrame', startFrame.toString());
|
|
9028
9186
|
ausps.set('frameLength', frameLength.toString());
|
|
@@ -9033,67 +9191,69 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9033
9191
|
ausps.set('requestUUID', UUID.generate());
|
|
9034
9192
|
}
|
|
9035
9193
|
let obs = new Observable(observer => {
|
|
9036
|
-
this.audioRequestByURL(baseAudioUrl, ausps).subscribe(
|
|
9037
|
-
|
|
9038
|
-
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
|
|
9042
|
-
|
|
9043
|
-
|
|
9044
|
-
|
|
9045
|
-
|
|
9046
|
-
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9194
|
+
this.audioRequestByURL(baseAudioUrl, ausps).subscribe({
|
|
9195
|
+
next: resp => {
|
|
9196
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9197
|
+
if (resp.body) {
|
|
9198
|
+
//console.debug("chunkAudioRequest: observer.closed: "+observer.closed);
|
|
9199
|
+
//console.debug("Audio file bytes: "+resp.body.byteLength);
|
|
9200
|
+
// Check original audio format
|
|
9201
|
+
let wr = new WavReader(resp.body);
|
|
9202
|
+
const pcmFmt = wr.readFormat();
|
|
9203
|
+
const orgFl = wr.frameLength();
|
|
9204
|
+
// if(pcmFmt){
|
|
9205
|
+
// console.debug("Original WAVE format of download chunk: "+pcmFmt);
|
|
9206
|
+
// }else{
|
|
9207
|
+
// console.error("Could not read WAVE format of original download chunk!");
|
|
9208
|
+
// }
|
|
9209
|
+
// if(orgFl){
|
|
9210
|
+
// console.debug("Original frame length of download chunk: "+orgFl);
|
|
9211
|
+
// }else{
|
|
9212
|
+
// console.error("Could not read WAVE format of original download chunk!");
|
|
9213
|
+
// }
|
|
9214
|
+
if (pcmFmt && orgFl) {
|
|
9215
|
+
AudioContextProvider.decodeAudioData(resp.body).then((ab) => {
|
|
9216
|
+
//console.debug("Decoded audio chunk frames: "+ab.length);
|
|
9217
|
+
let chDl = new ChunkDownload(pcmFmt, orgFl, ab);
|
|
9218
|
+
observer.next(chDl);
|
|
9219
|
+
observer.complete();
|
|
9220
|
+
}).catch(error => {
|
|
9221
|
+
//if(error instanceof HttpErrorResponse) {
|
|
9222
|
+
// if (error.status == 404) {
|
|
9223
|
+
// // Interpret not as an error, the file ist not recorded yet
|
|
9224
|
+
// observer.next(null);
|
|
9225
|
+
// observer.complete()
|
|
9226
|
+
// } else {
|
|
9227
|
+
// // all other states are errors
|
|
9228
|
+
console.error("Recordings service chunkAudioRequest error decoding audio data: " + error.name + ": " + error.message);
|
|
9229
|
+
observer.error(error);
|
|
9230
|
+
// }
|
|
9231
|
+
// }
|
|
9232
|
+
});
|
|
9233
|
+
}
|
|
9234
|
+
else {
|
|
9235
|
+
const errMsg = 'Could not parse audio header for format and/or frame length of download.';
|
|
9236
|
+
console.error(errMsg);
|
|
9237
|
+
observer.error(errMsg);
|
|
9238
|
+
}
|
|
9074
9239
|
}
|
|
9075
9240
|
else {
|
|
9076
|
-
const errMsg = '
|
|
9241
|
+
const errMsg = 'Fetching audio file: response has no body';
|
|
9077
9242
|
console.error(errMsg);
|
|
9078
9243
|
observer.error(errMsg);
|
|
9079
9244
|
}
|
|
9245
|
+
}, error: (error) => {
|
|
9246
|
+
// all other states are errors
|
|
9247
|
+
//const errMsg='Fetching audio file HTTP error: '+error;
|
|
9248
|
+
//console.error(errMsg);
|
|
9249
|
+
observer.error(error);
|
|
9250
|
+
//observer.complete();
|
|
9080
9251
|
}
|
|
9081
|
-
else {
|
|
9082
|
-
const errMsg = 'Fetching audio file: response has no body';
|
|
9083
|
-
console.error(errMsg);
|
|
9084
|
-
observer.error(errMsg);
|
|
9085
|
-
}
|
|
9086
|
-
}, (error) => {
|
|
9087
|
-
// all other states are errors
|
|
9088
|
-
//const errMsg='Fetching audio file HTTP error: '+error;
|
|
9089
|
-
//console.error(errMsg);
|
|
9090
|
-
observer.error(error);
|
|
9091
|
-
//observer.complete();
|
|
9092
9252
|
});
|
|
9093
9253
|
});
|
|
9094
9254
|
return obs;
|
|
9095
9255
|
}
|
|
9096
|
-
chunkAudioRequestToNetAudioBuffer(
|
|
9256
|
+
chunkAudioRequestToNetAudioBuffer(baseAudioUrl, startFrame = 0, orgSampleRate, seconds, frames) {
|
|
9097
9257
|
//let audioUrl=baseAudioUrl+'?startFrame='+startFrame+'&frameLength='+frameLength;
|
|
9098
9258
|
//let audioUrl=new URL(baseAudioUrl);
|
|
9099
9259
|
// if(orgSampleRate!=null && frameLength%orgSampleRate>0){
|
|
@@ -9117,7 +9277,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9117
9277
|
if (resp.body) {
|
|
9118
9278
|
//console.debug("chunkAudioRequestTonetAb: subscriber.closed: "+subscriber.closed);
|
|
9119
9279
|
//console.debug("chunkAudioRequestTonetAb: Audio file bytes: "+resp.body.byteLength);
|
|
9120
|
-
|
|
9280
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9121
9281
|
//console.debug("chunkAudioRequestTonetAb: Decoded audio chunk frames for netAb: "+ab.length);
|
|
9122
9282
|
//console.debug("chunkAudioRequestTonetAb: Create netAb ab from chunk ab...");
|
|
9123
9283
|
if (frames === null) {
|
|
@@ -9131,7 +9291,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9131
9291
|
//console.debug("Platform sr: "+ab.sampleRate+", file sr: "+orgSampleRate+", decoded/org frame length: "+fl+"/"+frames+", ab.length: "+ab.length);
|
|
9132
9292
|
}
|
|
9133
9293
|
}
|
|
9134
|
-
let nab = NetAudioBuffer.fromChunkAudioBuffer(
|
|
9294
|
+
let nab = NetAudioBuffer.fromChunkAudioBuffer(this, baseAudioUrl, ab, fl, frameLength);
|
|
9135
9295
|
//let rp=new ReadyProvider();
|
|
9136
9296
|
//nab.readyProvider=rp;
|
|
9137
9297
|
//rp.ready();
|
|
@@ -9143,7 +9303,7 @@ let BasicRecordingService = class BasicRecordingService {
|
|
|
9143
9303
|
subscriber.next(nab);
|
|
9144
9304
|
subscriber.complete();
|
|
9145
9305
|
}
|
|
9146
|
-
}
|
|
9306
|
+
}).catch(error => {
|
|
9147
9307
|
console.error('chunkAudioRequestToNetAb: error: ' + error);
|
|
9148
9308
|
//if(error instanceof HttpErrorResponse) {
|
|
9149
9309
|
subscriber.error(error);
|
|
@@ -9251,7 +9411,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9251
9411
|
withCredentials: this.withCredentials
|
|
9252
9412
|
});
|
|
9253
9413
|
}
|
|
9254
|
-
chunkAudioRequestToIndDb(
|
|
9414
|
+
chunkAudioRequestToIndDb(persistentAudioStorageTarget, inddbAudioBuffer, baseAudioUrl, startFrame = 0, orgSampleRate, seconds) {
|
|
9255
9415
|
//let audioUrl=baseAudioUrl+'?startFrame='+startFrame+'&frameLength='+frameLength;
|
|
9256
9416
|
//let audioUrl=new URL(baseAudioUrl);
|
|
9257
9417
|
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.
|
|
@@ -9270,7 +9430,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9270
9430
|
if (resp.body) {
|
|
9271
9431
|
//console.debug("chunkAudioRequestToIndDb: subscriber.closed: "+subscriber.closed);
|
|
9272
9432
|
//console.debug("chunkAudioRequestToIndDb: Audio file bytes: "+resp.body.byteLength);
|
|
9273
|
-
|
|
9433
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9274
9434
|
//console.debug("chunkAudioRequestToIndDb: Decoded audio chunk frames for inddb: "+ab.length);
|
|
9275
9435
|
if (!inddbAudioBuffer) {
|
|
9276
9436
|
//console.debug("chunkAudioRequestToIndDb: Create inddb ab from chunk ab...");
|
|
@@ -9314,7 +9474,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9314
9474
|
}
|
|
9315
9475
|
});
|
|
9316
9476
|
}
|
|
9317
|
-
}
|
|
9477
|
+
}).catch(error => {
|
|
9318
9478
|
console.error('chunkAudioRequestToIndDb: error: ' + error);
|
|
9319
9479
|
//if(error instanceof HttpErrorResponse) {
|
|
9320
9480
|
subscriber.error(error);
|
|
@@ -9322,8 +9482,9 @@ class RecordingService extends BasicRecordingService {
|
|
|
9322
9482
|
});
|
|
9323
9483
|
}
|
|
9324
9484
|
else {
|
|
9325
|
-
|
|
9326
|
-
|
|
9485
|
+
const errMsg = 'chunkAudioRequestToIndDb: Fetching audio file: response has no body';
|
|
9486
|
+
console.error(errMsg);
|
|
9487
|
+
subscriber.error(new Error(errMsg));
|
|
9327
9488
|
}
|
|
9328
9489
|
},
|
|
9329
9490
|
error: (error) => {
|
|
@@ -9335,13 +9496,13 @@ class RecordingService extends BasicRecordingService {
|
|
|
9335
9496
|
});
|
|
9336
9497
|
return obs;
|
|
9337
9498
|
}
|
|
9338
|
-
chunkedAudioRequestToArrayBuffer(
|
|
9499
|
+
chunkedAudioRequestToArrayBuffer(baseAudioUrl, orgSampleRate, seconds) {
|
|
9339
9500
|
let obs = new Observable(subscriber => {
|
|
9340
9501
|
let arrayAudioBuffer = null;
|
|
9341
9502
|
let startFrame = 0;
|
|
9342
9503
|
let frameLength = orgSampleRate * Math.round(seconds); // Important: multiple of original sample rate to prevent numeric rounding errors on resampling.
|
|
9343
9504
|
//console.debug("Chunk audio request startFrame 0");
|
|
9344
|
-
let subscr = this.chunkAudioRequest(
|
|
9505
|
+
let subscr = this.chunkAudioRequest(baseAudioUrl, startFrame, frameLength).pipe(expand(value => {
|
|
9345
9506
|
if (subscriber.closed) {
|
|
9346
9507
|
subscr.unsubscribe();
|
|
9347
9508
|
}
|
|
@@ -9360,7 +9521,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9360
9521
|
startFrame += frameLength;
|
|
9361
9522
|
//console.debug("Next start frame: "+startFrame);
|
|
9362
9523
|
//console.debug("chunkedAudioRequest: expand() subscriber.closed: "+subscriber.closed);
|
|
9363
|
-
return this.chunkAudioRequest(
|
|
9524
|
+
return this.chunkAudioRequest(baseAudioUrl, startFrame, frameLength);
|
|
9364
9525
|
}
|
|
9365
9526
|
}
|
|
9366
9527
|
else {
|
|
@@ -9430,14 +9591,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9430
9591
|
});
|
|
9431
9592
|
return obs;
|
|
9432
9593
|
}
|
|
9433
|
-
chunkedInddbAudioRequest(
|
|
9594
|
+
chunkedInddbAudioRequest(persistentAudioStorageTarget, baseAudioUrl, orgSampleRate, seconds) {
|
|
9434
9595
|
let obs = new Observable(subscriber => {
|
|
9435
9596
|
let inddbAudioBuffer = null;
|
|
9436
9597
|
let startFrame = 0;
|
|
9437
9598
|
//let frameLength = DEFAULT_CHUNKED_DOWNLOAD_FRAMELENGTH;
|
|
9438
9599
|
let frameLength = orgSampleRate * Math.round(seconds);
|
|
9439
9600
|
//console.debug("chunkedInddbAudioRequest: Chunk audio request for inddb. startFrame: "+startFrame);
|
|
9440
|
-
let subscr = this.chunkAudioRequestToIndDb(
|
|
9601
|
+
let subscr = this.chunkAudioRequestToIndDb(persistentAudioStorageTarget, null, baseAudioUrl, startFrame, orgSampleRate, seconds).pipe(expand(iab => {
|
|
9441
9602
|
// console.debug("chunkedInddbAudioRequest (pipe/expand): Got inddb ab: "+iab);
|
|
9442
9603
|
if (subscriber.closed) {
|
|
9443
9604
|
subscr.unsubscribe();
|
|
@@ -9458,7 +9619,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9458
9619
|
startFrame += frameLength;
|
|
9459
9620
|
//console.debug("Next start frame: "+startFrame);
|
|
9460
9621
|
//console.debug("chunkedInddbAudioRequest: expand() subscriber.closed: "+subscriber.closed);
|
|
9461
|
-
return this.chunkAudioRequestToIndDb(
|
|
9622
|
+
return this.chunkAudioRequestToIndDb(persistentAudioStorageTarget, inddbAudioBuffer, baseAudioUrl, startFrame, orgSampleRate, seconds);
|
|
9462
9623
|
}
|
|
9463
9624
|
// } else {
|
|
9464
9625
|
// return EMPTY;
|
|
@@ -9650,7 +9811,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9650
9811
|
// //let recUrl=new URL(recUrlStr);
|
|
9651
9812
|
// return this.chunkedInddbAudioRequest(aCtx,recUrlStr);
|
|
9652
9813
|
// }
|
|
9653
|
-
fetchRecordingFileAudioBuffer(
|
|
9814
|
+
fetchRecordingFileAudioBuffer(projectName, recordingFile) {
|
|
9654
9815
|
let wobs = new Observable(observer => {
|
|
9655
9816
|
let recFileId = recordingFile.recordingFileId;
|
|
9656
9817
|
if (!recFileId) {
|
|
@@ -9658,36 +9819,38 @@ class RecordingService extends BasicRecordingService {
|
|
|
9658
9819
|
}
|
|
9659
9820
|
if (recordingFile.session && recFileId) {
|
|
9660
9821
|
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
9661
|
-
obs.subscribe(
|
|
9662
|
-
|
|
9663
|
-
|
|
9664
|
-
|
|
9665
|
-
|
|
9666
|
-
|
|
9667
|
-
|
|
9668
|
-
|
|
9669
|
-
|
|
9670
|
-
|
|
9671
|
-
|
|
9672
|
-
|
|
9673
|
-
|
|
9674
|
-
|
|
9675
|
-
|
|
9676
|
-
|
|
9677
|
-
if (err
|
|
9678
|
-
|
|
9679
|
-
|
|
9680
|
-
|
|
9822
|
+
obs.subscribe({
|
|
9823
|
+
next: resp => {
|
|
9824
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9825
|
+
if (resp.body) {
|
|
9826
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9827
|
+
observer.next(ab);
|
|
9828
|
+
observer.complete();
|
|
9829
|
+
}).catch(error => {
|
|
9830
|
+
observer.error(error);
|
|
9831
|
+
observer.complete();
|
|
9832
|
+
});
|
|
9833
|
+
}
|
|
9834
|
+
else {
|
|
9835
|
+
observer.error('Fetching audio file: response has no body');
|
|
9836
|
+
}
|
|
9837
|
+
}, error: (err) => {
|
|
9838
|
+
if (err instanceof HttpErrorResponse) {
|
|
9839
|
+
if (err.status == 404) {
|
|
9840
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9841
|
+
observer.next(null);
|
|
9842
|
+
observer.complete();
|
|
9843
|
+
}
|
|
9844
|
+
else {
|
|
9845
|
+
// all other states are errors
|
|
9846
|
+
observer.error(err);
|
|
9847
|
+
observer.complete();
|
|
9848
|
+
}
|
|
9681
9849
|
}
|
|
9682
9850
|
else {
|
|
9683
|
-
// all other states are errors
|
|
9684
9851
|
observer.error(err);
|
|
9685
|
-
observer.complete();
|
|
9686
9852
|
}
|
|
9687
9853
|
}
|
|
9688
|
-
else {
|
|
9689
|
-
observer.error(err);
|
|
9690
|
-
}
|
|
9691
9854
|
});
|
|
9692
9855
|
}
|
|
9693
9856
|
else {
|
|
@@ -9704,49 +9867,50 @@ class RecordingService extends BasicRecordingService {
|
|
|
9704
9867
|
}
|
|
9705
9868
|
if (recordingFile.session && recFileId) {
|
|
9706
9869
|
let obs = this.fetchAudiofile(projectName, recordingFile.session, recFileId);
|
|
9707
|
-
obs.subscribe(resp => {
|
|
9708
|
-
|
|
9709
|
-
|
|
9710
|
-
|
|
9711
|
-
|
|
9712
|
-
|
|
9713
|
-
|
|
9714
|
-
|
|
9715
|
-
|
|
9716
|
-
|
|
9870
|
+
obs.subscribe({ next: resp => {
|
|
9871
|
+
//console.log("Fetched audio file. HTTP response status: "+resp.status+", type: "+resp.type+", byte length: "+ resp.body.byteLength);
|
|
9872
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9873
|
+
if (resp.body) {
|
|
9874
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9875
|
+
let abs = new AudioBufferSource(ab);
|
|
9876
|
+
let adh = new AudioDataHolder(abs);
|
|
9877
|
+
RecordingFileUtils.setAudioData(recordingFile, adh);
|
|
9878
|
+
if (this.debugDelay > 0) {
|
|
9879
|
+
window.setTimeout(() => {
|
|
9880
|
+
observer.next(recordingFile);
|
|
9881
|
+
observer.complete();
|
|
9882
|
+
}, this.debugDelay);
|
|
9883
|
+
}
|
|
9884
|
+
else {
|
|
9717
9885
|
observer.next(recordingFile);
|
|
9718
9886
|
observer.complete();
|
|
9719
|
-
}
|
|
9887
|
+
}
|
|
9888
|
+
}).catch(error => {
|
|
9889
|
+
observer.error(error);
|
|
9890
|
+
observer.complete();
|
|
9891
|
+
});
|
|
9892
|
+
}
|
|
9893
|
+
else {
|
|
9894
|
+
observer.error('Fetching audio file: response has no body');
|
|
9895
|
+
}
|
|
9896
|
+
},
|
|
9897
|
+
error: (err) => {
|
|
9898
|
+
if (err instanceof HttpErrorResponse) {
|
|
9899
|
+
if (err.status == 404) {
|
|
9900
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
9901
|
+
observer.next(null);
|
|
9902
|
+
observer.complete();
|
|
9720
9903
|
}
|
|
9721
9904
|
else {
|
|
9722
|
-
|
|
9905
|
+
// all other states are errors
|
|
9906
|
+
observer.error(err);
|
|
9723
9907
|
observer.complete();
|
|
9724
9908
|
}
|
|
9725
|
-
}, error => {
|
|
9726
|
-
observer.error(error);
|
|
9727
|
-
observer.complete();
|
|
9728
|
-
});
|
|
9729
|
-
}
|
|
9730
|
-
else {
|
|
9731
|
-
observer.error('Fetching audio file: response has no body');
|
|
9732
|
-
}
|
|
9733
|
-
}, (err) => {
|
|
9734
|
-
if (err instanceof HttpErrorResponse) {
|
|
9735
|
-
if (err.status == 404) {
|
|
9736
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
9737
|
-
observer.next(null);
|
|
9738
|
-
observer.complete();
|
|
9739
9909
|
}
|
|
9740
9910
|
else {
|
|
9741
|
-
// all other states are errors
|
|
9742
9911
|
observer.error(err);
|
|
9743
|
-
observer.complete();
|
|
9744
9912
|
}
|
|
9745
|
-
}
|
|
9746
|
-
else {
|
|
9747
|
-
observer.error(err);
|
|
9748
|
-
}
|
|
9749
|
-
});
|
|
9913
|
+
} });
|
|
9750
9914
|
}
|
|
9751
9915
|
else {
|
|
9752
9916
|
observer.error();
|
|
@@ -9754,7 +9918,7 @@ class RecordingService extends BasicRecordingService {
|
|
|
9754
9918
|
});
|
|
9755
9919
|
return wobs;
|
|
9756
9920
|
}
|
|
9757
|
-
fetchSprRecordingFileAudioBuffer(
|
|
9921
|
+
fetchSprRecordingFileAudioBuffer(projectName, recordingFile) {
|
|
9758
9922
|
let wobs = new Observable(observer => {
|
|
9759
9923
|
if (recordingFile.session) {
|
|
9760
9924
|
let obs = this.fetchSprAudiofile(projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
@@ -9762,11 +9926,11 @@ class RecordingService extends BasicRecordingService {
|
|
|
9762
9926
|
next: resp => {
|
|
9763
9927
|
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
9764
9928
|
if (resp.body) {
|
|
9765
|
-
|
|
9929
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
9766
9930
|
//RecordingFileUtils.setAudioData(recordingFile,new AudioDataHolder(ab,null));
|
|
9767
9931
|
observer.next(ab);
|
|
9768
9932
|
observer.complete();
|
|
9769
|
-
}
|
|
9933
|
+
}).catch(error => {
|
|
9770
9934
|
observer.error(error);
|
|
9771
9935
|
observer.complete();
|
|
9772
9936
|
});
|
|
@@ -9794,14 +9958,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9794
9958
|
});
|
|
9795
9959
|
return wobs;
|
|
9796
9960
|
}
|
|
9797
|
-
fetchSprRecordingFileArrayAudioBuffer(
|
|
9961
|
+
fetchSprRecordingFileArrayAudioBuffer(projectName, recordingFile) {
|
|
9798
9962
|
let wobs = new Observable(observer => {
|
|
9799
9963
|
if (recordingFile.session) {
|
|
9800
9964
|
let baseUrl = this.sprAudioFileUrl(projectName, recordingFile);
|
|
9801
9965
|
if (baseUrl) {
|
|
9802
9966
|
if (recordingFile.samplerate) {
|
|
9803
9967
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9804
|
-
let obs = this.chunkedAudioRequestToArrayBuffer(
|
|
9968
|
+
let obs = this.chunkedAudioRequestToArrayBuffer(baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9805
9969
|
//let obs = this.fetchSprAudiofileArrayBuffer(aCtx,projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
9806
9970
|
let subscr = obs.subscribe({
|
|
9807
9971
|
next: aab => {
|
|
@@ -9838,14 +10002,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9838
10002
|
});
|
|
9839
10003
|
return wobs;
|
|
9840
10004
|
}
|
|
9841
|
-
fetchRecordingFileArrayAudioBuffer(
|
|
10005
|
+
fetchRecordingFileArrayAudioBuffer(projectName, recordingFile) {
|
|
9842
10006
|
let wobs = new Observable(observer => {
|
|
9843
10007
|
if (recordingFile.session) {
|
|
9844
10008
|
let baseUrl = this.audioFileUrl(projectName, recordingFile);
|
|
9845
10009
|
if (baseUrl) {
|
|
9846
10010
|
if (recordingFile.samplerate) {
|
|
9847
10011
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9848
|
-
let obs = this.chunkedAudioRequestToArrayBuffer(
|
|
10012
|
+
let obs = this.chunkedAudioRequestToArrayBuffer(baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9849
10013
|
//let obs = this.fetchSprAudiofileArrayBuffer(aCtx,projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
9850
10014
|
let subscr = obs.subscribe({
|
|
9851
10015
|
next: aab => {
|
|
@@ -9882,14 +10046,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9882
10046
|
});
|
|
9883
10047
|
return wobs;
|
|
9884
10048
|
}
|
|
9885
|
-
fetchSprRecordingFileIndDbAudioBuffer(
|
|
10049
|
+
fetchSprRecordingFileIndDbAudioBuffer(persistentAudioStorageTarget, projectName, recordingFile) {
|
|
9886
10050
|
let wobs = new Observable(observer => {
|
|
9887
10051
|
if (recordingFile.session) {
|
|
9888
10052
|
let baseUrl = this.sprAudioFileUrl(projectName, recordingFile);
|
|
9889
10053
|
if (baseUrl) {
|
|
9890
10054
|
if (recordingFile.samplerate) {
|
|
9891
10055
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9892
|
-
let obs = this.chunkedInddbAudioRequest(
|
|
10056
|
+
let obs = this.chunkedInddbAudioRequest(persistentAudioStorageTarget, baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9893
10057
|
let subscr = obs.subscribe({
|
|
9894
10058
|
next: aab => {
|
|
9895
10059
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -9925,14 +10089,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9925
10089
|
});
|
|
9926
10090
|
return wobs;
|
|
9927
10091
|
}
|
|
9928
|
-
fetchRecordingFileIndDbAudioBuffer(
|
|
10092
|
+
fetchRecordingFileIndDbAudioBuffer(persistentAudioStorageTarget, projectName, recordingFile) {
|
|
9929
10093
|
let wobs = new Observable(observer => {
|
|
9930
10094
|
if (recordingFile.session) {
|
|
9931
10095
|
let baseUrl = this.audioFileUrl(projectName, recordingFile);
|
|
9932
10096
|
if (baseUrl) {
|
|
9933
10097
|
if (recordingFile.samplerate) {
|
|
9934
10098
|
let lengthInSeconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9935
|
-
let obs = this.chunkedInddbAudioRequest(
|
|
10099
|
+
let obs = this.chunkedInddbAudioRequest(persistentAudioStorageTarget, baseUrl, recordingFile.samplerate, lengthInSeconds);
|
|
9936
10100
|
let subscr = obs.subscribe({
|
|
9937
10101
|
next: aab => {
|
|
9938
10102
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -9968,14 +10132,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
9968
10132
|
});
|
|
9969
10133
|
return wobs;
|
|
9970
10134
|
}
|
|
9971
|
-
fetchSprRecordingFileNetAudioBuffer(
|
|
10135
|
+
fetchSprRecordingFileNetAudioBuffer(projectName, recordingFile) {
|
|
9972
10136
|
let wobs = new Observable(observer => {
|
|
9973
10137
|
if (recordingFile.session) {
|
|
9974
10138
|
let baseUrl = this.sprAudioFileUrl(projectName, recordingFile);
|
|
9975
10139
|
if (baseUrl) {
|
|
9976
10140
|
let seconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
9977
10141
|
if (recordingFile.samplerate) {
|
|
9978
|
-
let obs = this.chunkAudioRequestToNetAudioBuffer(
|
|
10142
|
+
let obs = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, recordingFile.samplerate, seconds, recordingFile.frames);
|
|
9979
10143
|
let subscr = obs.subscribe({
|
|
9980
10144
|
next: aab => {
|
|
9981
10145
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -10016,14 +10180,14 @@ class RecordingService extends BasicRecordingService {
|
|
|
10016
10180
|
});
|
|
10017
10181
|
return wobs;
|
|
10018
10182
|
}
|
|
10019
|
-
fetchRecordingFileNetAudioBuffer(
|
|
10183
|
+
fetchRecordingFileNetAudioBuffer(projectName, recordingFile) {
|
|
10020
10184
|
let wobs = new Observable(observer => {
|
|
10021
10185
|
if (recordingFile.session) {
|
|
10022
10186
|
let baseUrl = this.audioFileUrl(projectName, recordingFile);
|
|
10023
10187
|
if (baseUrl) {
|
|
10024
10188
|
let seconds = RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
10025
10189
|
if (recordingFile.samplerate) {
|
|
10026
|
-
let obs = this.chunkAudioRequestToNetAudioBuffer(
|
|
10190
|
+
let obs = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, recordingFile.samplerate, seconds, recordingFile.frames);
|
|
10027
10191
|
let subscr = obs.subscribe({
|
|
10028
10192
|
next: aab => {
|
|
10029
10193
|
//console.debug("fetchSprRecordingFileIndDbAudioBuffer: observer.closed: "+observer.closed);
|
|
@@ -10068,83 +10232,87 @@ class RecordingService extends BasicRecordingService {
|
|
|
10068
10232
|
let wobs = new Observable(observer => {
|
|
10069
10233
|
if (recordingFile.session) {
|
|
10070
10234
|
let obs = this.fetchSprAudiofile(projectName, recordingFile.session, recordingFile.itemCode, recordingFile.version);
|
|
10071
|
-
obs.subscribe(
|
|
10072
|
-
|
|
10073
|
-
|
|
10235
|
+
obs.subscribe({
|
|
10236
|
+
next: resp => {
|
|
10237
|
+
//console.log("Fetched audio file. HTTP response status: "+resp.status+", type: "+resp.type+", byte length: "+ resp.body.byteLength);
|
|
10238
|
+
// Do not use Promise version, which does not work with Safari 13 (13.0.5)
|
|
10239
|
+
if (resp.body) {
|
|
10240
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
10241
|
+
let abs = new AudioBufferSource(ab);
|
|
10242
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(abs));
|
|
10243
|
+
if (this.debugDelay > 0) {
|
|
10244
|
+
window.setTimeout(() => {
|
|
10245
|
+
observer.next(recordingFile);
|
|
10246
|
+
observer.complete();
|
|
10247
|
+
}, this.debugDelay);
|
|
10248
|
+
}
|
|
10249
|
+
else {
|
|
10250
|
+
observer.next(recordingFile);
|
|
10251
|
+
observer.complete();
|
|
10252
|
+
}
|
|
10253
|
+
}).catch(error => {
|
|
10254
|
+
observer.error(error);
|
|
10255
|
+
observer.complete();
|
|
10256
|
+
});
|
|
10257
|
+
}
|
|
10258
|
+
else {
|
|
10259
|
+
observer.error('Fetching audio file: response has no body');
|
|
10260
|
+
}
|
|
10261
|
+
},
|
|
10262
|
+
error: (err) => {
|
|
10263
|
+
if (err instanceof HttpErrorResponse && err.status == 404) {
|
|
10264
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
10265
|
+
observer.next(null);
|
|
10266
|
+
observer.complete();
|
|
10267
|
+
}
|
|
10268
|
+
else {
|
|
10269
|
+
// all other states are errors
|
|
10270
|
+
observer.error(err);
|
|
10271
|
+
}
|
|
10272
|
+
}
|
|
10273
|
+
});
|
|
10274
|
+
}
|
|
10275
|
+
else {
|
|
10276
|
+
observer.error();
|
|
10277
|
+
}
|
|
10278
|
+
});
|
|
10279
|
+
return wobs;
|
|
10280
|
+
}
|
|
10281
|
+
fetchRecordingFile(aCtx, projectName, sessId, itemcode, version) {
|
|
10282
|
+
let wobs = new Observable(observer => {
|
|
10283
|
+
let obs = this.fetchSprAudiofile(projectName, sessId, itemcode, version);
|
|
10284
|
+
obs.subscribe({ next: resp => {
|
|
10074
10285
|
if (resp.body) {
|
|
10075
|
-
|
|
10286
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
10076
10287
|
let abs = new AudioBufferSource(ab);
|
|
10077
|
-
|
|
10288
|
+
let adh = new AudioDataHolder(abs);
|
|
10289
|
+
let rf = new SprRecordingFile(sessId, itemcode, version, adh);
|
|
10078
10290
|
if (this.debugDelay > 0) {
|
|
10079
10291
|
window.setTimeout(() => {
|
|
10080
|
-
observer.next(
|
|
10292
|
+
observer.next(rf);
|
|
10081
10293
|
observer.complete();
|
|
10082
10294
|
}, this.debugDelay);
|
|
10083
10295
|
}
|
|
10084
10296
|
else {
|
|
10085
|
-
observer.next(
|
|
10297
|
+
observer.next(rf);
|
|
10086
10298
|
observer.complete();
|
|
10087
10299
|
}
|
|
10088
|
-
}
|
|
10089
|
-
observer.error(error);
|
|
10090
|
-
observer.complete();
|
|
10091
|
-
});
|
|
10300
|
+
}).catch((reason) => { observer.error(reason); });
|
|
10092
10301
|
}
|
|
10093
10302
|
else {
|
|
10094
|
-
observer.error(
|
|
10303
|
+
observer.error();
|
|
10095
10304
|
}
|
|
10096
|
-
},
|
|
10305
|
+
},
|
|
10306
|
+
error: (err) => {
|
|
10097
10307
|
if (err instanceof HttpErrorResponse && err.status == 404) {
|
|
10098
10308
|
// Interpret not as an error, the file ist not recorded yet
|
|
10099
10309
|
observer.next(null);
|
|
10100
10310
|
observer.complete();
|
|
10101
10311
|
}
|
|
10102
10312
|
else {
|
|
10103
|
-
// all other
|
|
10313
|
+
// all other errors are real errors
|
|
10104
10314
|
observer.error(err);
|
|
10105
10315
|
}
|
|
10106
|
-
});
|
|
10107
|
-
}
|
|
10108
|
-
else {
|
|
10109
|
-
observer.error();
|
|
10110
|
-
}
|
|
10111
|
-
});
|
|
10112
|
-
return wobs;
|
|
10113
|
-
}
|
|
10114
|
-
fetchRecordingFile(aCtx, projectName, sessId, itemcode, version) {
|
|
10115
|
-
let wobs = new Observable(observer => {
|
|
10116
|
-
let obs = this.fetchSprAudiofile(projectName, sessId, itemcode, version);
|
|
10117
|
-
obs.subscribe(resp => {
|
|
10118
|
-
// Do not use Promise version, which does not work with Safari 13
|
|
10119
|
-
if (resp.body) {
|
|
10120
|
-
aCtx.decodeAudioData(resp.body, ab => {
|
|
10121
|
-
let abs = new AudioBufferSource(ab);
|
|
10122
|
-
let adh = new AudioDataHolder(abs);
|
|
10123
|
-
let rf = new SprRecordingFile(sessId, itemcode, version, adh);
|
|
10124
|
-
if (this.debugDelay > 0) {
|
|
10125
|
-
window.setTimeout(() => {
|
|
10126
|
-
observer.next(rf);
|
|
10127
|
-
observer.complete();
|
|
10128
|
-
}, this.debugDelay);
|
|
10129
|
-
}
|
|
10130
|
-
else {
|
|
10131
|
-
observer.next(rf);
|
|
10132
|
-
observer.complete();
|
|
10133
|
-
}
|
|
10134
|
-
});
|
|
10135
|
-
}
|
|
10136
|
-
else {
|
|
10137
|
-
observer.error();
|
|
10138
|
-
}
|
|
10139
|
-
}, (err) => {
|
|
10140
|
-
if (err instanceof HttpErrorResponse && err.status == 404) {
|
|
10141
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
10142
|
-
observer.next(null);
|
|
10143
|
-
observer.complete();
|
|
10144
|
-
}
|
|
10145
|
-
else {
|
|
10146
|
-
// all other errors are real errors
|
|
10147
|
-
observer.error(err);
|
|
10148
10316
|
}
|
|
10149
10317
|
});
|
|
10150
10318
|
});
|
|
@@ -10166,23 +10334,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10166
10334
|
}] }];
|
|
10167
10335
|
} });
|
|
10168
10336
|
|
|
10169
|
-
class AudioContextProvider {
|
|
10170
|
-
static audioContextInstance() {
|
|
10171
|
-
if (!this._audioContext) {
|
|
10172
|
-
let debugFail = false;
|
|
10173
|
-
if (!window.AudioContext || typeof window.AudioContext !== 'function' || debugFail) {
|
|
10174
|
-
throw new Error('Browser does not support Web Audio API!');
|
|
10175
|
-
this._audioContext = null;
|
|
10176
|
-
}
|
|
10177
|
-
else {
|
|
10178
|
-
this._audioContext = new window.AudioContext();
|
|
10179
|
-
}
|
|
10180
|
-
}
|
|
10181
|
-
return this._audioContext;
|
|
10182
|
-
}
|
|
10183
|
-
}
|
|
10184
|
-
AudioContextProvider._audioContext = null;
|
|
10185
|
-
|
|
10186
10337
|
class Item {
|
|
10187
10338
|
constructor(_promptAsString, _training, _recording) {
|
|
10188
10339
|
this._promptAsString = _promptAsString;
|
|
@@ -10605,7 +10756,7 @@ class UploadStatus {
|
|
|
10605
10756
|
constructor() {
|
|
10606
10757
|
this._awaitNewUpload = false;
|
|
10607
10758
|
this.spinnerMode = 'determinate';
|
|
10608
|
-
this.
|
|
10759
|
+
this.colorStatus = 'primary';
|
|
10609
10760
|
this._value = 100;
|
|
10610
10761
|
this.displayValue = null;
|
|
10611
10762
|
this.toolTipText = '';
|
|
@@ -10644,13 +10795,13 @@ class UploadStatus {
|
|
|
10644
10795
|
set status(status) {
|
|
10645
10796
|
this._status = status;
|
|
10646
10797
|
if ('accent' === status) {
|
|
10647
|
-
this.
|
|
10798
|
+
this.colorStatus = 'accent';
|
|
10648
10799
|
}
|
|
10649
10800
|
else if ('warn' === status) {
|
|
10650
|
-
this.
|
|
10801
|
+
this.colorStatus = 'warn';
|
|
10651
10802
|
}
|
|
10652
10803
|
else {
|
|
10653
|
-
this.
|
|
10804
|
+
this.colorStatus = 'primary';
|
|
10654
10805
|
}
|
|
10655
10806
|
this._updateSpinner();
|
|
10656
10807
|
}
|
|
@@ -10660,12 +10811,14 @@ class UploadStatus {
|
|
|
10660
10811
|
}
|
|
10661
10812
|
UploadStatus.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: UploadStatus, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
10662
10813
|
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: `
|
|
10663
|
-
<mat-progress-spinner [mode]="spinnerMode" [color]="
|
|
10814
|
+
<mat-progress-spinner [mode]="spinnerMode" [color]="colorStatus" [diameter]="30" [strokeWidth]="5" [value]="_value"
|
|
10815
|
+
[matTooltip]="toolTipText"></mat-progress-spinner>
|
|
10664
10816
|
`, 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"] }] });
|
|
10665
10817
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: UploadStatus, decorators: [{
|
|
10666
10818
|
type: Component,
|
|
10667
10819
|
args: [{ selector: 'app-uploadstatus', template: `
|
|
10668
|
-
<mat-progress-spinner [mode]="spinnerMode" [color]="
|
|
10820
|
+
<mat-progress-spinner [mode]="spinnerMode" [color]="colorStatus" [diameter]="30" [strokeWidth]="5" [value]="_value"
|
|
10821
|
+
[matTooltip]="toolTipText"></mat-progress-spinner>
|
|
10669
10822
|
`, styles: [":host{text-align:left}\n", "mat-progress-spinner{display:inline-block}\n"] }]
|
|
10670
10823
|
}], propDecorators: { value: [{
|
|
10671
10824
|
type: Input
|
|
@@ -10774,7 +10927,7 @@ class TransportPanel extends ResponsiveComponent {
|
|
|
10774
10927
|
}
|
|
10775
10928
|
}
|
|
10776
10929
|
}
|
|
10777
|
-
TransportPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: TransportPanel, deps: [{ token: i1$
|
|
10930
|
+
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 });
|
|
10778
10931
|
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: `
|
|
10779
10932
|
<button id="bwdBtn" *ngIf="navigationEnabled" (click)="actions.bwdAction.perform()" [disabled]="bwdDisabled()"
|
|
10780
10933
|
mat-raised-button>
|
|
@@ -10819,7 +10972,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10819
10972
|
</button>
|
|
10820
10973
|
|
|
10821
10974
|
`, 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"] }]
|
|
10822
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
10975
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; }, propDecorators: { readonly: [{
|
|
10823
10976
|
type: Input
|
|
10824
10977
|
}], actions: [{
|
|
10825
10978
|
type: Input
|
|
@@ -10891,7 +11044,7 @@ class ControlPanel extends ResponsiveComponent {
|
|
|
10891
11044
|
return this._ready;
|
|
10892
11045
|
}
|
|
10893
11046
|
}
|
|
10894
|
-
ControlPanel.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: ControlPanel, deps: [{ token: i1$
|
|
11047
|
+
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 });
|
|
10895
11048
|
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: `
|
|
10896
11049
|
<div *ngIf="!screenXs" style="flex-direction: row" >
|
|
10897
11050
|
<app-sprstatusdisplay style="flex:0 0 0" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"
|
|
@@ -10901,9 +11054,9 @@ ControlPanel.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version:
|
|
|
10901
11054
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
10902
11055
|
<app-readystateindicator [ready]="_ready"></app-readystateindicator>
|
|
10903
11056
|
</div>
|
|
10904
|
-
<div *ngIf="screenXs"style="flex-direction: column" >
|
|
11057
|
+
<div *ngIf="screenXs" style="flex-direction: column" >
|
|
10905
11058
|
<div style="flex-direction: row" class="flexFill" >
|
|
10906
|
-
<app-sprstatusdisplay style="flex:10 0 0
|
|
11059
|
+
<app-sprstatusdisplay style="flex:10 0 0" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"
|
|
10907
11060
|
class="hidden-xs"></app-sprstatusdisplay>
|
|
10908
11061
|
<app-uploadstatus style="flex:0 0 0" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
10909
11062
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
@@ -10924,9 +11077,9 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10924
11077
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
10925
11078
|
<app-readystateindicator [ready]="_ready"></app-readystateindicator>
|
|
10926
11079
|
</div>
|
|
10927
|
-
<div *ngIf="screenXs"style="flex-direction: column" >
|
|
11080
|
+
<div *ngIf="screenXs" style="flex-direction: column" >
|
|
10928
11081
|
<div style="flex-direction: row" class="flexFill" >
|
|
10929
|
-
<app-sprstatusdisplay style="flex:10 0 0
|
|
11082
|
+
<app-sprstatusdisplay style="flex:10 0 0" [statusMsg]="statusMsg" [statusAlertType]="statusAlertType" [statusWaiting]="statusWaiting"
|
|
10930
11083
|
class="hidden-xs"></app-sprstatusdisplay>
|
|
10931
11084
|
<app-uploadstatus style="flex:0 0 0" *ngIf="enableUploadRecordings" [value]="uploadProgress"
|
|
10932
11085
|
[status]="uploadStatus" [awaitNewUpload]="processing"></app-uploadstatus>
|
|
@@ -10936,7 +11089,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
10936
11089
|
|
|
10937
11090
|
</div>
|
|
10938
11091
|
`, styles: ["div{align-content:center;align-items:center;margin:0;padding:20px;min-height:min-content}\n"] }]
|
|
10939
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
11092
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i1$3.MatDialog }]; }, propDecorators: { statusDisplay: [{
|
|
10940
11093
|
type: ViewChild,
|
|
10941
11094
|
args: [StatusDisplay, { static: true }]
|
|
10942
11095
|
}], transportPanel: [{
|
|
@@ -11591,7 +11744,7 @@ class RecordingItemControls extends ResponsiveComponent {
|
|
|
11591
11744
|
// this.status = 'ERROR';
|
|
11592
11745
|
}
|
|
11593
11746
|
}
|
|
11594
|
-
RecordingItemControls.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingItemControls, deps: [{ token: i1$
|
|
11747
|
+
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 });
|
|
11595
11748
|
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: `
|
|
11596
11749
|
<button matTooltip="Start playback" (click)="playStartAction?.perform()"
|
|
11597
11750
|
[disabled]="playStartAction?.disabled"
|
|
@@ -11640,7 +11793,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
11640
11793
|
[style.color]="(peakDbLvl > warnDbLevel)?'red':'black'">{{peakDbLvl | number:'1.1-1'}} dB </span></td></tr>
|
|
11641
11794
|
<tr *ngIf="_agc"><td>AGC:</td><td><span matTooltip="Auto gain control">{{agcString}}</span></td></tr></table></div>
|
|
11642
11795
|
`, 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"] }]
|
|
11643
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
11796
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { audioSignalCollapsed: [{
|
|
11644
11797
|
type: Input
|
|
11645
11798
|
}], enableDownload: [{
|
|
11646
11799
|
type: Input
|
|
@@ -11721,7 +11874,7 @@ class RecordingItemDisplay extends ResponsiveComponent {
|
|
|
11721
11874
|
let peakDBVal = levelInfo.powerLevelDB();
|
|
11722
11875
|
if (this.peakDbLvl < peakDBVal) {
|
|
11723
11876
|
this.peakDbLvl = peakDBVal;
|
|
11724
|
-
// the event comes from outside
|
|
11877
|
+
// the event comes from outside an Angular zone
|
|
11725
11878
|
this.changeDetectorRef.detectChanges();
|
|
11726
11879
|
}
|
|
11727
11880
|
this.liveLevel.update(levelInfo);
|
|
@@ -11737,7 +11890,7 @@ class RecordingItemDisplay extends ResponsiveComponent {
|
|
|
11737
11890
|
this.changeDetectorRef.detectChanges();
|
|
11738
11891
|
}
|
|
11739
11892
|
}
|
|
11740
|
-
RecordingItemDisplay.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingItemDisplay, deps: [{ token: i1$
|
|
11893
|
+
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 });
|
|
11741
11894
|
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: `
|
|
11742
11895
|
<div [class]="{audioStatusDisplay:!screenXs,audioStatusDisplayXs:screenXs}">
|
|
11743
11896
|
<audio-levelbar style="flex:1 0 1%" [streamingMode]="streamingMode" [displayLevelInfos]="_displayLevelInfos"></audio-levelbar>
|
|
@@ -11752,7 +11905,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
11752
11905
|
<spr-recordingitemcontrols style="flex:0 0 0px" [audioLoaded]="displayAudioBuffer!==null" [playStartAction]="playStartAction" [playStopAction]="playStopAction" [peakDbLvl]="peakDbLvl" [agc]="_agc" (onShowRecordingDetails)="onShowRecordingDetails.emit()"></spr-recordingitemcontrols>
|
|
11753
11906
|
</div>
|
|
11754
11907
|
`, 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"] }]
|
|
11755
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
11908
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }, { type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { liveLevel: [{
|
|
11756
11909
|
type: ViewChild,
|
|
11757
11910
|
args: [LevelBar, { static: true }]
|
|
11758
11911
|
}], streamingMode: [{
|
|
@@ -12056,6 +12209,7 @@ let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
|
|
|
12056
12209
|
this._wakeLock = false;
|
|
12057
12210
|
this._selectedDeviceId = undefined;
|
|
12058
12211
|
this._channelCount = 2;
|
|
12212
|
+
this._allowEchoCancellation = false;
|
|
12059
12213
|
this._session = null;
|
|
12060
12214
|
this._recordingFile = null;
|
|
12061
12215
|
this.startedDate = null;
|
|
@@ -12097,6 +12251,12 @@ let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
|
|
|
12097
12251
|
this.streamLevelMeasure = new StreamLevelMeasure();
|
|
12098
12252
|
this.selCaptureDeviceId = null;
|
|
12099
12253
|
}
|
|
12254
|
+
get allowEchoCancellation() {
|
|
12255
|
+
return this._allowEchoCancellation;
|
|
12256
|
+
}
|
|
12257
|
+
set allowEchoCancellation(value) {
|
|
12258
|
+
this._allowEchoCancellation = value;
|
|
12259
|
+
}
|
|
12100
12260
|
get maxAutoNetMemStoreSamples() {
|
|
12101
12261
|
return this._maxAutoNetMemStoreSamples;
|
|
12102
12262
|
}
|
|
@@ -12482,7 +12642,7 @@ let BasicRecorder = class BasicRecorder extends ResponsiveComponent {
|
|
|
12482
12642
|
else {
|
|
12483
12643
|
console.log("Open session with default audio device for " + this._channelCount + " channels");
|
|
12484
12644
|
}
|
|
12485
|
-
this.ac.open(this._channelCount, this._selectedDeviceId, this._autoGainControlConfigs);
|
|
12645
|
+
this.ac.open(this._channelCount, this._selectedDeviceId, this._autoGainControlConfigs, this._allowEchoCancellation);
|
|
12486
12646
|
}
|
|
12487
12647
|
else {
|
|
12488
12648
|
this.ac.start();
|
|
@@ -12842,6 +13002,7 @@ class SessionManager extends BasicRecorder {
|
|
|
12842
13002
|
this.bpo = bpo;
|
|
12843
13003
|
this.renderer = renderer;
|
|
12844
13004
|
this.recFileService = recFileService;
|
|
13005
|
+
this.offlineAudioContext = null;
|
|
12845
13006
|
this.enableUploadRecordings = true;
|
|
12846
13007
|
this.enableDownloadRecordings = false;
|
|
12847
13008
|
this.status = 0 /* BLOCKED */;
|
|
@@ -12898,37 +13059,58 @@ class SessionManager extends BasicRecorder {
|
|
|
12898
13059
|
this.transportActions.nextAction.disabled = true;
|
|
12899
13060
|
this.transportActions.pauseAction.disabled = true;
|
|
12900
13061
|
this.playStartAction.disabled = true;
|
|
12901
|
-
let context
|
|
12902
|
-
try {
|
|
12903
|
-
|
|
12904
|
-
}
|
|
12905
|
-
|
|
12906
|
-
|
|
12907
|
-
|
|
12908
|
-
|
|
12909
|
-
|
|
12910
|
-
|
|
12911
|
-
|
|
12912
|
-
|
|
12913
|
-
|
|
12914
|
-
|
|
12915
|
-
|
|
12916
|
-
|
|
12917
|
-
|
|
12918
|
-
|
|
12919
|
-
|
|
12920
|
-
|
|
12921
|
-
|
|
12922
|
-
|
|
12923
|
-
|
|
12924
|
-
|
|
13062
|
+
// let context:AudioContext|null=null;
|
|
13063
|
+
// try {
|
|
13064
|
+
// context = AudioContextProvider.audioContextInstance();
|
|
13065
|
+
// } catch (err) {
|
|
13066
|
+
// this.status = Status.ERROR;
|
|
13067
|
+
// let errMsg = 'Unknown error';
|
|
13068
|
+
// if(err instanceof Error){
|
|
13069
|
+
// errMsg=err.message;
|
|
13070
|
+
// }
|
|
13071
|
+
// this.statusMsg = 'ERROR: ' + errMsg;
|
|
13072
|
+
// this.statusAlertType = 'error';
|
|
13073
|
+
// this.dialog.open(MessageDialog, {
|
|
13074
|
+
// data: {
|
|
13075
|
+
// type: 'error',
|
|
13076
|
+
// title: 'Error',
|
|
13077
|
+
// msg: errMsg,
|
|
13078
|
+
// advice: 'Please use a supported browser.',
|
|
13079
|
+
// }
|
|
13080
|
+
// });
|
|
13081
|
+
// return;
|
|
13082
|
+
// }
|
|
13083
|
+
// if(context) {
|
|
13084
|
+
// console.info("State of audio context: " + context.state)
|
|
13085
|
+
// }else{
|
|
13086
|
+
// console.info("No audio context available!");
|
|
13087
|
+
// }
|
|
13088
|
+
// if (!context || !navigator.mediaDevices) {
|
|
13089
|
+
// this.status = Status.ERROR;
|
|
13090
|
+
// let errMsg = 'Browser does not support Media streams!';
|
|
13091
|
+
// this.statusMsg = 'ERROR: ' + errMsg;
|
|
13092
|
+
// this.statusAlertType = 'error';
|
|
13093
|
+
// this.dialog.open(MessageDialog, {
|
|
13094
|
+
// data: {
|
|
13095
|
+
// type: 'error',
|
|
13096
|
+
// title: 'Error',
|
|
13097
|
+
// msg: errMsg,
|
|
13098
|
+
// advice: 'Please use a supported browser.',
|
|
13099
|
+
// }
|
|
13100
|
+
// });
|
|
13101
|
+
// return;
|
|
13102
|
+
// } else {
|
|
13103
|
+
this.ac = new AudioCapture();
|
|
13104
|
+
if (this.ac) {
|
|
13105
|
+
this.transportActions.startAction.onAction = () => this.startItem();
|
|
13106
|
+
this.ac.listener = this;
|
|
13107
|
+
this.configureStreamCaptureStream();
|
|
13108
|
+
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
13109
|
+
//this.ac.listDevices();
|
|
12925
13110
|
}
|
|
12926
13111
|
else {
|
|
12927
|
-
|
|
12928
|
-
|
|
12929
|
-
if (!context || !navigator.mediaDevices) {
|
|
12930
|
-
this.status = 9 /* ERROR */;
|
|
12931
|
-
let errMsg = 'Browser does not support Media streams!';
|
|
13112
|
+
this.transportActions.startAction.disabled = true;
|
|
13113
|
+
let errMsg = 'Browser does not support Media/Audio API!';
|
|
12932
13114
|
this.statusMsg = 'ERROR: ' + errMsg;
|
|
12933
13115
|
this.statusAlertType = 'error';
|
|
12934
13116
|
this.dialog.open(MessageDialog, {
|
|
@@ -12941,38 +13123,13 @@ class SessionManager extends BasicRecorder {
|
|
|
12941
13123
|
});
|
|
12942
13124
|
return;
|
|
12943
13125
|
}
|
|
12944
|
-
|
|
12945
|
-
|
|
12946
|
-
|
|
12947
|
-
|
|
12948
|
-
|
|
12949
|
-
|
|
12950
|
-
|
|
12951
|
-
//this.ac.listDevices();
|
|
12952
|
-
}
|
|
12953
|
-
else {
|
|
12954
|
-
this.transportActions.startAction.disabled = true;
|
|
12955
|
-
let errMsg = 'Browser does not support Media/Audio API!';
|
|
12956
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
12957
|
-
this.statusAlertType = 'error';
|
|
12958
|
-
this.dialog.open(MessageDialog, {
|
|
12959
|
-
data: {
|
|
12960
|
-
type: 'error',
|
|
12961
|
-
title: 'Error',
|
|
12962
|
-
msg: errMsg,
|
|
12963
|
-
advice: 'Please use a supported browser.',
|
|
12964
|
-
}
|
|
12965
|
-
});
|
|
12966
|
-
return;
|
|
12967
|
-
}
|
|
12968
|
-
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
12969
|
-
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
12970
|
-
this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
12971
|
-
this.transportActions.fwdAction.onAction = () => this.nextItem();
|
|
12972
|
-
this.transportActions.fwdNextAction.onAction = () => this.nextUnrecordedItem();
|
|
12973
|
-
this.transportActions.bwdAction.onAction = () => this.prevItem();
|
|
12974
|
-
this.playStartAction.onAction = () => { var _a; return (_a = this.controlAudioPlayer) === null || _a === void 0 ? void 0 : _a.start(); };
|
|
12975
|
-
}
|
|
13126
|
+
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
13127
|
+
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
13128
|
+
this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
13129
|
+
this.transportActions.fwdAction.onAction = () => this.nextItem();
|
|
13130
|
+
this.transportActions.fwdNextAction.onAction = () => this.nextUnrecordedItem();
|
|
13131
|
+
this.transportActions.bwdAction.onAction = () => this.prevItem();
|
|
13132
|
+
this.playStartAction.onAction = () => { var _a; return (_a = this.controlAudioPlayer) === null || _a === void 0 ? void 0 : _a.start(); };
|
|
12976
13133
|
this.startStopSignalState = 4 /* OFF */;
|
|
12977
13134
|
}
|
|
12978
13135
|
onKeyPress(ke) {
|
|
@@ -13279,7 +13436,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13279
13436
|
}
|
|
13280
13437
|
else {
|
|
13281
13438
|
//console.debug("Fetch audio and store to indexed db...");
|
|
13282
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileIndDbAudioBuffer(this.
|
|
13439
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileIndDbAudioBuffer(this._persistentAudioStorageTarget, this._session.project, rf).subscribe({
|
|
13283
13440
|
next: (iab) => {
|
|
13284
13441
|
//console.debug("Sessionmanager: Received inddb audio buffer: "+iab);
|
|
13285
13442
|
nextIab = iab;
|
|
@@ -13321,7 +13478,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13321
13478
|
// Fetch chunked audio buffer from network
|
|
13322
13479
|
let nextNetAb = null;
|
|
13323
13480
|
//console.debug("Fetch chunked audio from network");
|
|
13324
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileNetAudioBuffer(this.
|
|
13481
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileNetAudioBuffer(this._session.project, rf).subscribe({
|
|
13325
13482
|
next: (netAb) => {
|
|
13326
13483
|
//console.debug("Sessionmanager: Received net audio buffer: "+netAb);
|
|
13327
13484
|
nextNetAb = netAb;
|
|
@@ -13363,7 +13520,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13363
13520
|
// Fetch chunked array audio buffer
|
|
13364
13521
|
let nextAab = null;
|
|
13365
13522
|
//console.debug("Fetch audio and store to (chunked) array buffer...");
|
|
13366
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileArrayAudioBuffer(this.
|
|
13523
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileArrayAudioBuffer(this._session.project, rf).subscribe({
|
|
13367
13524
|
next: (aab) => {
|
|
13368
13525
|
nextAab = aab;
|
|
13369
13526
|
},
|
|
@@ -13401,7 +13558,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13401
13558
|
else {
|
|
13402
13559
|
// Fetch regular audio buffer
|
|
13403
13560
|
//console.debug("Fetch audio and store to audio buffer...");
|
|
13404
|
-
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this.
|
|
13561
|
+
this.audioFetchSubscription = this.recFileService.fetchSprRecordingFileAudioBuffer(this._session.project, rf).subscribe({
|
|
13405
13562
|
next: (ab) => {
|
|
13406
13563
|
this.liveLevelDisplayState = State.READY;
|
|
13407
13564
|
let fabDh = null;
|
|
@@ -13789,7 +13946,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13789
13946
|
const sr = this.ac.currentSampleRate;
|
|
13790
13947
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
13791
13948
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
13792
|
-
let netAb = new NetAudioBuffer(this.
|
|
13949
|
+
let netAb = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
13793
13950
|
as = netAb;
|
|
13794
13951
|
if (this.uploadSet) {
|
|
13795
13952
|
//let rp=new ReadyProvider();
|
|
@@ -13836,7 +13993,7 @@ class SessionManager extends BasicRecorder {
|
|
|
13836
13993
|
const sr = this.ac.currentSampleRate;
|
|
13837
13994
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
13838
13995
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
13839
|
-
const netAb = new NetAudioBuffer(this.
|
|
13996
|
+
const netAb = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
13840
13997
|
as = netAb;
|
|
13841
13998
|
if (this.uploadSet) {
|
|
13842
13999
|
this.uploadSet.onDone = (uploadSet) => {
|
|
@@ -13874,8 +14031,8 @@ class SessionManager extends BasicRecorder {
|
|
|
13874
14031
|
// TODO could we avoid conversion to save CPU resources and transfer float PCM directly?
|
|
13875
14032
|
// TODO duplicate conversion for manual download
|
|
13876
14033
|
//console.log("Build wav writer...");
|
|
13877
|
-
this.processingRecording = true;
|
|
13878
14034
|
if (ab) {
|
|
14035
|
+
this.processingRecording = true;
|
|
13879
14036
|
let ww = new WavWriter();
|
|
13880
14037
|
//new REST API URL
|
|
13881
14038
|
let apiEndPoint = '';
|
|
@@ -14011,7 +14168,7 @@ class SessionManager extends BasicRecorder {
|
|
|
14011
14168
|
}
|
|
14012
14169
|
}
|
|
14013
14170
|
}
|
|
14014
|
-
SessionManager.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SessionManager, deps: [{ token: i1$
|
|
14171
|
+
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 });
|
|
14015
14172
|
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: `
|
|
14016
14173
|
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
14017
14174
|
<app-warningbar [show]="isDefaultAudioTestSession()" warningText="This test uses default audio device! Regular sessions may require a particular audio device (microphone)!"></app-warningbar>
|
|
@@ -14115,7 +14272,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
14115
14272
|
</div>
|
|
14116
14273
|
`, 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"] }]
|
|
14117
14274
|
}], ctorParameters: function () {
|
|
14118
|
-
return [{ type: i1$
|
|
14275
|
+
return [{ type: i1$2.BreakpointObserver }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1$3.MatDialog }, { type: SessionService }, { type: RecordingService }, { type: SpeechRecorderUploader }, { type: SpeechRecorderConfig, decorators: [{
|
|
14119
14276
|
type: Inject,
|
|
14120
14277
|
args: [SPEECHRECORDER_CONFIG]
|
|
14121
14278
|
}] }];
|
|
@@ -14388,18 +14545,10 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14388
14545
|
console.error(errMsg);
|
|
14389
14546
|
}
|
|
14390
14547
|
ngOnInit() {
|
|
14391
|
-
|
|
14392
|
-
|
|
14393
|
-
|
|
14394
|
-
|
|
14395
|
-
}
|
|
14396
|
-
this.sm.controlAudioPlayer = this.controlAudioPlayer;
|
|
14397
|
-
this.sm.statusAlertType = 'info';
|
|
14398
|
-
this.sm.statusMsg = 'Player initialized.';
|
|
14399
|
-
}
|
|
14400
|
-
catch (err) {
|
|
14401
|
-
this.handleError(err);
|
|
14402
|
-
}
|
|
14548
|
+
this.controlAudioPlayer = new AudioPlayer(this);
|
|
14549
|
+
this.sm.controlAudioPlayer = this.controlAudioPlayer;
|
|
14550
|
+
this.sm.statusAlertType = 'info';
|
|
14551
|
+
this.sm.statusMsg = 'Player initialized.';
|
|
14403
14552
|
}
|
|
14404
14553
|
ngAfterViewInit() {
|
|
14405
14554
|
// let wakeLockSupp=('wakeLock' in navigator);
|
|
@@ -14564,7 +14713,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14564
14713
|
}
|
|
14565
14714
|
else {
|
|
14566
14715
|
// all this attempts to customize the message do not work anymore (for security reasons)!!
|
|
14567
|
-
|
|
14716
|
+
const message = "Please do not leave the page, until all recordings are uploaded!";
|
|
14568
14717
|
alert(message);
|
|
14569
14718
|
e = e || window.event;
|
|
14570
14719
|
if (e) {
|
|
@@ -14656,6 +14805,9 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14656
14805
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
14657
14806
|
console.info("Project requested recording channel count: " + chCnt);
|
|
14658
14807
|
this.sm.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
14808
|
+
if (project.allowEchoCancellation !== undefined) {
|
|
14809
|
+
this.sm.allowEchoCancellation = project.allowEchoCancellation;
|
|
14810
|
+
}
|
|
14659
14811
|
if (project.chunkedRecording === true) {
|
|
14660
14812
|
console.debug("Enable chunked upload: chunkSize: " + BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS);
|
|
14661
14813
|
this.sm.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
|
|
@@ -14688,7 +14840,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14688
14840
|
projUrl = window.location.protocol + '//' + window.location.hostname + ':' + window.location.port + '/wikispeech/rest/projects/?sessionId=' + this.sessionId;
|
|
14689
14841
|
}
|
|
14690
14842
|
if (projUrl) {
|
|
14691
|
-
|
|
14843
|
+
const pLoader = new XMLHttpRequest();
|
|
14692
14844
|
pLoader.open("GET", projUrl, true);
|
|
14693
14845
|
pLoader.setRequestHeader('Accept', 'application/json');
|
|
14694
14846
|
pLoader.responseType = "json";
|
|
@@ -14723,7 +14875,7 @@ class SpeechrecorderngComponent extends RecorderComponent {
|
|
|
14723
14875
|
this.sm.statusMsg = 'ERROR: Recording.';
|
|
14724
14876
|
}
|
|
14725
14877
|
}
|
|
14726
|
-
SpeechrecorderngComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngComponent, deps: [{ token:
|
|
14878
|
+
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 });
|
|
14727
14879
|
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: `
|
|
14728
14880
|
<app-sprrecordingsession [projectName]="project?.name" [dataSaved]="dataSaved"></app-sprrecordingsession>
|
|
14729
14881
|
`, 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"] }] });
|
|
@@ -14732,7 +14884,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
14732
14884
|
args: [{ selector: 'app-speechrecorder', providers: [SessionService], template: `
|
|
14733
14885
|
<app-sprrecordingsession [projectName]="project?.name" [dataSaved]="dataSaved"></app-sprrecordingsession>
|
|
14734
14886
|
`, styles: [":host{flex:2;display:flex;flex-direction:column;min-height:0}\n"] }]
|
|
14735
|
-
}], ctorParameters: function () { return [{ type:
|
|
14887
|
+
}], 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: [{
|
|
14736
14888
|
type: ViewChild,
|
|
14737
14889
|
args: [SessionManager, { static: true }]
|
|
14738
14890
|
}] } });
|
|
@@ -14752,10 +14904,8 @@ class AudioDisplayPlayer {
|
|
|
14752
14904
|
this.ref = ref;
|
|
14753
14905
|
this.eRef = eRef;
|
|
14754
14906
|
this._audioUrl = null;
|
|
14755
|
-
this.aCtx = null;
|
|
14756
14907
|
this._audioClip = null;
|
|
14757
14908
|
this.currentLoader = null;
|
|
14758
|
-
//console.log("constructor: "+this.ac);
|
|
14759
14909
|
this.parentE = this.eRef.nativeElement;
|
|
14760
14910
|
this.playStartAction = new Action("Start");
|
|
14761
14911
|
this.playSelectionAction = new Action("Play selected");
|
|
@@ -14763,26 +14913,19 @@ class AudioDisplayPlayer {
|
|
|
14763
14913
|
this.status = "Player created.";
|
|
14764
14914
|
}
|
|
14765
14915
|
ngOnInit() {
|
|
14766
|
-
//console.log("OnInit: "+this.ac);
|
|
14767
14916
|
this.zoomSelectedAction = this.audioDisplayScrollPane.zoomSelectedAction;
|
|
14768
14917
|
this.zoomFitToPanelAction = this.audioDisplayScrollPane.zoomFitToPanelAction;
|
|
14769
14918
|
this.zoomOutAction = this.audioDisplayScrollPane.zoomOutAction;
|
|
14770
14919
|
this.zoomInAction = this.audioDisplayScrollPane.zoomInAction;
|
|
14771
|
-
|
|
14772
|
-
this.aCtx = AudioContextProvider.audioContextInstance();
|
|
14773
|
-
if (this.aCtx) {
|
|
14774
|
-
this.ap = new AudioPlayer(this.aCtx, this);
|
|
14775
|
-
}
|
|
14776
|
-
}
|
|
14777
|
-
catch (err) {
|
|
14778
|
-
if (err instanceof Error) {
|
|
14779
|
-
this.status = err.message;
|
|
14780
|
-
}
|
|
14781
|
-
}
|
|
14920
|
+
this.ap = new AudioPlayer(this);
|
|
14782
14921
|
}
|
|
14783
14922
|
ngAfterViewInit() {
|
|
14784
|
-
if (this.
|
|
14785
|
-
this.playStartAction.onAction = () => {
|
|
14923
|
+
if (this.ap) {
|
|
14924
|
+
this.playStartAction.onAction = () => {
|
|
14925
|
+
var _a;
|
|
14926
|
+
console.debug("Start action, player: " + this.ap);
|
|
14927
|
+
(_a = this.ap) === null || _a === void 0 ? void 0 : _a.start();
|
|
14928
|
+
};
|
|
14786
14929
|
this.playSelectionAction.onAction = () => { var _a; return (_a = this.ap) === null || _a === void 0 ? void 0 : _a.startSelected(); };
|
|
14787
14930
|
this.playStopAction.onAction = () => { var _a; return (_a = this.ap) === null || _a === void 0 ? void 0 : _a.stop(); };
|
|
14788
14931
|
}
|
|
@@ -14847,15 +14990,12 @@ class AudioDisplayPlayer {
|
|
|
14847
14990
|
//console.debug("Loaded");
|
|
14848
14991
|
this.status = 'Audio file loaded.';
|
|
14849
14992
|
//console.debug("Received data ", data.byteLength);
|
|
14850
|
-
|
|
14851
|
-
|
|
14852
|
-
|
|
14853
|
-
|
|
14854
|
-
|
|
14855
|
-
|
|
14856
|
-
this.audioClip = new AudioClip(adh);
|
|
14857
|
-
});
|
|
14858
|
-
}
|
|
14993
|
+
AudioContextProvider.decodeAudioData(data).then(audioBuffer => {
|
|
14994
|
+
//console.debug("Audio Buffer Samplerate: ", audioBuffer.sampleRate)
|
|
14995
|
+
let as = new AudioBufferSource(audioBuffer);
|
|
14996
|
+
let adh = new AudioDataHolder(as);
|
|
14997
|
+
this.audioClip = new AudioClip(adh);
|
|
14998
|
+
});
|
|
14859
14999
|
}
|
|
14860
15000
|
set audioData(audioData) {
|
|
14861
15001
|
this.audioDisplayScrollPane.audioData = audioData;
|
|
@@ -14938,7 +15078,7 @@ class AudioDisplayPlayer {
|
|
|
14938
15078
|
this.status = 'ERROR';
|
|
14939
15079
|
}
|
|
14940
15080
|
}
|
|
14941
|
-
AudioDisplayPlayer.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioDisplayPlayer, deps: [{ token:
|
|
15081
|
+
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 });
|
|
14942
15082
|
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: `
|
|
14943
15083
|
|
|
14944
15084
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
@@ -14969,7 +15109,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
14969
15109
|
[zoomSelectedAction]="zoomSelectedAction"
|
|
14970
15110
|
[zoomFitToPanelAction]="zoomFitToPanelAction"></audio-display-control><p>{{status}}
|
|
14971
15111
|
`, 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"] }]
|
|
14972
|
-
}], ctorParameters: function () { return [{ type:
|
|
15112
|
+
}], ctorParameters: function () { return [{ type: i4$2.ActivatedRoute }, { type: i0.ChangeDetectorRef }, { type: i0.ElementRef }]; }, propDecorators: { playStartAction: [{
|
|
14973
15113
|
type: Input
|
|
14974
15114
|
}], playStopAction: [{
|
|
14975
15115
|
type: Input
|
|
@@ -15115,41 +15255,42 @@ class RecordingFileService extends BasicRecordingService {
|
|
|
15115
15255
|
});
|
|
15116
15256
|
}
|
|
15117
15257
|
// TODO test
|
|
15118
|
-
fetchAndApplyRecordingFile(
|
|
15258
|
+
fetchAndApplyRecordingFile(recordingFile) {
|
|
15119
15259
|
let wobs = new Observable(observer => {
|
|
15120
15260
|
if (recordingFile.recordingFileId) {
|
|
15121
15261
|
let obs = this.fetchAudiofile(recordingFile.recordingFileId);
|
|
15122
|
-
obs.subscribe(resp => {
|
|
15123
|
-
|
|
15124
|
-
|
|
15125
|
-
|
|
15126
|
-
|
|
15127
|
-
|
|
15128
|
-
|
|
15129
|
-
|
|
15262
|
+
obs.subscribe({ next: resp => {
|
|
15263
|
+
if (resp.body) {
|
|
15264
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
15265
|
+
let as = new AudioBufferSource(ab);
|
|
15266
|
+
RecordingFileUtils.setAudioData(recordingFile, new AudioDataHolder(as));
|
|
15267
|
+
if (this.debugDelay > 0) {
|
|
15268
|
+
window.setTimeout(() => {
|
|
15269
|
+
observer.next(recordingFile);
|
|
15270
|
+
observer.complete();
|
|
15271
|
+
}, this.debugDelay);
|
|
15272
|
+
}
|
|
15273
|
+
else {
|
|
15130
15274
|
observer.next(recordingFile);
|
|
15131
15275
|
observer.complete();
|
|
15132
|
-
}
|
|
15133
|
-
}
|
|
15134
|
-
|
|
15135
|
-
|
|
15136
|
-
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
|
|
15143
|
-
|
|
15144
|
-
|
|
15145
|
-
|
|
15146
|
-
|
|
15147
|
-
|
|
15148
|
-
|
|
15149
|
-
|
|
15150
|
-
// all other states are errors
|
|
15151
|
-
observer.error(error);
|
|
15152
|
-
observer.complete();
|
|
15276
|
+
}
|
|
15277
|
+
}).catch(reason => { observer.error(reason); });
|
|
15278
|
+
}
|
|
15279
|
+
else {
|
|
15280
|
+
observer.error('Received no audio data!');
|
|
15281
|
+
}
|
|
15282
|
+
},
|
|
15283
|
+
error: (error) => {
|
|
15284
|
+
if (error.status == 404) {
|
|
15285
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
15286
|
+
observer.next(null);
|
|
15287
|
+
observer.complete();
|
|
15288
|
+
}
|
|
15289
|
+
else {
|
|
15290
|
+
// all other states are errors
|
|
15291
|
+
observer.error(error);
|
|
15292
|
+
observer.complete();
|
|
15293
|
+
}
|
|
15153
15294
|
}
|
|
15154
15295
|
});
|
|
15155
15296
|
}
|
|
@@ -15163,82 +15304,40 @@ class RecordingFileService extends BasicRecordingService {
|
|
|
15163
15304
|
let wobs = new Observable(observer => {
|
|
15164
15305
|
let rf = null;
|
|
15165
15306
|
let rfDescrObs = this.recordingFileDescrObserver(recordingFileId);
|
|
15166
|
-
rfDescrObs.subscribe(value => {
|
|
15167
|
-
|
|
15168
|
-
|
|
15169
|
-
|
|
15170
|
-
|
|
15171
|
-
|
|
15172
|
-
|
|
15173
|
-
|
|
15174
|
-
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
|
|
15180
|
-
|
|
15181
|
-
|
|
15182
|
-
|
|
15183
|
-
|
|
15184
|
-
|
|
15185
|
-
|
|
15186
|
-
|
|
15187
|
-
|
|
15307
|
+
rfDescrObs.subscribe({ next: value => {
|
|
15308
|
+
rf = value;
|
|
15309
|
+
}, error: (error) => {
|
|
15310
|
+
observer.error(error);
|
|
15311
|
+
}, complete: () => {
|
|
15312
|
+
let rfAudioObs = this.fetchAudiofile(recordingFileId);
|
|
15313
|
+
rfAudioObs.subscribe({
|
|
15314
|
+
next: resp => {
|
|
15315
|
+
// Do not use Promise version, which does not work with Safari 13
|
|
15316
|
+
if (resp.body) {
|
|
15317
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
15318
|
+
if (rf) {
|
|
15319
|
+
let as = new AudioBufferSource(ab);
|
|
15320
|
+
RecordingFileUtils.setAudioData(rf, new AudioDataHolder(as));
|
|
15321
|
+
}
|
|
15322
|
+
else {
|
|
15323
|
+
observer.error('Recording file object null');
|
|
15324
|
+
}
|
|
15325
|
+
if (this.debugDelay > 0) {
|
|
15326
|
+
window.setTimeout(() => {
|
|
15327
|
+
observer.next(rf);
|
|
15328
|
+
observer.complete();
|
|
15329
|
+
}, this.debugDelay);
|
|
15330
|
+
}
|
|
15331
|
+
else {
|
|
15332
|
+
observer.next(rf);
|
|
15333
|
+
observer.complete();
|
|
15334
|
+
}
|
|
15335
|
+
}).catch(reason => { observer.error(reason); });
|
|
15188
15336
|
}
|
|
15189
15337
|
else {
|
|
15190
|
-
observer.
|
|
15191
|
-
observer.complete();
|
|
15192
|
-
}
|
|
15193
|
-
});
|
|
15194
|
-
}
|
|
15195
|
-
else {
|
|
15196
|
-
observer.error('Received no audio data');
|
|
15197
|
-
}
|
|
15198
|
-
}, (error) => {
|
|
15199
|
-
if (error.status == 404) {
|
|
15200
|
-
// Interpret not as an error, the file ist not recorded yet
|
|
15201
|
-
observer.next(null);
|
|
15202
|
-
observer.complete();
|
|
15203
|
-
}
|
|
15204
|
-
else {
|
|
15205
|
-
// all other states are errors
|
|
15206
|
-
observer.error(error);
|
|
15207
|
-
observer.complete();
|
|
15208
|
-
}
|
|
15209
|
-
});
|
|
15210
|
-
});
|
|
15211
|
-
});
|
|
15212
|
-
return wobs;
|
|
15213
|
-
}
|
|
15214
|
-
fetchSprRecordingFile(aCtx, recordingFileId) {
|
|
15215
|
-
let wobs = new Observable(observer => {
|
|
15216
|
-
let rf = null;
|
|
15217
|
-
let rfDescrObs = this.sprRecordingFileDescrObserver(recordingFileId);
|
|
15218
|
-
rfDescrObs.subscribe(value => {
|
|
15219
|
-
rf = value;
|
|
15220
|
-
}, (error) => {
|
|
15221
|
-
observer.error(error);
|
|
15222
|
-
}, () => {
|
|
15223
|
-
let sampleCnt = null;
|
|
15224
|
-
if (rf && rf.channels && rf.frames) {
|
|
15225
|
-
sampleCnt = rf.channels * rf.frames;
|
|
15226
|
-
}
|
|
15227
|
-
// TODO use download storage type depending on sample count of file
|
|
15228
|
-
if (rf && rf.samplerate && sampleCnt != null && sampleCnt > this._maxAutoNetMemStoreSamples) {
|
|
15229
|
-
const baseUrl = this.recoFileUrl(recordingFileId);
|
|
15230
|
-
const obNetAb = this.chunkAudioRequestToNetAudioBuffer(aCtx, baseUrl, 0, rf === null || rf === void 0 ? void 0 : rf.samplerate, BasicRecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS, rf.frames);
|
|
15231
|
-
obNetAb.subscribe({
|
|
15232
|
-
next: (nab) => {
|
|
15233
|
-
let adh = new AudioDataHolder(nab);
|
|
15234
|
-
if (rf) {
|
|
15235
|
-
RecordingFileUtils.setAudioData(rf, adh);
|
|
15236
|
-
observer.next(rf);
|
|
15338
|
+
observer.error('Received no audio data');
|
|
15237
15339
|
}
|
|
15238
15340
|
},
|
|
15239
|
-
complete: () => {
|
|
15240
|
-
observer.complete();
|
|
15241
|
-
},
|
|
15242
15341
|
error: (error) => {
|
|
15243
15342
|
if (error.status == 404) {
|
|
15244
15343
|
// Interpret not as an error, the file ist not recorded yet
|
|
@@ -15253,47 +15352,97 @@ class RecordingFileService extends BasicRecordingService {
|
|
|
15253
15352
|
}
|
|
15254
15353
|
});
|
|
15255
15354
|
}
|
|
15256
|
-
|
|
15257
|
-
|
|
15258
|
-
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15355
|
+
});
|
|
15356
|
+
});
|
|
15357
|
+
return wobs;
|
|
15358
|
+
}
|
|
15359
|
+
fetchSprRecordingFile(recordingFileId) {
|
|
15360
|
+
let wobs = new Observable(observer => {
|
|
15361
|
+
let rf = null;
|
|
15362
|
+
let rfDescrObs = this.sprRecordingFileDescrObserver(recordingFileId);
|
|
15363
|
+
rfDescrObs.subscribe({ next: value => {
|
|
15364
|
+
rf = value;
|
|
15365
|
+
},
|
|
15366
|
+
error: (error) => {
|
|
15367
|
+
observer.error(error);
|
|
15368
|
+
}, complete: () => {
|
|
15369
|
+
let sampleCnt = null;
|
|
15370
|
+
if (rf && rf.channels && rf.frames) {
|
|
15371
|
+
sampleCnt = rf.channels * rf.frames;
|
|
15372
|
+
}
|
|
15373
|
+
// TODO use download storage type depending on sample count of file
|
|
15374
|
+
if (rf && rf.samplerate && sampleCnt != null && sampleCnt > this._maxAutoNetMemStoreSamples) {
|
|
15375
|
+
const baseUrl = this.recoFileUrl(recordingFileId);
|
|
15376
|
+
const obNetAb = this.chunkAudioRequestToNetAudioBuffer(baseUrl, 0, rf === null || rf === void 0 ? void 0 : rf.samplerate, BasicRecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS, rf.frames);
|
|
15377
|
+
obNetAb.subscribe({
|
|
15378
|
+
next: (nab) => {
|
|
15379
|
+
let adh = new AudioDataHolder(nab);
|
|
15262
15380
|
if (rf) {
|
|
15263
|
-
let as = new AudioBufferSource(ab);
|
|
15264
|
-
let adh = new AudioDataHolder(as);
|
|
15265
15381
|
RecordingFileUtils.setAudioData(rf, adh);
|
|
15382
|
+
observer.next(rf);
|
|
15383
|
+
}
|
|
15384
|
+
},
|
|
15385
|
+
complete: () => {
|
|
15386
|
+
observer.complete();
|
|
15387
|
+
},
|
|
15388
|
+
error: (error) => {
|
|
15389
|
+
if (error.status == 404) {
|
|
15390
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
15391
|
+
observer.next(null);
|
|
15392
|
+
observer.complete();
|
|
15266
15393
|
}
|
|
15267
15394
|
else {
|
|
15268
|
-
|
|
15395
|
+
// all other states are errors
|
|
15396
|
+
observer.error(error);
|
|
15397
|
+
observer.complete();
|
|
15269
15398
|
}
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
15273
|
-
|
|
15274
|
-
|
|
15399
|
+
}
|
|
15400
|
+
});
|
|
15401
|
+
}
|
|
15402
|
+
else {
|
|
15403
|
+
let rfAudioObs = this.fetchAudiofile(recordingFileId);
|
|
15404
|
+
rfAudioObs.subscribe({ next: resp => {
|
|
15405
|
+
// Do not use Promise version, which does not work with Safari 13
|
|
15406
|
+
if (resp.body) {
|
|
15407
|
+
AudioContextProvider.decodeAudioData(resp.body).then(ab => {
|
|
15408
|
+
if (rf) {
|
|
15409
|
+
let as = new AudioBufferSource(ab);
|
|
15410
|
+
let adh = new AudioDataHolder(as);
|
|
15411
|
+
RecordingFileUtils.setAudioData(rf, adh);
|
|
15412
|
+
}
|
|
15413
|
+
else {
|
|
15414
|
+
observer.error('Recording file object null');
|
|
15415
|
+
}
|
|
15416
|
+
if (this.debugDelay > 0) {
|
|
15417
|
+
window.setTimeout(() => {
|
|
15418
|
+
observer.next(rf);
|
|
15419
|
+
observer.complete();
|
|
15420
|
+
}, this.debugDelay);
|
|
15421
|
+
}
|
|
15422
|
+
else {
|
|
15423
|
+
observer.next(rf);
|
|
15424
|
+
observer.complete();
|
|
15425
|
+
}
|
|
15426
|
+
}).catch(reason => { observer.error(reason); });
|
|
15275
15427
|
}
|
|
15276
15428
|
else {
|
|
15277
|
-
observer.
|
|
15429
|
+
observer.error('Received no audio data');
|
|
15430
|
+
}
|
|
15431
|
+
},
|
|
15432
|
+
error: (error) => {
|
|
15433
|
+
if (error.status == 404) {
|
|
15434
|
+
// Interpret not as an error, the file ist not recorded yet
|
|
15435
|
+
observer.next(null);
|
|
15278
15436
|
observer.complete();
|
|
15279
15437
|
}
|
|
15280
|
-
|
|
15281
|
-
|
|
15282
|
-
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
observer.next(null);
|
|
15289
|
-
observer.complete();
|
|
15290
|
-
}
|
|
15291
|
-
else {
|
|
15292
|
-
// all other states are errors
|
|
15293
|
-
observer.error(error);
|
|
15294
|
-
observer.complete();
|
|
15295
|
-
}
|
|
15296
|
-
});
|
|
15438
|
+
else {
|
|
15439
|
+
// all other states are errors
|
|
15440
|
+
observer.error(error);
|
|
15441
|
+
observer.complete();
|
|
15442
|
+
}
|
|
15443
|
+
}
|
|
15444
|
+
});
|
|
15445
|
+
}
|
|
15297
15446
|
}
|
|
15298
15447
|
});
|
|
15299
15448
|
});
|
|
@@ -15347,7 +15496,7 @@ RecordingFileNaviComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0
|
|
|
15347
15496
|
<legend>Versions</legend>
|
|
15348
15497
|
<mat-progress-spinner *ngIf="naviInfoLoading" mode="indeterminate" [diameter]="15"></mat-progress-spinner>
|
|
15349
15498
|
<select *ngIf="!naviInfoLoading" [disabled]="versions==null || versions.length==1" (change)="selectVersionChange($event)">
|
|
15350
|
-
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<
|
|
15499
|
+
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<ng-container *ngIf="i==0"> (latest)</ng-container></option>
|
|
15351
15500
|
</select>
|
|
15352
15501
|
</fieldset>
|
|
15353
15502
|
<fieldset>
|
|
@@ -15382,7 +15531,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
15382
15531
|
<legend>Versions</legend>
|
|
15383
15532
|
<mat-progress-spinner *ngIf="naviInfoLoading" mode="indeterminate" [diameter]="15"></mat-progress-spinner>
|
|
15384
15533
|
<select *ngIf="!naviInfoLoading" [disabled]="versions==null || versions.length==1" (change)="selectVersionChange($event)">
|
|
15385
|
-
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<
|
|
15534
|
+
<option *ngFor="let v of versions; let i = index" [selected]="v===version" value="{{v}}">{{v}}<ng-container *ngIf="i==0"> (latest)</ng-container></option>
|
|
15386
15535
|
</select>
|
|
15387
15536
|
</fieldset>
|
|
15388
15537
|
<fieldset>
|
|
@@ -15434,9 +15583,9 @@ class RecordingFileMetaComponent {
|
|
|
15434
15583
|
constructor() {
|
|
15435
15584
|
this.sessionId = null;
|
|
15436
15585
|
this._recordingFile = null;
|
|
15437
|
-
this.stateLoading = false;
|
|
15438
15586
|
this.itemCode = null;
|
|
15439
15587
|
this.uuid = null;
|
|
15588
|
+
this.stateLoading = false;
|
|
15440
15589
|
}
|
|
15441
15590
|
get recordingFile() {
|
|
15442
15591
|
return this._recordingFile;
|
|
@@ -15545,7 +15694,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
15545
15694
|
</mat-card-content>
|
|
15546
15695
|
</mat-card>
|
|
15547
15696
|
` }]
|
|
15548
|
-
}], propDecorators: { sessionId: [{
|
|
15697
|
+
}], ctorParameters: function () { return []; }, propDecorators: { sessionId: [{
|
|
15549
15698
|
type: Input
|
|
15550
15699
|
}], stateLoading: [{
|
|
15551
15700
|
type: Input
|
|
@@ -15566,7 +15715,6 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15566
15715
|
this.ref = ref;
|
|
15567
15716
|
this.eRef = eRef;
|
|
15568
15717
|
this.dialog = dialog;
|
|
15569
|
-
//protected _recordingFileId: string | number = null;
|
|
15570
15718
|
this.sessionId = null;
|
|
15571
15719
|
this.sessionIdFromRoute = null;
|
|
15572
15720
|
this.availRecFiles = null;
|
|
@@ -15575,9 +15723,11 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15575
15723
|
this.recordingFileVersion = null;
|
|
15576
15724
|
this.routedByQueryParam = false;
|
|
15577
15725
|
this.posInList = null;
|
|
15578
|
-
this.audioFetching = false;
|
|
15579
|
-
this.naviInfoLoading = false;
|
|
15580
15726
|
this.parentE = this.eRef.nativeElement;
|
|
15727
|
+
// TODO Should be initialized with false, but this causes in debug mode:
|
|
15728
|
+
// 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
|
|
15729
|
+
this.audioFetching = true;
|
|
15730
|
+
this.naviInfoLoading = false;
|
|
15581
15731
|
this.firstAction = new Action('First');
|
|
15582
15732
|
this.firstAction.onAction = () => {
|
|
15583
15733
|
this.posInList = 0;
|
|
@@ -15745,10 +15895,9 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15745
15895
|
this.recordingFile = null;
|
|
15746
15896
|
this.posInList = null;
|
|
15747
15897
|
this.updateActions();
|
|
15748
|
-
|
|
15749
|
-
|
|
15750
|
-
|
|
15751
|
-
this.recordingFileService.fetchSprRecordingFile(audioContext, rfId).subscribe(value => {
|
|
15898
|
+
this.audioFetching = true;
|
|
15899
|
+
this.recordingFileService.fetchSprRecordingFile(rfId).subscribe({
|
|
15900
|
+
next: value => {
|
|
15752
15901
|
this.audioFetching = false;
|
|
15753
15902
|
this.status = 'Audio file loaded.';
|
|
15754
15903
|
let clip = null;
|
|
@@ -15786,11 +15935,11 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15786
15935
|
}
|
|
15787
15936
|
this.audioClip = clip;
|
|
15788
15937
|
this.loadedRecfile();
|
|
15789
|
-
}, error1 => {
|
|
15938
|
+
}, error: error1 => {
|
|
15790
15939
|
this.audioFetching = false;
|
|
15791
15940
|
this.status = 'Error loading audio file!';
|
|
15792
|
-
}
|
|
15793
|
-
}
|
|
15941
|
+
}
|
|
15942
|
+
});
|
|
15794
15943
|
}
|
|
15795
15944
|
loadedRecfile() {
|
|
15796
15945
|
if (this.recordingFile && !this.sessionId) {
|
|
@@ -15816,7 +15965,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15816
15965
|
this.lastAction.disabled = (this.posInList == null || itemCnt == null || this.posInList >= itemCnt - 1);
|
|
15817
15966
|
}
|
|
15818
15967
|
loadSession(sessionId) {
|
|
15819
|
-
// load session and recording file
|
|
15968
|
+
// load session and recording file metadata only when on init and when session changes
|
|
15820
15969
|
if (sessionId != this.sessionId) {
|
|
15821
15970
|
// tell UI that we are working...
|
|
15822
15971
|
this.naviInfoLoading = true;
|
|
@@ -15854,7 +16003,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15854
16003
|
else {
|
|
15855
16004
|
// rec file with itemcode already exists, add (push) this version ...
|
|
15856
16005
|
exRfsForIc.push(rfd);
|
|
15857
|
-
//
|
|
16006
|
+
// ... and sort latest version (highest version number) to lowest index
|
|
15858
16007
|
exRfsForIc.sort((rfd1, rfd2) => {
|
|
15859
16008
|
return rfd2.version - rfd1.version;
|
|
15860
16009
|
});
|
|
@@ -15908,7 +16057,7 @@ class RecordingFileViewComponent extends AudioDisplayPlayer {
|
|
|
15908
16057
|
}
|
|
15909
16058
|
}
|
|
15910
16059
|
}
|
|
15911
|
-
RecordingFileViewComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileViewComponent, deps: [{ token: RecordingFileService }, { token: RecordingService }, { token: SessionService }, { token:
|
|
16060
|
+
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 });
|
|
15912
16061
|
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: `
|
|
15913
16062
|
|
|
15914
16063
|
<audio-display-scroll-pane #audioDisplayScrollPane></audio-display-scroll-pane>
|
|
@@ -15947,7 +16096,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
15947
16096
|
<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>
|
|
15948
16097
|
</div>
|
|
15949
16098
|
`, 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"] }]
|
|
15950
|
-
}], ctorParameters: function () { return [{ type: RecordingFileService }, { type: RecordingService }, { type: SessionService }, { type:
|
|
16099
|
+
}], 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: [{
|
|
15951
16100
|
type: ViewChild,
|
|
15952
16101
|
args: [AudioDisplayScrollPane]
|
|
15953
16102
|
}] } });
|
|
@@ -16013,27 +16162,28 @@ class RecordingFileUI extends RecordingFileViewComponent {
|
|
|
16013
16162
|
sf = s.startFrame;
|
|
16014
16163
|
ef = s.endFrame;
|
|
16015
16164
|
}
|
|
16016
|
-
this.recordingFileService.saveEditSelection(this.recordingFile.recordingFileId, sr, sf, ef).subscribe((value) => {
|
|
16017
|
-
|
|
16018
|
-
|
|
16019
|
-
|
|
16020
|
-
|
|
16021
|
-
|
|
16022
|
-
|
|
16023
|
-
|
|
16024
|
-
|
|
16025
|
-
|
|
16026
|
-
|
|
16027
|
-
|
|
16028
|
-
|
|
16029
|
-
|
|
16030
|
-
|
|
16165
|
+
this.recordingFileService.saveEditSelection(this.recordingFile.recordingFileId, sr, sf, ef).subscribe({ next: (value) => { },
|
|
16166
|
+
error: () => {
|
|
16167
|
+
this.dialog.open(MessageDialog, {
|
|
16168
|
+
data: {
|
|
16169
|
+
type: 'error',
|
|
16170
|
+
title: 'Save selection edit error',
|
|
16171
|
+
msg: "Could not save edit selection to WikiSpeech server!",
|
|
16172
|
+
advice: "Please check network connection and server state."
|
|
16173
|
+
}
|
|
16174
|
+
});
|
|
16175
|
+
}, complete: () => {
|
|
16176
|
+
// Or use returned selection value from server?
|
|
16177
|
+
this.savedEditSelection = s;
|
|
16178
|
+
this.editSaved = true;
|
|
16179
|
+
this.snackBar.open('Selection edit saved successfully.', 'OK', { duration: 1500 });
|
|
16180
|
+
}
|
|
16031
16181
|
});
|
|
16032
16182
|
}
|
|
16033
16183
|
}
|
|
16034
16184
|
}
|
|
16035
16185
|
}
|
|
16036
|
-
RecordingFileUI.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingFileUI, deps: [{ token: RecordingFileService }, { token: RecordingService }, { token: SessionService }, { token:
|
|
16186
|
+
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 });
|
|
16037
16187
|
RecordingFileUI.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: RecordingFileUI, selector: "app-audiodisplayplayer", usesInheritance: true, ngImport: i0, template: `
|
|
16038
16188
|
<h1>Recording file editing</h1>
|
|
16039
16189
|
<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>
|
|
@@ -16078,7 +16228,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
16078
16228
|
|
|
16079
16229
|
<button mat-raised-button color="accent" (click)="applySelection()" [disabled]="editSaved">{{this.applyButtonText()}}</button>
|
|
16080
16230
|
`, 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"] }]
|
|
16081
|
-
}], ctorParameters: function () { return [{ type: RecordingFileService }, { type: RecordingService }, { type: SessionService }, { type:
|
|
16231
|
+
}], 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 }]; } });
|
|
16082
16232
|
|
|
16083
16233
|
class MediaUtils {
|
|
16084
16234
|
static toMediaTime(timeInSeconds) {
|
|
@@ -16216,7 +16366,7 @@ RecordingList.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version:
|
|
|
16216
16366
|
</mat-card-content>
|
|
16217
16367
|
</mat-card>
|
|
16218
16368
|
|
|
16219
|
-
`, 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$
|
|
16369
|
+
`, 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" }] });
|
|
16220
16370
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecordingList, decorators: [{
|
|
16221
16371
|
type: Component,
|
|
16222
16372
|
args: [{ selector: 'app-recordinglist', template: `
|
|
@@ -16297,7 +16447,7 @@ class RecorderCombiPane extends ResponsiveComponent {
|
|
|
16297
16447
|
this.recordingListComp.selectTop();
|
|
16298
16448
|
}
|
|
16299
16449
|
}
|
|
16300
|
-
RecorderCombiPane.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: RecorderCombiPane, deps: [{ token: i1$
|
|
16450
|
+
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 });
|
|
16301
16451
|
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: `
|
|
16302
16452
|
<div class="scrollList">
|
|
16303
16453
|
<app-recordinglist [selectedRecordingFile]="selectedRecordingFile" [selectDisabled]="selectDisabled" (selectedRecordingFileChanged)="selectRecordingFile($event)"></app-recordinglist>
|
|
@@ -16326,7 +16476,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
16326
16476
|
[playStopAction]="playStopAction"></app-audiodisplay>
|
|
16327
16477
|
</div>
|
|
16328
16478
|
`, 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"] }]
|
|
16329
|
-
}], ctorParameters: function () { return [{ type: i1$
|
|
16479
|
+
}], ctorParameters: function () { return [{ type: i1$2.BreakpointObserver }]; }, propDecorators: { recordingListComp: [{
|
|
16330
16480
|
type: ViewChild,
|
|
16331
16481
|
args: [RecordingList]
|
|
16332
16482
|
}], selectDisabled: [{
|
|
@@ -16353,11 +16503,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
16353
16503
|
}] } });
|
|
16354
16504
|
|
|
16355
16505
|
class AudioRecorder extends BasicRecorder {
|
|
16356
|
-
constructor(bpo, changeDetectorRef, renderer,
|
|
16506
|
+
constructor(bpo, changeDetectorRef, renderer, dialog, sessionService, recFileService, uploader, config) {
|
|
16357
16507
|
super(bpo, changeDetectorRef, dialog, sessionService, uploader, config);
|
|
16358
16508
|
this.bpo = bpo;
|
|
16359
16509
|
this.renderer = renderer;
|
|
16360
|
-
this.route = route;
|
|
16361
16510
|
this.recFileService = recFileService;
|
|
16362
16511
|
this.uploader = uploader;
|
|
16363
16512
|
this._project = null;
|
|
@@ -16402,38 +16551,17 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16402
16551
|
this.transportActions.nextAction.disabled = true;
|
|
16403
16552
|
this.transportActions.pauseAction.disabled = true;
|
|
16404
16553
|
this.playStartAction.disabled = true;
|
|
16405
|
-
|
|
16406
|
-
|
|
16407
|
-
|
|
16408
|
-
|
|
16409
|
-
|
|
16410
|
-
|
|
16411
|
-
this.
|
|
16412
|
-
let errMsg = 'Unknown error';
|
|
16413
|
-
if (err instanceof Error) {
|
|
16414
|
-
errMsg = err.message;
|
|
16415
|
-
}
|
|
16416
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
16417
|
-
this.statusAlertType = 'error';
|
|
16418
|
-
this.dialog.open(MessageDialog, {
|
|
16419
|
-
data: {
|
|
16420
|
-
type: 'error',
|
|
16421
|
-
title: 'Error',
|
|
16422
|
-
msg: errMsg,
|
|
16423
|
-
advice: 'Please use a supported browser.',
|
|
16424
|
-
}
|
|
16425
|
-
});
|
|
16426
|
-
return;
|
|
16427
|
-
}
|
|
16428
|
-
if (context) {
|
|
16429
|
-
console.info("State of audio context: " + context.state);
|
|
16554
|
+
this.ac = new AudioCapture();
|
|
16555
|
+
if (this.ac) {
|
|
16556
|
+
this.transportActions.startAction.onAction = () => this.startItem();
|
|
16557
|
+
this.ac.listener = this;
|
|
16558
|
+
this.configureStreamCaptureStream();
|
|
16559
|
+
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
16560
|
+
//this.ac.listDevices();
|
|
16430
16561
|
}
|
|
16431
16562
|
else {
|
|
16432
|
-
|
|
16433
|
-
|
|
16434
|
-
if (!context || !navigator.mediaDevices) {
|
|
16435
|
-
this.status = 5 /* ERROR */;
|
|
16436
|
-
let errMsg = 'Browser does not support Media streams!';
|
|
16563
|
+
this.transportActions.startAction.disabled = true;
|
|
16564
|
+
let errMsg = 'Browser does not support Media/Audio API!';
|
|
16437
16565
|
this.statusMsg = 'ERROR: ' + errMsg;
|
|
16438
16566
|
this.statusAlertType = 'error';
|
|
16439
16567
|
this.dialog.open(MessageDialog, {
|
|
@@ -16446,36 +16574,10 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16446
16574
|
});
|
|
16447
16575
|
return;
|
|
16448
16576
|
}
|
|
16449
|
-
|
|
16450
|
-
|
|
16451
|
-
|
|
16452
|
-
|
|
16453
|
-
this.transportActions.startAction.onAction = () => this.startItem();
|
|
16454
|
-
this.ac.listener = this;
|
|
16455
|
-
this.configureStreamCaptureStream();
|
|
16456
|
-
// Don't list the devices here. If we do not have audio permissions we only get anonymized devices without labels.
|
|
16457
|
-
//this.ac.listDevices();
|
|
16458
|
-
}
|
|
16459
|
-
else {
|
|
16460
|
-
this.transportActions.startAction.disabled = true;
|
|
16461
|
-
let errMsg = 'Browser does not support Media/Audio API!';
|
|
16462
|
-
this.statusMsg = 'ERROR: ' + errMsg;
|
|
16463
|
-
this.statusAlertType = 'error';
|
|
16464
|
-
this.dialog.open(MessageDialog, {
|
|
16465
|
-
data: {
|
|
16466
|
-
type: 'error',
|
|
16467
|
-
title: 'Error',
|
|
16468
|
-
msg: errMsg,
|
|
16469
|
-
advice: 'Please use a supported browser.',
|
|
16470
|
-
}
|
|
16471
|
-
});
|
|
16472
|
-
return;
|
|
16473
|
-
}
|
|
16474
|
-
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
16475
|
-
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
16476
|
-
//this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
16477
|
-
this.playStartAction.onAction = () => { var _a; return (_a = this.controlAudioPlayer) === null || _a === void 0 ? void 0 : _a.start(); };
|
|
16478
|
-
}
|
|
16577
|
+
this.transportActions.stopAction.onAction = () => this.stopItem();
|
|
16578
|
+
this.transportActions.nextAction.onAction = () => this.stopItem();
|
|
16579
|
+
//this.transportActions.pauseAction.onAction = () => this.pauseItem();
|
|
16580
|
+
this.playStartAction.onAction = () => { var _a; return (_a = this.controlAudioPlayer) === null || _a === void 0 ? void 0 : _a.start(); };
|
|
16479
16581
|
this.uploader.listener = (ue) => {
|
|
16480
16582
|
this.uploadUpdate(ue);
|
|
16481
16583
|
};
|
|
@@ -16584,6 +16686,9 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16584
16686
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
16585
16687
|
console.info("Project requested recording channel count: " + chCnt);
|
|
16586
16688
|
this.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
16689
|
+
if (project.allowEchoCancellation !== undefined) {
|
|
16690
|
+
this.allowEchoCancellation = project.allowEchoCancellation;
|
|
16691
|
+
}
|
|
16587
16692
|
if (project.chunkedRecording === true) {
|
|
16588
16693
|
this.uploadChunkSizeSeconds = BasicRecorder.DEFAULT_CHUNK_SIZE_SECONDS;
|
|
16589
16694
|
}
|
|
@@ -16784,7 +16889,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16784
16889
|
}
|
|
16785
16890
|
else {
|
|
16786
16891
|
//console.debug("Fetch audio and store to indexed db...");
|
|
16787
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileIndDbAudioBuffer(this.
|
|
16892
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileIndDbAudioBuffer(this._persistentAudioStorageTarget, this._session.project, rf).subscribe({
|
|
16788
16893
|
next: (iab) => {
|
|
16789
16894
|
//console.debug("Sessionmanager: Received inddb audio buffer: "+iab);
|
|
16790
16895
|
nextIab = iab;
|
|
@@ -16827,7 +16932,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16827
16932
|
// Fetch chunked audio buffer from network
|
|
16828
16933
|
let nextNetAb = null;
|
|
16829
16934
|
//console.debug("Fetch chunked audio from network");
|
|
16830
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileNetAudioBuffer(this.
|
|
16935
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileNetAudioBuffer(this._session.project, rf).subscribe({
|
|
16831
16936
|
next: (netAb) => {
|
|
16832
16937
|
//console.debug("Sessionmanager: Received net audio buffer: "+netAb);
|
|
16833
16938
|
nextNetAb = netAb;
|
|
@@ -16872,7 +16977,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16872
16977
|
// Fetch chunked array audio buffer
|
|
16873
16978
|
let nextAab = null;
|
|
16874
16979
|
//console.debug("Fetch audio and store to (chunked) array buffer...");
|
|
16875
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileArrayAudioBuffer(this.
|
|
16980
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileArrayAudioBuffer(this._session.project, rf).subscribe({
|
|
16876
16981
|
next: (aab) => {
|
|
16877
16982
|
nextAab = aab;
|
|
16878
16983
|
},
|
|
@@ -16909,7 +17014,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
16909
17014
|
});
|
|
16910
17015
|
}
|
|
16911
17016
|
else {
|
|
16912
|
-
this.audioFetchSubscription = this.recFileService.fetchRecordingFileAudioBuffer(this.
|
|
17017
|
+
this.audioFetchSubscription = this.recFileService.fetchRecordingFileAudioBuffer(this._session.project, rf).subscribe({
|
|
16913
17018
|
next: ab => {
|
|
16914
17019
|
this.liveLevelDisplayState = State.READY;
|
|
16915
17020
|
let fabDh = null;
|
|
@@ -17049,7 +17154,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17049
17154
|
this.transportActions.pauseAction.disabled = true;
|
|
17050
17155
|
this.statusAlertType = 'info';
|
|
17051
17156
|
this.statusMsg = 'Recorded.';
|
|
17052
|
-
let
|
|
17157
|
+
let ab = null;
|
|
17053
17158
|
if (this.ac) {
|
|
17054
17159
|
let adh = null;
|
|
17055
17160
|
let as = null;
|
|
@@ -17081,7 +17186,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17081
17186
|
const sr = this.ac.currentSampleRate;
|
|
17082
17187
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
17083
17188
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
17084
|
-
let netAs = new NetAudioBuffer(this.
|
|
17189
|
+
let netAs = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
17085
17190
|
as = netAs;
|
|
17086
17191
|
if (this.uploadSet) {
|
|
17087
17192
|
this.uploadSet.onDone = (uploadSet) => {
|
|
@@ -17128,7 +17233,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17128
17233
|
const sr = this.ac.currentSampleRate;
|
|
17129
17234
|
const chFl = sr * RecordingService.DEFAULT_CHUNKED_DOWNLOAD_SECONDS;
|
|
17130
17235
|
//console.debug("stopped(): rfID: "+this._recordingFile?.recordingFileId+", net ab url: " + burl+", frames: "+this.ac.framesRecorded+", sample rate: "+sr);
|
|
17131
|
-
let netAs = new NetAudioBuffer(this.
|
|
17236
|
+
let netAs = new NetAudioBuffer(this.recFileService, burl, this.ac.channelCount, sr, chFl, this.ac.framesRecorded, rUUID, chFl);
|
|
17132
17237
|
as = netAs;
|
|
17133
17238
|
if (this.uploadSet) {
|
|
17134
17239
|
this.uploadSet.onDone = (uploadSet) => {
|
|
@@ -17147,7 +17252,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17147
17252
|
as = this.ac.audioBufferArray();
|
|
17148
17253
|
}
|
|
17149
17254
|
else {
|
|
17150
|
-
|
|
17255
|
+
ab = this.ac.audioBuffer();
|
|
17151
17256
|
if (ab) {
|
|
17152
17257
|
as = new AudioBufferSource(ab);
|
|
17153
17258
|
}
|
|
@@ -17167,7 +17272,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17167
17272
|
RecordingFileUtils.setAudioData(rf, adh);
|
|
17168
17273
|
this.recorderCombiPane.addRecFile(rf);
|
|
17169
17274
|
// Upload if upload enabled and not in chunked upload mode
|
|
17170
|
-
if (this.enableUploadRecordings && this._uploadChunkSizeSeconds === null && rf != null &&
|
|
17275
|
+
if (this.enableUploadRecordings && this._uploadChunkSizeSeconds === null && AudioStorageType.MEM_ENTIRE === this._clientAudioStorageType && rf != null && ab != null) {
|
|
17171
17276
|
let apiEndPoint = '';
|
|
17172
17277
|
if (this.config && this.config.apiEndPoint) {
|
|
17173
17278
|
apiEndPoint = this.config.apiEndPoint;
|
|
@@ -17182,7 +17287,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17182
17287
|
// TODO duplicate conversion for manual download
|
|
17183
17288
|
this.processingRecording = true;
|
|
17184
17289
|
let ww = new WavWriter();
|
|
17185
|
-
ww.writeAsync(
|
|
17290
|
+
ww.writeAsync(ab, (wavFile) => {
|
|
17186
17291
|
this.postRecordingMultipart(wavFile, recUrl, rf);
|
|
17187
17292
|
this.processingRecording = false;
|
|
17188
17293
|
this.updateWakeLock();
|
|
@@ -17267,7 +17372,7 @@ class AudioRecorder extends BasicRecorder {
|
|
|
17267
17372
|
}
|
|
17268
17373
|
}
|
|
17269
17374
|
}
|
|
17270
|
-
AudioRecorder.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioRecorder, deps: [{ token: i1$
|
|
17375
|
+
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 });
|
|
17271
17376
|
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: `
|
|
17272
17377
|
<app-warningbar [show]="isTestSession()" warningText="Test recording only!"></app-warningbar>
|
|
17273
17378
|
<app-warningbar [show]="isDefaultAudioTestSession()"
|
|
@@ -17389,7 +17494,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
17389
17494
|
</div>
|
|
17390
17495
|
`, 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"] }]
|
|
17391
17496
|
}], ctorParameters: function () {
|
|
17392
|
-
return [{ type: i1$
|
|
17497
|
+
return [{ type: i1$2.BreakpointObserver }, { type: i0.ChangeDetectorRef }, { type: i0.Renderer2 }, { type: i1$3.MatDialog }, { type: SessionService }, { type: RecordingService }, { type: SpeechRecorderUploader }, { type: SpeechRecorderConfig, decorators: [{
|
|
17393
17498
|
type: Inject,
|
|
17394
17499
|
args: [SPEECHRECORDER_CONFIG]
|
|
17395
17500
|
}] }];
|
|
@@ -17421,11 +17526,7 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
17421
17526
|
this.uploader = uploader;
|
|
17422
17527
|
}
|
|
17423
17528
|
ngOnInit() {
|
|
17424
|
-
|
|
17425
|
-
let audioContext = AudioContextProvider.audioContextInstance();
|
|
17426
|
-
if (audioContext) {
|
|
17427
|
-
this.controlAudioPlayer = new AudioPlayer(audioContext, this.ar);
|
|
17428
|
-
}
|
|
17529
|
+
this.controlAudioPlayer = new AudioPlayer(this.ar);
|
|
17429
17530
|
this.ar.controlAudioPlayer = this.controlAudioPlayer;
|
|
17430
17531
|
//TODO Duplicate code in SpeechRecorderComponent
|
|
17431
17532
|
window.addEventListener('beforeunload', (e) => {
|
|
@@ -17435,7 +17536,7 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
17435
17536
|
}
|
|
17436
17537
|
else {
|
|
17437
17538
|
// all this attempts to customize the message do not work anymore (for security reasons)!!
|
|
17438
|
-
|
|
17539
|
+
const message = "Please do not leave the page, until all recordings are uploaded!";
|
|
17439
17540
|
alert(message);
|
|
17440
17541
|
e = e || window.event;
|
|
17441
17542
|
if (e) {
|
|
@@ -17535,7 +17636,7 @@ class AudioRecorderComponent extends RecorderComponent {
|
|
|
17535
17636
|
return this.dataSaved && !this.ar.isActive();
|
|
17536
17637
|
}
|
|
17537
17638
|
}
|
|
17538
|
-
AudioRecorderComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: AudioRecorderComponent, deps: [{ token:
|
|
17639
|
+
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 });
|
|
17539
17640
|
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: `
|
|
17540
17641
|
<app-audiorecorder [projectName]="_project?.name" [dataSaved]="dataSaved"></app-audiorecorder>
|
|
17541
17642
|
`, 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"] }] });
|
|
@@ -17544,7 +17645,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
17544
17645
|
args: [{ selector: 'app-audiorecorder-comp', providers: [SessionService], template: `
|
|
17545
17646
|
<app-audiorecorder [projectName]="_project?.name" [dataSaved]="dataSaved"></app-audiorecorder>
|
|
17546
17647
|
`, styles: [":host{flex:2;display:flex;height:100%;flex-direction:column;min-height:0}\n"] }]
|
|
17547
|
-
}], ctorParameters: function () { return [{ type:
|
|
17648
|
+
}], ctorParameters: function () { return [{ type: i4$2.ActivatedRoute }, { type: i4$2.Router }, { type: i0.ChangeDetectorRef }, { type: SessionService }, { type: ProjectService }, { type: SpeechRecorderUploader }]; }, propDecorators: { ar: [{
|
|
17548
17649
|
type: ViewChild,
|
|
17549
17650
|
args: [AudioRecorder, { static: true }]
|
|
17550
17651
|
}] } });
|
|
@@ -17580,7 +17681,7 @@ class SpeechrecorderngModule {
|
|
|
17580
17681
|
}
|
|
17581
17682
|
SpeechrecorderngModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
|
|
17582
17683
|
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,
|
|
17583
|
-
ProgressDisplay, RecordingItemDisplay, RecordingItemControls, UploadStatus, TransportPanel, WakeLockIndicator, ReadyStateIndicator, ControlPanel, WarningBar, AudioRecorder, SessionManager, MessageDialog, SessionFinishedDialog, SpeechrecorderngComponent, AudioRecorderComponent, RecordingFileViewComponent, RecordingFileUI, ScrollIntoViewDirective, RecordingFileNaviComponent, RecordingFileMetaComponent, RecordingList, RecorderCombiPane, AudioRecorder], imports: [
|
|
17684
|
+
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] });
|
|
17584
17685
|
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] });
|
|
17585
17686
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: SpeechrecorderngModule, decorators: [{
|
|
17586
17687
|
type: NgModule,
|
|
@@ -17593,7 +17694,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImpo
|
|
|
17593
17694
|
}]
|
|
17594
17695
|
}] });
|
|
17595
17696
|
|
|
17596
|
-
const VERSION = '3.
|
|
17697
|
+
const VERSION = '3.6.0';
|
|
17597
17698
|
|
|
17598
17699
|
/*
|
|
17599
17700
|
* Public API Surface of speechrecorderng
|