speechrecorderng 2.18.13 → 2.19.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/bundles/speechrecorderng.umd.js +558 -104
- package/bundles/speechrecorderng.umd.js.map +1 -1
- package/esm2015/lib/audio/capture/capture.js +262 -69
- package/esm2015/lib/io/stream.js +8 -7
- package/esm2015/lib/speechrecorder/project/project.js +27 -1
- package/esm2015/lib/speechrecorder/session/sessionmanager.js +35 -8
- package/esm2015/lib/speechrecorderng.component.js +2 -1
- package/esm2015/lib/spr.module.version.js +2 -2
- package/esm2015/lib/ui/livelevel_display.js +24 -4
- package/esm2015/lib/utils/ua-parser.js +166 -0
- package/fesm2015/speechrecorderng.js +526 -95
- package/fesm2015/speechrecorderng.js.map +1 -1
- package/lib/audio/capture/capture.d.ts +6 -3
- package/lib/speechrecorder/project/project.d.ts +25 -0
- package/lib/speechrecorder/session/sessionmanager.d.ts +7 -3
- package/lib/spr.module.version.d.ts +1 -1
- package/lib/ui/livelevel_display.d.ts +4 -1
- package/lib/utils/ua-parser.d.ts +40 -0
- package/package.json +3 -3
|
@@ -720,15 +720,309 @@
|
|
|
720
720
|
}());
|
|
721
721
|
AudioPlayer.DEFAULT_BUFSIZE = 8192;
|
|
722
722
|
|
|
723
|
-
var
|
|
724
|
-
function
|
|
725
|
-
this.
|
|
726
|
-
this.
|
|
723
|
+
var UserAgentComponent = /** @class */ (function () {
|
|
724
|
+
function UserAgentComponent(name, version, comment) {
|
|
725
|
+
this.name = name;
|
|
726
|
+
this.version = version;
|
|
727
|
+
this.comment = comment;
|
|
727
728
|
}
|
|
728
|
-
|
|
729
|
+
UserAgentComponent.prototype.toString = function () {
|
|
730
|
+
var s = '[' + this.name + ']';
|
|
731
|
+
if (this.version) {
|
|
732
|
+
s = s + ' [' + this.version + ']';
|
|
733
|
+
}
|
|
734
|
+
if (this.comment) {
|
|
735
|
+
s = s + ' [' + this.comment + ']';
|
|
736
|
+
}
|
|
737
|
+
return s;
|
|
738
|
+
};
|
|
739
|
+
return UserAgentComponent;
|
|
740
|
+
}());
|
|
741
|
+
var NAME_FIREFOX = 'Firefox';
|
|
742
|
+
var NAME_CHROME = 'Chrome';
|
|
743
|
+
var NAME_SAFARI = 'Safari';
|
|
744
|
+
var NAME_EDGE = 'Edge';
|
|
745
|
+
var Browser$1;
|
|
746
|
+
(function (Browser) {
|
|
747
|
+
Browser["Firefox"] = "Firefox";
|
|
748
|
+
Browser["Chrome"] = "Chrome";
|
|
749
|
+
Browser["Safari"] = "Safari";
|
|
750
|
+
Browser["Edge"] = "Edge";
|
|
751
|
+
})(Browser$1 || (Browser$1 = {}));
|
|
752
|
+
var OS_WINDOWS = 'Windows';
|
|
753
|
+
var OS_ANDROID = 'Android';
|
|
754
|
+
var Platform$1;
|
|
755
|
+
(function (Platform) {
|
|
756
|
+
Platform["Windows"] = "Windows";
|
|
757
|
+
Platform["Android"] = "Android";
|
|
758
|
+
Platform["macOS"] = "MAC OS X";
|
|
759
|
+
})(Platform$1 || (Platform$1 = {}));
|
|
760
|
+
var UserAgent = /** @class */ (function () {
|
|
761
|
+
function UserAgent(_detectedPlatform, _detectedBrowser) {
|
|
762
|
+
this._detectedPlatform = _detectedPlatform;
|
|
763
|
+
this._detectedBrowser = _detectedBrowser;
|
|
764
|
+
}
|
|
765
|
+
Object.defineProperty(UserAgent.prototype, "detectedBrowser", {
|
|
766
|
+
get: function () {
|
|
767
|
+
return this._detectedBrowser;
|
|
768
|
+
},
|
|
769
|
+
enumerable: false,
|
|
770
|
+
configurable: true
|
|
771
|
+
});
|
|
772
|
+
Object.defineProperty(UserAgent.prototype, "detectedPlatform", {
|
|
773
|
+
get: function () {
|
|
774
|
+
return this._detectedPlatform;
|
|
775
|
+
},
|
|
776
|
+
enumerable: false,
|
|
777
|
+
configurable: true
|
|
778
|
+
});
|
|
779
|
+
return UserAgent;
|
|
780
|
+
}());
|
|
781
|
+
var UserAgentBuilder = /** @class */ (function () {
|
|
782
|
+
function UserAgentBuilder() {
|
|
783
|
+
this.comps = new Array();
|
|
784
|
+
}
|
|
785
|
+
UserAgentBuilder.prototype.build = function () {
|
|
786
|
+
// // @ts-ignore
|
|
787
|
+
// if(navigator.userAgentData){
|
|
788
|
+
// // maybe we can use this in the future
|
|
789
|
+
// console.info("Browser provides userAgentData:");
|
|
790
|
+
//
|
|
791
|
+
// console.info("Brands:");
|
|
792
|
+
// // @ts-ignore
|
|
793
|
+
// navigator.userAgentData.brands.forEach((br=>{
|
|
794
|
+
// console.info(br.brand +" "+br.version);
|
|
795
|
+
// }))
|
|
796
|
+
// // @ts-ignore
|
|
797
|
+
// console.info("Platform: "+navigator.userAgentData.platform);
|
|
798
|
+
// // @ts-ignore
|
|
799
|
+
// console.info("Mobile:"+navigator.userAgentData.mobile);
|
|
800
|
+
// // @ts-ignore
|
|
801
|
+
// //console.info(navigator.userAgentData.toJSON());
|
|
802
|
+
// }else {
|
|
803
|
+
// console.info("Browser does not provide userAgentData.");
|
|
804
|
+
// }
|
|
805
|
+
var ua = navigator.userAgent;
|
|
806
|
+
this.comps = new Array();
|
|
807
|
+
var pp = 0;
|
|
808
|
+
while (pp < ua.length) {
|
|
809
|
+
//parse name/version
|
|
810
|
+
var name = null;
|
|
811
|
+
var version = null;
|
|
812
|
+
var comment = void 0;
|
|
813
|
+
var blPos = ua.indexOf(' ', pp);
|
|
814
|
+
var prt = void 0;
|
|
815
|
+
if (blPos == -1) {
|
|
816
|
+
prt = ua.substr(pp);
|
|
817
|
+
pp += prt.length;
|
|
818
|
+
}
|
|
819
|
+
else {
|
|
820
|
+
prt = ua.substr(pp, blPos - pp);
|
|
821
|
+
pp = blPos + 1;
|
|
822
|
+
}
|
|
823
|
+
var sepPos = prt.indexOf('/');
|
|
824
|
+
if (sepPos > 0) {
|
|
825
|
+
name = prt.substr(0, sepPos);
|
|
826
|
+
version = prt.substr(sepPos + 1);
|
|
827
|
+
}
|
|
828
|
+
else {
|
|
829
|
+
name = prt;
|
|
830
|
+
}
|
|
831
|
+
while (ua[pp] === ' ' && pp < ua.length) {
|
|
832
|
+
pp++;
|
|
833
|
+
}
|
|
834
|
+
if (ua[pp] === '(') {
|
|
835
|
+
pp++;
|
|
836
|
+
var commEnd = ua.indexOf(')', pp);
|
|
837
|
+
comment = ua.substr(pp, commEnd - pp);
|
|
838
|
+
pp = commEnd + 1;
|
|
839
|
+
}
|
|
840
|
+
while (ua[pp] === ' ' && pp < ua.length) {
|
|
841
|
+
pp++;
|
|
842
|
+
}
|
|
843
|
+
this.comps.push(new UserAgentComponent(name, version, comment));
|
|
844
|
+
}
|
|
845
|
+
var detPlatf = null;
|
|
846
|
+
if (this.runsOnOS(Platform$1.Android)) {
|
|
847
|
+
detPlatf = Platform$1.Android;
|
|
848
|
+
}
|
|
849
|
+
else if (this.runsOnOS(Platform$1.Windows)) {
|
|
850
|
+
detPlatf = Platform$1.Windows;
|
|
851
|
+
}
|
|
852
|
+
else if (this.runsOnOS(Platform$1.macOS)) {
|
|
853
|
+
detPlatf = Platform$1.macOS;
|
|
854
|
+
}
|
|
855
|
+
var detBr = null;
|
|
856
|
+
if (this.matchesBrowser(Browser$1.Firefox)) {
|
|
857
|
+
detBr = Browser$1.Firefox;
|
|
858
|
+
}
|
|
859
|
+
else if (this.matchesBrowser(Browser$1.Chrome)) {
|
|
860
|
+
detBr = Browser$1.Chrome;
|
|
861
|
+
}
|
|
862
|
+
else if (this.matchesBrowser(Browser$1.Safari)) {
|
|
863
|
+
detBr = Browser$1.Safari;
|
|
864
|
+
}
|
|
865
|
+
this.userAgent = new UserAgent(detPlatf, detBr);
|
|
866
|
+
};
|
|
867
|
+
UserAgentBuilder.prototype.matchesBrowser = function (browserName) {
|
|
868
|
+
for (var ci = 0; ci < this.comps.length; ci++) {
|
|
869
|
+
var bn = this.comps[ci].name;
|
|
870
|
+
var bnRe = new RegExp(browserName, 'i');
|
|
871
|
+
if (bn.match(bnRe)) {
|
|
872
|
+
return true;
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
return false;
|
|
876
|
+
};
|
|
877
|
+
UserAgentBuilder.prototype.runsOnOS = function (os) {
|
|
878
|
+
for (var ci = 0; ci < this.comps.length; ci++) {
|
|
879
|
+
var cc = this.comps[ci].comment;
|
|
880
|
+
if (cc) {
|
|
881
|
+
var osRe = new RegExp(os, 'i');
|
|
882
|
+
if (cc.match(osRe)) {
|
|
883
|
+
return true;
|
|
884
|
+
}
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
return false;
|
|
888
|
+
};
|
|
889
|
+
UserAgentBuilder.userAgent = function () {
|
|
890
|
+
if (!this.instance) {
|
|
891
|
+
this.instance = new UserAgentBuilder();
|
|
892
|
+
}
|
|
893
|
+
this.instance.build();
|
|
894
|
+
return this.instance.userAgent;
|
|
895
|
+
};
|
|
896
|
+
return UserAgentBuilder;
|
|
729
897
|
}());
|
|
898
|
+
UserAgentBuilder.instance = undefined;
|
|
899
|
+
|
|
900
|
+
var ConstraintType;
|
|
901
|
+
(function (ConstraintType) {
|
|
902
|
+
ConstraintType["Exact"] = "EXACT";
|
|
903
|
+
ConstraintType["Ideal"] = "IDEAL";
|
|
904
|
+
})(ConstraintType || (ConstraintType = {}));
|
|
905
|
+
;
|
|
906
|
+
var Platform;
|
|
907
|
+
(function (Platform) {
|
|
908
|
+
Platform["Linux"] = "LINUX";
|
|
909
|
+
Platform["macOS"] = "MACOS";
|
|
910
|
+
Platform["Windows"] = "WINDOWS";
|
|
911
|
+
Platform["Android"] = "ANDROID";
|
|
912
|
+
})(Platform || (Platform = {}));
|
|
913
|
+
var BrowserBase;
|
|
914
|
+
(function (BrowserBase) {
|
|
915
|
+
BrowserBase["Chromium"] = "CHROMIUM";
|
|
916
|
+
})(BrowserBase || (BrowserBase = {}));
|
|
917
|
+
;
|
|
918
|
+
var Browser;
|
|
919
|
+
(function (Browser) {
|
|
920
|
+
Browser["Firefox"] = "FIREFOX";
|
|
921
|
+
Browser["Chromium"] = "CHROMIUM";
|
|
922
|
+
Browser["Chrome"] = "CHROME";
|
|
923
|
+
Browser["Edge"] = "EDGE";
|
|
924
|
+
Browser["Opera"] = "OPERA";
|
|
925
|
+
})(Browser || (Browser = {}));
|
|
926
|
+
var ProjectUtil = /** @class */ (function () {
|
|
927
|
+
function ProjectUtil() {
|
|
928
|
+
}
|
|
929
|
+
ProjectUtil.audioChannelCount = function (project) {
|
|
930
|
+
var chs = ProjectUtil.DEFAULT_AUDIO_CHANNEL_COUNT;
|
|
931
|
+
if (project.mediaCaptureFormat) {
|
|
932
|
+
chs = project.mediaCaptureFormat.audioChannelCount;
|
|
933
|
+
}
|
|
934
|
+
else if (project.audioFormat) {
|
|
935
|
+
chs = project.audioFormat.channels;
|
|
936
|
+
}
|
|
937
|
+
return chs;
|
|
938
|
+
};
|
|
939
|
+
return ProjectUtil;
|
|
940
|
+
}());
|
|
941
|
+
ProjectUtil.DEFAULT_AUDIO_CHANNEL_COUNT = 2;
|
|
942
|
+
|
|
943
|
+
var CHROME_ACTIVATE_ECHO_CANCELLATION_WITH_AGC = false;
|
|
944
|
+
var DEBUG_TRACE_LEVEL = 0;
|
|
945
|
+
var ENABLE_AUDIO_WORKLET = true;
|
|
946
|
+
// Super dirty way to load this module
|
|
947
|
+
// Copy content of interceptor_worklet.js to this string
|
|
948
|
+
var awpStr = "class AudioCaptureInterceptorProcessor extends AudioWorkletProcessor{\n" +
|
|
949
|
+
"\n" +
|
|
950
|
+
" BUFFER_QUANTUMS=64;\n" +
|
|
951
|
+
" QUANTUM_FRAME_LEN=128;\n" +
|
|
952
|
+
" BUFFER_FRAME_LEN=this.QUANTUM_FRAME_LEN*this.BUFFER_QUANTUMS;\n" +
|
|
953
|
+
" buffer=null;\n" +
|
|
954
|
+
" bufferPos=0;\n" +
|
|
955
|
+
" bufferPosBytes=0;\n" +
|
|
956
|
+
" constructor() {\n" +
|
|
957
|
+
" super();\n" +
|
|
958
|
+
"\n" +
|
|
959
|
+
" }\n" +
|
|
960
|
+
"\n" +
|
|
961
|
+
" process(\n" +
|
|
962
|
+
" inputs,\n" +
|
|
963
|
+
" outputs,\n" +
|
|
964
|
+
" parameters\n" +
|
|
965
|
+
" ){\n" +
|
|
966
|
+
"\n" +
|
|
967
|
+
" let inputsCnt=inputs.length;\n" +
|
|
968
|
+
" let channelCount=0;\n" +
|
|
969
|
+
" let inputLen=0;\n" +
|
|
970
|
+
" let inputLenBytes=0;\n" +
|
|
971
|
+
" if(inputsCnt>0) {\n" +
|
|
972
|
+
" let input0 = inputs[0];\n" +
|
|
973
|
+
" channelCount = input0.length;\n" +
|
|
974
|
+
" if (channelCount > 0) {\n" +
|
|
975
|
+
" let input0ch0=input0[0];\n" +
|
|
976
|
+
" inputLen=input0ch0.length;\n" +
|
|
977
|
+
" inputLenBytes=input0ch0.buffer.length;\n" +
|
|
978
|
+
" }\n" +
|
|
979
|
+
" }\n" +
|
|
980
|
+
" if (!this.buffer || this.buffer.length < channelCount) {\n" +
|
|
981
|
+
" this.buffer = new Array(channelCount);\n" +
|
|
982
|
+
" this.bufferPos = 0\n" +
|
|
983
|
+
" for (let bch = 0; bch < channelCount; bch++) {\n" +
|
|
984
|
+
" this.buffer[bch] = new Float32Array(this.BUFFER_FRAME_LEN);\n" +
|
|
985
|
+
" this.bufferPos = 0;\n" +
|
|
986
|
+
" this.bufferPosBytes=0;\n" +
|
|
987
|
+
" }\n" +
|
|
988
|
+
" }\n" +
|
|
989
|
+
" let bufAvail = this.BUFFER_FRAME_LEN - this.bufferPos;\n" +
|
|
990
|
+
" // check if buffer has to be transferred\n" +
|
|
991
|
+
" if (inputLen > bufAvail) {\n" +
|
|
992
|
+
" let ada=new Array(channelCount);\n" +
|
|
993
|
+
" for (let ch = 0; ch < channelCount; ch++) {\n" +
|
|
994
|
+
" ada[ch]=this.buffer[ch].buffer.slice(0);\n" +
|
|
995
|
+
" }\n" +
|
|
996
|
+
" this.port.postMessage({\n" +
|
|
997
|
+
" data: ada,\n" +
|
|
998
|
+
" chs: channelCount,\n" +
|
|
999
|
+
" len: this.bufferPos\n" +
|
|
1000
|
+
" }, ada);\n" +
|
|
1001
|
+
" // buffer transferred, reset\n" +
|
|
1002
|
+
" this.bufferPos = 0;\n" +
|
|
1003
|
+
" this.bufferPosBytes=0;\n" +
|
|
1004
|
+
" }\n" +
|
|
1005
|
+
"\n" +
|
|
1006
|
+
" for(let ii=0;ii<inputsCnt;ii++) {\n" +
|
|
1007
|
+
" for (let ch = 0; ch < channelCount; ch++) {\n" +
|
|
1008
|
+
" // Mute outputs\n" +
|
|
1009
|
+
" //outputs[ii][ch].fill(0);\n" +
|
|
1010
|
+
" let chSamples = inputs[ii][ch];\n" +
|
|
1011
|
+
" this.buffer[ch].set(chSamples,this.bufferPos);\n" +
|
|
1012
|
+
" }\n" +
|
|
1013
|
+
" this.bufferPos+=inputLen;\n" +
|
|
1014
|
+
" this.bufferPosBytes+=inputLenBytes;\n" +
|
|
1015
|
+
" }\n" +
|
|
1016
|
+
" \n" +
|
|
1017
|
+
" return true;\n" +
|
|
1018
|
+
" }\n" +
|
|
1019
|
+
"}\n" +
|
|
1020
|
+
"\n" +
|
|
1021
|
+
"registerProcessor('capture-interceptor',AudioCaptureInterceptorProcessor);\n";
|
|
730
1022
|
var AudioCapture = /** @class */ (function () {
|
|
731
1023
|
function AudioCapture(context) {
|
|
1024
|
+
this.agcStatus = null;
|
|
1025
|
+
this.bufferingNode = null;
|
|
732
1026
|
this.audioOutStream = null;
|
|
733
1027
|
this.disconnectStreams = true;
|
|
734
1028
|
this._opened = false;
|
|
@@ -783,7 +1077,7 @@
|
|
|
783
1077
|
if (!labelsAvailable) {
|
|
784
1078
|
//console.debug("Media device enumeration: No labels.")
|
|
785
1079
|
if (retry) {
|
|
786
|
-
|
|
1080
|
+
console.info("Starting dummy session to request audio permissions...");
|
|
787
1081
|
_this.dummySession().then(function (s) {
|
|
788
1082
|
// and stop it immediately
|
|
789
1083
|
if (s) {
|
|
@@ -848,13 +1142,14 @@
|
|
|
848
1142
|
console.log("Audio device: Id: " + di.deviceId + " groupId: " + di.groupId + " label: " + di.label + " kind: " + di.kind);
|
|
849
1143
|
}
|
|
850
1144
|
};
|
|
851
|
-
AudioCapture.prototype.open = function (channelCount, selDeviceId) {
|
|
1145
|
+
AudioCapture.prototype.open = function (channelCount, selDeviceId, autoGainControlConfigs) {
|
|
852
1146
|
var _this = this;
|
|
853
1147
|
this.context.resume().then(function () {
|
|
854
|
-
_this._open(channelCount, selDeviceId);
|
|
1148
|
+
_this._open(channelCount, selDeviceId, autoGainControlConfigs);
|
|
855
1149
|
});
|
|
856
1150
|
};
|
|
857
|
-
AudioCapture.prototype._open = function (channelCount, selDeviceId) {
|
|
1151
|
+
AudioCapture.prototype._open = function (channelCount, selDeviceId, autoGainControlConfigs) {
|
|
1152
|
+
var e_1, _a;
|
|
858
1153
|
var _this = this;
|
|
859
1154
|
this.channelCount = channelCount;
|
|
860
1155
|
this.framesRecorded = 0;
|
|
@@ -871,7 +1166,58 @@
|
|
|
871
1166
|
// TODO test if input is unprocessed
|
|
872
1167
|
var msc;
|
|
873
1168
|
console.info('User agent: ' + navigator.userAgent);
|
|
874
|
-
|
|
1169
|
+
var ua = UserAgentBuilder.userAgent();
|
|
1170
|
+
// ua.components.forEach((c)=>{
|
|
1171
|
+
// console.info("UA_Comp: "+c.toString());
|
|
1172
|
+
// })
|
|
1173
|
+
var agcCfg = null;
|
|
1174
|
+
var autoGainControl = false;
|
|
1175
|
+
var chromeEchoCancellation = false;
|
|
1176
|
+
if (autoGainControlConfigs) {
|
|
1177
|
+
try {
|
|
1178
|
+
for (var autoGainControlConfigs_1 = __values(autoGainControlConfigs), autoGainControlConfigs_1_1 = autoGainControlConfigs_1.next(); !autoGainControlConfigs_1_1.done; autoGainControlConfigs_1_1 = autoGainControlConfigs_1.next()) {
|
|
1179
|
+
var agcc = autoGainControlConfigs_1_1.value;
|
|
1180
|
+
if (agcc.platform === Platform.Android && ua.detectedPlatform === Platform$1.Android) {
|
|
1181
|
+
agcCfg = agcc;
|
|
1182
|
+
break;
|
|
1183
|
+
}
|
|
1184
|
+
if (agcc.platform === Platform.Windows && ua.detectedPlatform === Platform$1.Windows) {
|
|
1185
|
+
agcCfg = agcc;
|
|
1186
|
+
break;
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
1191
|
+
finally {
|
|
1192
|
+
try {
|
|
1193
|
+
if (autoGainControlConfigs_1_1 && !autoGainControlConfigs_1_1.done && (_a = autoGainControlConfigs_1.return)) _a.call(autoGainControlConfigs_1);
|
|
1194
|
+
}
|
|
1195
|
+
finally { if (e_1) throw e_1.error; }
|
|
1196
|
+
}
|
|
1197
|
+
if (agcCfg) {
|
|
1198
|
+
// TODO use EXACT/IDEAL constraint
|
|
1199
|
+
autoGainControl = agcCfg.value;
|
|
1200
|
+
if (CHROME_ACTIVATE_ECHO_CANCELLATION_WITH_AGC) {
|
|
1201
|
+
chromeEchoCancellation = agcCfg.value;
|
|
1202
|
+
}
|
|
1203
|
+
// TODO query real AGC status
|
|
1204
|
+
this.agcStatus = agcCfg.value;
|
|
1205
|
+
}
|
|
1206
|
+
else {
|
|
1207
|
+
this.agcStatus = false;
|
|
1208
|
+
}
|
|
1209
|
+
}
|
|
1210
|
+
// default
|
|
1211
|
+
msc = {
|
|
1212
|
+
audio: {
|
|
1213
|
+
deviceId: selDeviceId,
|
|
1214
|
+
echoCancellation: false,
|
|
1215
|
+
channelCount: channelCount,
|
|
1216
|
+
autoGainControl: autoGainControl
|
|
1217
|
+
},
|
|
1218
|
+
video: false
|
|
1219
|
+
};
|
|
1220
|
+
if (ua.detectedBrowser === Browser$1.Edge) {
|
|
875
1221
|
// Microsoft Edge sends unmodified audio
|
|
876
1222
|
// The constraint can follow the specification
|
|
877
1223
|
console.info("Setting media track constraints for Microsoft Edge.");
|
|
@@ -879,12 +1225,13 @@
|
|
|
879
1225
|
audio: {
|
|
880
1226
|
deviceId: selDeviceId,
|
|
881
1227
|
echoCancellation: false,
|
|
882
|
-
channelCount: channelCount
|
|
1228
|
+
channelCount: channelCount,
|
|
1229
|
+
autoGainControl: autoGainControl
|
|
883
1230
|
},
|
|
884
1231
|
video: false
|
|
885
1232
|
};
|
|
886
1233
|
}
|
|
887
|
-
else if (
|
|
1234
|
+
else if (ua.detectedBrowser === Browser$1.Chrome) {
|
|
888
1235
|
// Google Chrome: we need to switch of each of the preprocessing units including the
|
|
889
1236
|
console.info("Setting media track constraints for Google Chrome.");
|
|
890
1237
|
// Chrome 60 -> 61 changed
|
|
@@ -892,47 +1239,38 @@
|
|
|
892
1239
|
// Requires at least Chrome 61
|
|
893
1240
|
msc = {
|
|
894
1241
|
audio: {
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
"googExperimentalEchoCancellation": false,
|
|
901
|
-
"googAutoGainControl": false,
|
|
902
|
-
"googTypingNoiseDetection": false,
|
|
903
|
-
"googNoiseSuppression": false,
|
|
904
|
-
"googHighpassFilter": false,
|
|
905
|
-
"googBeamforming": false
|
|
1242
|
+
deviceId: selDeviceId,
|
|
1243
|
+
channelCount: channelCount,
|
|
1244
|
+
echoCancellation: { exact: chromeEchoCancellation },
|
|
1245
|
+
autoGainControl: { exact: autoGainControl },
|
|
1246
|
+
sampleSize: { min: 16 },
|
|
906
1247
|
},
|
|
907
1248
|
video: false,
|
|
908
1249
|
};
|
|
909
1250
|
}
|
|
910
|
-
else if (
|
|
1251
|
+
else if (ua.detectedBrowser === Browser$1.Firefox) {
|
|
911
1252
|
console.info("Setting media track constraints for Mozilla Firefox.");
|
|
912
1253
|
// Firefox
|
|
913
1254
|
msc = {
|
|
914
1255
|
audio: {
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
"mozAutoGainControl": false,
|
|
921
|
-
"noiseSuppression": false,
|
|
922
|
-
"mozNoiseSuppression": false
|
|
1256
|
+
deviceId: selDeviceId,
|
|
1257
|
+
channelCount: channelCount,
|
|
1258
|
+
echoCancellation: false,
|
|
1259
|
+
autoGainControl: autoGainControl,
|
|
1260
|
+
noiseSuppression: false
|
|
923
1261
|
},
|
|
924
1262
|
video: false,
|
|
925
1263
|
};
|
|
926
1264
|
}
|
|
927
|
-
else if (
|
|
1265
|
+
else if (ua.detectedBrowser === Browser$1.Safari) {
|
|
928
1266
|
console.info("Setting media track constraints for Safari browser.");
|
|
929
1267
|
console.info("Apply workaround for Safari: Avoid disconnect of streams.");
|
|
930
1268
|
this.disconnectStreams = false;
|
|
931
1269
|
msc = {
|
|
932
1270
|
audio: {
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1271
|
+
deviceId: selDeviceId,
|
|
1272
|
+
channelCount: channelCount,
|
|
1273
|
+
echoCancellation: false
|
|
936
1274
|
},
|
|
937
1275
|
video: false,
|
|
938
1276
|
};
|
|
@@ -940,6 +1278,7 @@
|
|
|
940
1278
|
else {
|
|
941
1279
|
// TODO default constraints or error Browser not supported
|
|
942
1280
|
}
|
|
1281
|
+
console.debug("Audio capture, AGC: " + this.agcStatus);
|
|
943
1282
|
var ump = navigator.mediaDevices.getUserMedia(msc);
|
|
944
1283
|
ump.then(function (s) {
|
|
945
1284
|
_this.stream = s;
|
|
@@ -947,6 +1286,11 @@
|
|
|
947
1286
|
for (var i = 0; i < aTracks.length; i++) {
|
|
948
1287
|
var aTrack = aTracks[i];
|
|
949
1288
|
console.info("Track audio info: id: " + aTrack.id + " kind: " + aTrack.kind + " label: \"" + aTrack.label + "\"");
|
|
1289
|
+
var mtrSts = aTrack.getSettings();
|
|
1290
|
+
console.info("Track audio settings: Ch cnt: " + mtrSts.channelCount + ", AGC: " + mtrSts.autoGainControl + ", Echo cancell.: " + mtrSts.echoCancellation);
|
|
1291
|
+
if (mtrSts.autoGainControl) {
|
|
1292
|
+
_this.agcStatus = mtrSts.autoGainControl;
|
|
1293
|
+
}
|
|
950
1294
|
}
|
|
951
1295
|
var vTracks = s.getVideoTracks();
|
|
952
1296
|
for (var i = 0; i < vTracks.length; i++) {
|
|
@@ -956,6 +1300,7 @@
|
|
|
956
1300
|
_this.mediaStream = _this.context.createMediaStreamSource(s);
|
|
957
1301
|
// stream channel count ( is always 2 !)
|
|
958
1302
|
var streamChannelCount = _this.mediaStream.channelCount;
|
|
1303
|
+
console.info("Stream channel count: " + streamChannelCount);
|
|
959
1304
|
// is not set!!
|
|
960
1305
|
//this.currentSampleRate = this.mediaStream.sampleRate;
|
|
961
1306
|
_this.currentSampleRate = _this.context.sampleRate;
|
|
@@ -965,43 +1310,117 @@
|
|
|
965
1310
|
}
|
|
966
1311
|
// W3C -> new name is createScriptProcessor
|
|
967
1312
|
//
|
|
968
|
-
//
|
|
1313
|
+
// Again deprecated, but AudioWorker not yet implemented in stable releases (June 2016)
|
|
969
1314
|
// AudioWorker is now AudioWorkletProcessor ... (May 2017)
|
|
970
1315
|
// Update 12-2020:
|
|
971
1316
|
// The ScriptProcessorNode Interface - DEPRECATED
|
|
972
|
-
|
|
973
|
-
|
|
1317
|
+
// Update 06-2021
|
|
1318
|
+
// AudioWorkletProcessor is here to stay. Web Audio API has now Recommendation status !
|
|
1319
|
+
if (ENABLE_AUDIO_WORKLET && _this.context.audioWorklet) {
|
|
1320
|
+
//const workletFileName = ('file-loader!./interceptor_worklet.js');
|
|
1321
|
+
//const workletFileName = 'http://localhost:4200/assets/interceptor_worklet.js';
|
|
1322
|
+
//console.log(awpStr);
|
|
1323
|
+
var audioWorkletModuleBlob = new Blob([awpStr], { type: 'text/javascript' });
|
|
1324
|
+
var audioWorkletModuleBlobUrl = window.URL.createObjectURL(audioWorkletModuleBlob);
|
|
1325
|
+
_this.context.audioWorklet.addModule(audioWorkletModuleBlobUrl).then(function () {
|
|
1326
|
+
var awn = new AudioWorkletNode(_this.context, 'capture-interceptor');
|
|
1327
|
+
awn.onprocessorerror = function (ev) {
|
|
1328
|
+
var msg = 'Unknwon error';
|
|
1329
|
+
if (ev instanceof ErrorEvent) {
|
|
1330
|
+
msg = ev.message;
|
|
1331
|
+
}
|
|
1332
|
+
console.error("Capture audio worklet error: " + msg);
|
|
1333
|
+
if (_this.listener) {
|
|
1334
|
+
_this.listener.error(msg);
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
var awnPt = awn.port;
|
|
1338
|
+
if (awnPt) {
|
|
1339
|
+
awnPt.onmessage = function (ev) {
|
|
1340
|
+
if (_this.capturing) {
|
|
1341
|
+
var dt = ev.data;
|
|
1342
|
+
var chs = dt.chs;
|
|
1343
|
+
var adaLen = dt.data.length;
|
|
1344
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
1345
|
+
console.debug('Received data from worklet: ' + chs + ' ' + dt.len + ' Data chs: ' + adaLen);
|
|
1346
|
+
}
|
|
1347
|
+
//let chunkLen = adaLen / chs;
|
|
1348
|
+
var chunkLen = adaLen;
|
|
1349
|
+
var chunk = new Array(chs);
|
|
1350
|
+
for (var ch = 0; ch < chs; ch++) {
|
|
1351
|
+
if (_this.data && _this.data[ch]) {
|
|
1352
|
+
var adaPos = ch * chunkLen;
|
|
1353
|
+
if (dt.data[ch]) {
|
|
1354
|
+
var fa = new Float32Array(dt.data[ch]);
|
|
1355
|
+
_this.data[ch].push(fa);
|
|
1356
|
+
chunk[ch] = fa;
|
|
1357
|
+
// Use samples of channel 0 to count frames (samples)
|
|
1358
|
+
if (ch == 0) {
|
|
1359
|
+
_this.framesRecorded += fa.length;
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
else {
|
|
1363
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
1364
|
+
console.debug('Channel ' + ch + ' data not set!!');
|
|
1365
|
+
}
|
|
1366
|
+
}
|
|
1367
|
+
}
|
|
1368
|
+
}
|
|
1369
|
+
if (_this.audioOutStream) {
|
|
1370
|
+
_this.audioOutStream.write(chunk);
|
|
1371
|
+
}
|
|
1372
|
+
}
|
|
1373
|
+
};
|
|
1374
|
+
}
|
|
1375
|
+
_this.bufferingNode = awn;
|
|
1376
|
+
_this._opened = true;
|
|
1377
|
+
if (_this.listener) {
|
|
1378
|
+
_this.listener.opened();
|
|
1379
|
+
}
|
|
1380
|
+
}).catch(function (error) {
|
|
1381
|
+
console.log('Could not add module ' + error);
|
|
1382
|
+
});
|
|
974
1383
|
}
|
|
975
|
-
else {
|
|
976
|
-
// The ScriptProcessorNode Interface - DEPRECATED
|
|
977
|
-
//console.debug("Audio script processor implemented!!");
|
|
1384
|
+
else if (_this.context.createScriptProcessor) {
|
|
1385
|
+
// The ScriptProcessorNode Interface - DEPRECATED Only as fallback
|
|
978
1386
|
// TODO should we use streamChannelCount or channelCount here ?
|
|
979
|
-
|
|
1387
|
+
var scriptProcessorNode = _this.context.createScriptProcessor(AudioCapture.BUFFER_SIZE, streamChannelCount, streamChannelCount);
|
|
1388
|
+
_this.bufferingNode = scriptProcessorNode;
|
|
980
1389
|
var c_1 = 0;
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
1390
|
+
if (scriptProcessorNode.onaudioprocess) {
|
|
1391
|
+
scriptProcessorNode.onaudioprocess = function (e) {
|
|
1392
|
+
if (_this.capturing) {
|
|
1393
|
+
var inBuffer = e.inputBuffer;
|
|
1394
|
+
var duration = inBuffer.duration;
|
|
1395
|
+
// only process requested count of channels
|
|
1396
|
+
var currentBuffers = new Array(channelCount);
|
|
1397
|
+
for (var ch = 0; ch < channelCount; ch++) {
|
|
1398
|
+
var chSamples = inBuffer.getChannelData(ch);
|
|
1399
|
+
var chSamplesCopy = chSamples.slice(0);
|
|
1400
|
+
currentBuffers[ch] = chSamplesCopy.slice(0);
|
|
1401
|
+
_this.data[ch].push(chSamplesCopy);
|
|
1402
|
+
if (DEBUG_TRACE_LEVEL > 8) {
|
|
1403
|
+
console.debug("Process " + chSamplesCopy.length + " samples.");
|
|
1404
|
+
}
|
|
1405
|
+
_this.framesRecorded += chSamplesCopy.length;
|
|
1406
|
+
}
|
|
1407
|
+
c_1++;
|
|
1408
|
+
if (_this.audioOutStream) {
|
|
1409
|
+
_this.audioOutStream.write(currentBuffers);
|
|
1410
|
+
}
|
|
998
1411
|
}
|
|
1412
|
+
};
|
|
1413
|
+
_this._opened = true;
|
|
1414
|
+
if (_this.listener) {
|
|
1415
|
+
_this.listener.opened();
|
|
999
1416
|
}
|
|
1000
|
-
}
|
|
1417
|
+
}
|
|
1418
|
+
else {
|
|
1419
|
+
_this.listener.error('Browser does not support audio processing (ScriptProcessor.onaudioprocess method not found)!');
|
|
1420
|
+
}
|
|
1001
1421
|
}
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
_this.listener.opened();
|
|
1422
|
+
else {
|
|
1423
|
+
_this.listener.error('Browser does not support audio processing (neither AudioWorkletProcessor nor ScriptProcessor)!');
|
|
1005
1424
|
}
|
|
1006
1425
|
}, function (e) {
|
|
1007
1426
|
console.error(e + " Error name: " + e.name);
|
|
@@ -1028,14 +1447,16 @@
|
|
|
1028
1447
|
this.audioOutStream.nextStream();
|
|
1029
1448
|
}
|
|
1030
1449
|
this.capturing = true;
|
|
1031
|
-
|
|
1032
|
-
|
|
1450
|
+
if (this.bufferingNode) {
|
|
1451
|
+
this.mediaStream.connect(this.bufferingNode);
|
|
1452
|
+
this.bufferingNode.connect(this.context.destination);
|
|
1453
|
+
}
|
|
1033
1454
|
if (this.listener) {
|
|
1034
1455
|
this.listener.started();
|
|
1035
1456
|
}
|
|
1036
1457
|
};
|
|
1037
1458
|
AudioCapture.prototype.stop = function () {
|
|
1038
|
-
if (this.disconnectStreams) {
|
|
1459
|
+
if (this.disconnectStreams && this.bufferingNode) {
|
|
1039
1460
|
this.mediaStream.disconnect(this.bufferingNode);
|
|
1040
1461
|
this.bufferingNode.disconnect(this.context.destination);
|
|
1041
1462
|
}
|
|
@@ -1061,7 +1482,7 @@
|
|
|
1061
1482
|
this._opened = false;
|
|
1062
1483
|
};
|
|
1063
1484
|
AudioCapture.prototype.audioBuffer = function () {
|
|
1064
|
-
var
|
|
1485
|
+
var e_2, _a, e_3, _b;
|
|
1065
1486
|
var frameLen = 0;
|
|
1066
1487
|
var ch0Data = this.data[0];
|
|
1067
1488
|
try {
|
|
@@ -1070,31 +1491,31 @@
|
|
|
1070
1491
|
frameLen += ch0Chk.length;
|
|
1071
1492
|
}
|
|
1072
1493
|
}
|
|
1073
|
-
catch (
|
|
1494
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
1074
1495
|
finally {
|
|
1075
1496
|
try {
|
|
1076
1497
|
if (ch0Data_1_1 && !ch0Data_1_1.done && (_a = ch0Data_1.return)) _a.call(ch0Data_1);
|
|
1077
1498
|
}
|
|
1078
|
-
finally { if (
|
|
1499
|
+
finally { if (e_2) throw e_2.error; }
|
|
1079
1500
|
}
|
|
1080
1501
|
var ab = this.context.createBuffer(this.channelCount, frameLen, this.context.sampleRate);
|
|
1081
1502
|
for (var ch = 0; ch < this.channelCount; ch++) {
|
|
1082
1503
|
var chD = ab.getChannelData(ch);
|
|
1083
1504
|
var pos = 0;
|
|
1084
1505
|
try {
|
|
1085
|
-
for (var _c = (
|
|
1506
|
+
for (var _c = (e_3 = void 0, __values(this.data[ch])), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
1086
1507
|
var chChk = _d.value;
|
|
1087
1508
|
var bufLen = chChk.length;
|
|
1088
1509
|
chD.set(chChk, pos);
|
|
1089
1510
|
pos += bufLen;
|
|
1090
1511
|
}
|
|
1091
1512
|
}
|
|
1092
|
-
catch (
|
|
1513
|
+
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
1093
1514
|
finally {
|
|
1094
1515
|
try {
|
|
1095
1516
|
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
|
|
1096
1517
|
}
|
|
1097
|
-
finally { if (
|
|
1518
|
+
finally { if (e_3) throw e_3.error; }
|
|
1098
1519
|
}
|
|
1099
1520
|
}
|
|
1100
1521
|
return ab;
|
|
@@ -2283,6 +2704,8 @@
|
|
|
2283
2704
|
this.peakDbLevelStr = "-___ dB";
|
|
2284
2705
|
this.peakDbLvl = MIN_DB_LEVEL;
|
|
2285
2706
|
this._displayLevelInfos = null;
|
|
2707
|
+
this._agc = undefined;
|
|
2708
|
+
this.agcString = 'n/a';
|
|
2286
2709
|
this.onShowRecordingDetails = new i0.EventEmitter();
|
|
2287
2710
|
this.onDownloadRecording = new i0.EventEmitter();
|
|
2288
2711
|
this.playStartEnabled = false;
|
|
@@ -2291,6 +2714,24 @@
|
|
|
2291
2714
|
this.destroyed = false;
|
|
2292
2715
|
this.warnDbLevel = DEFAULT_WARN_DB_LEVEL;
|
|
2293
2716
|
}
|
|
2717
|
+
Object.defineProperty(LevelBarDisplay.prototype, "agc", {
|
|
2718
|
+
set: function (agc) {
|
|
2719
|
+
this._agc = agc;
|
|
2720
|
+
if (this._agc === undefined || this._agc === null) {
|
|
2721
|
+
this.agcString = 'n/a';
|
|
2722
|
+
}
|
|
2723
|
+
else {
|
|
2724
|
+
if (this._agc === true) {
|
|
2725
|
+
this.agcString = 'On';
|
|
2726
|
+
}
|
|
2727
|
+
else {
|
|
2728
|
+
this.agcString = 'Off';
|
|
2729
|
+
}
|
|
2730
|
+
}
|
|
2731
|
+
},
|
|
2732
|
+
enumerable: false,
|
|
2733
|
+
configurable: true
|
|
2734
|
+
});
|
|
2294
2735
|
LevelBarDisplay.prototype.ngOnDestroy = function () {
|
|
2295
2736
|
this.destroyed = true;
|
|
2296
2737
|
};
|
|
@@ -2357,12 +2798,12 @@
|
|
|
2357
2798
|
return LevelBarDisplay;
|
|
2358
2799
|
}());
|
|
2359
2800
|
LevelBarDisplay.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.10", ngImport: i0__namespace, type: LevelBarDisplay, deps: [{ token: i0__namespace.ElementRef }, { token: i0__namespace.ChangeDetectorRef }], target: i0__namespace.ɵɵFactoryTarget.Component });
|
|
2360
|
-
LevelBarDisplay.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.10", type: LevelBarDisplay, selector: "spr-recordingitemdisplay", inputs: { streamingMode: "streamingMode", audioSignalCollapsed: "audioSignalCollapsed", enableDownload: "enableDownload", playStartAction: "playStartAction", playStopAction: "playStopAction", displayAudioBuffer: "displayAudioBuffer", displayLevelInfos: "displayLevelInfos" }, outputs: { onShowRecordingDetails: "onShowRecordingDetails", onDownloadRecording: "onDownloadRecording" }, viewQueries: [{ propertyName: "liveLevel", first: true, predicate: LevelBar, descendants: true, static: true }], ngImport: i0__namespace, template: "\n <audio-levelbar [streamingMode]=\"streamingMode\" [displayLevelInfos]=\"_displayLevelInfos\"></audio-levelbar>\n <button matTooltip=\"Start playback\" (click)=\"playStartAction?.perform()\"\n [disabled]=\"playStartAction?.disabled\"\n [style.color]=\"playStartAction?.disabled ? 'grey' : 'green'\">\n <mat-icon>play_arrow</mat-icon>\n </button>\n <button matTooltip=\"Stop playback\" (click)=\"playStopAction?.perform()\"\n [disabled]=\"playStopAction?.disabled\"\n [style.color]=\"playStopAction?.disabled ? 'grey' : 'yellow'\">\n <mat-icon>stop</mat-icon>\n </button>\n <button matTooltip=\"Toggle detailed audio display\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"showRecordingDetails()\">\n <mat-icon>{{(audioSignalCollapsed) ? \"expand_less\" : \"expand_more\"}}</mat-icon>\n </button>\n <button matTooltip=\"Download current recording\" *ngIf=\"enableDownload\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"downloadRecording()\">\n <mat-icon>file_download</mat-icon>\n </button>\n <div style=\"min-width: 14ch;padding:2px\"><table border=\"0\"><tr><td>Peak:</td><td><span matTooltip=\"Peak level\"\n [style.color]=\"(peakDbLvl > warnDbLevel)?'red':'black'\">{{peakDbLvl | number:'1.1-1'}} dB </span></td></tr></table></div>\n ", isInline: true, styles: [":host {\n flex: 0; /* only required vertical space */\n width: 100%;\n background: darkgray;\n padding: 4px;\n box-sizing: border-box;\n height: 100px;\n min-height: 100px;\n display: flex; /* flex container: left level bar, right decimal peak level value */\n flex-direction: row;\n flex-wrap: nowrap; /* wrap could completely destroy the layout */\n }", "audio-levelbar {\n flex: 1;\n box-sizing: border-box;\n }", "span {\n flex: 0;\n font-weight: bold;\n display: inline-block;\n white-space: nowrap;\n box-sizing: border-box;\n }"], components: [{ type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos"] }, { type: i2__namespace.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i3__namespace.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i4__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i4__namespace.DecimalPipe } });
|
|
2801
|
+
LevelBarDisplay.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.10", type: LevelBarDisplay, 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 }], ngImport: i0__namespace, template: "\n <audio-levelbar [streamingMode]=\"streamingMode\" [displayLevelInfos]=\"_displayLevelInfos\"></audio-levelbar>\n <button matTooltip=\"Start playback\" (click)=\"playStartAction?.perform()\"\n [disabled]=\"playStartAction?.disabled\"\n [style.color]=\"playStartAction?.disabled ? 'grey' : 'green'\">\n <mat-icon>play_arrow</mat-icon>\n </button>\n <button matTooltip=\"Stop playback\" (click)=\"playStopAction?.perform()\"\n [disabled]=\"playStopAction?.disabled\"\n [style.color]=\"playStopAction?.disabled ? 'grey' : 'yellow'\">\n <mat-icon>stop</mat-icon>\n </button>\n <button matTooltip=\"Toggle detailed audio display\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"showRecordingDetails()\">\n <mat-icon>{{(audioSignalCollapsed) ? \"expand_less\" : \"expand_more\"}}</mat-icon>\n </button>\n <button matTooltip=\"Download current recording\" *ngIf=\"enableDownload\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"downloadRecording()\">\n <mat-icon>file_download</mat-icon>\n </button>\n <div style=\"min-width: 14ch;padding:2px\"><table border=\"0\"><tr><td>Peak:</td><td><span matTooltip=\"Peak level\"\n [style.color]=\"(peakDbLvl > warnDbLevel)?'red':'black'\">{{peakDbLvl | number:'1.1-1'}} dB </span></td></tr>\n <tr *ngIf=\"_agc\"><td>AGC:</td><td><span matTooltip=\"Auto gain control\">{{agcString}}</span></td></tr></table></div>\n ", isInline: true, styles: [":host {\n flex: 0; /* only required vertical space */\n width: 100%;\n background: darkgray;\n padding: 4px;\n box-sizing: border-box;\n height: 100px;\n min-height: 100px;\n display: flex; /* flex container: left level bar, right decimal peak level value */\n flex-direction: row;\n flex-wrap: nowrap; /* wrap could completely destroy the layout */\n }", "audio-levelbar {\n flex: 1;\n box-sizing: border-box;\n }", "span {\n flex: 0;\n font-weight: bold;\n display: inline-block;\n white-space: nowrap;\n box-sizing: border-box;\n }"], components: [{ type: LevelBar, selector: "audio-levelbar", inputs: ["streamingMode", "displayLevelInfos"] }, { type: i2__namespace.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }], directives: [{ type: i3__namespace.MatTooltip, selector: "[matTooltip]", exportAs: ["matTooltip"] }, { type: i4__namespace.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], pipes: { "number": i4__namespace.DecimalPipe } });
|
|
2361
2802
|
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.10", ngImport: i0__namespace, type: LevelBarDisplay, decorators: [{
|
|
2362
2803
|
type: i0.Component,
|
|
2363
2804
|
args: [{
|
|
2364
2805
|
selector: 'spr-recordingitemdisplay',
|
|
2365
|
-
template: "\n <audio-levelbar [streamingMode]=\"streamingMode\" [displayLevelInfos]=\"_displayLevelInfos\"></audio-levelbar>\n <button matTooltip=\"Start playback\" (click)=\"playStartAction?.perform()\"\n [disabled]=\"playStartAction?.disabled\"\n [style.color]=\"playStartAction?.disabled ? 'grey' : 'green'\">\n <mat-icon>play_arrow</mat-icon>\n </button>\n <button matTooltip=\"Stop playback\" (click)=\"playStopAction?.perform()\"\n [disabled]=\"playStopAction?.disabled\"\n [style.color]=\"playStopAction?.disabled ? 'grey' : 'yellow'\">\n <mat-icon>stop</mat-icon>\n </button>\n <button matTooltip=\"Toggle detailed audio display\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"showRecordingDetails()\">\n <mat-icon>{{(audioSignalCollapsed) ? \"expand_less\" : \"expand_more\"}}</mat-icon>\n </button>\n <button matTooltip=\"Download current recording\" *ngIf=\"enableDownload\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"downloadRecording()\">\n <mat-icon>file_download</mat-icon>\n </button>\n <div style=\"min-width: 14ch;padding:2px\"><table border=\"0\"><tr><td>Peak:</td><td><span matTooltip=\"Peak level\"\n [style.color]=\"(peakDbLvl > warnDbLevel)?'red':'black'\">{{peakDbLvl | number:'1.1-1'}} dB </span></td></tr></table></div>\n ",
|
|
2806
|
+
template: "\n <audio-levelbar [streamingMode]=\"streamingMode\" [displayLevelInfos]=\"_displayLevelInfos\"></audio-levelbar>\n <button matTooltip=\"Start playback\" (click)=\"playStartAction?.perform()\"\n [disabled]=\"playStartAction?.disabled\"\n [style.color]=\"playStartAction?.disabled ? 'grey' : 'green'\">\n <mat-icon>play_arrow</mat-icon>\n </button>\n <button matTooltip=\"Stop playback\" (click)=\"playStopAction?.perform()\"\n [disabled]=\"playStopAction?.disabled\"\n [style.color]=\"playStopAction?.disabled ? 'grey' : 'yellow'\">\n <mat-icon>stop</mat-icon>\n </button>\n <button matTooltip=\"Toggle detailed audio display\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"showRecordingDetails()\">\n <mat-icon>{{(audioSignalCollapsed) ? \"expand_less\" : \"expand_more\"}}</mat-icon>\n </button>\n <button matTooltip=\"Download current recording\" *ngIf=\"enableDownload\" [disabled]=\"displayAudioBuffer==null\"\n (click)=\"downloadRecording()\">\n <mat-icon>file_download</mat-icon>\n </button>\n <div style=\"min-width: 14ch;padding:2px\"><table border=\"0\"><tr><td>Peak:</td><td><span matTooltip=\"Peak level\"\n [style.color]=\"(peakDbLvl > warnDbLevel)?'red':'black'\">{{peakDbLvl | number:'1.1-1'}} dB </span></td></tr>\n <tr *ngIf=\"_agc\"><td>AGC:</td><td><span matTooltip=\"Auto gain control\">{{agcString}}</span></td></tr></table></div>\n ",
|
|
2366
2807
|
styles: [":host {\n flex: 0; /* only required vertical space */\n width: 100%;\n background: darkgray;\n padding: 4px;\n box-sizing: border-box;\n height: 100px;\n min-height: 100px;\n display: flex; /* flex container: left level bar, right decimal peak level value */\n flex-direction: row;\n flex-wrap: nowrap; /* wrap could completely destroy the layout */\n }", "audio-levelbar {\n flex: 1;\n box-sizing: border-box;\n }", "span {\n flex: 0;\n font-weight: bold;\n display: inline-block;\n white-space: nowrap;\n box-sizing: border-box;\n }"]
|
|
2367
2808
|
}]
|
|
2368
2809
|
}], ctorParameters: function () { return [{ type: i0__namespace.ElementRef }, { type: i0__namespace.ChangeDetectorRef }]; }, propDecorators: { liveLevel: [{
|
|
@@ -2374,6 +2815,8 @@
|
|
|
2374
2815
|
type: i0.Input
|
|
2375
2816
|
}], enableDownload: [{
|
|
2376
2817
|
type: i0.Input
|
|
2818
|
+
}], agc: [{
|
|
2819
|
+
type: i0.Input
|
|
2377
2820
|
}], onShowRecordingDetails: [{
|
|
2378
2821
|
type: i0.Output
|
|
2379
2822
|
}], onDownloadRecording: [{
|
|
@@ -6118,12 +6561,13 @@
|
|
|
6118
6561
|
toFill = avail;
|
|
6119
6562
|
}
|
|
6120
6563
|
var sliceEnd = copied + toFill;
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6564
|
+
// Firefox on Android sends only the first channel
|
|
6565
|
+
for (var ch = 0; ch < buffersLen; ch++) {
|
|
6566
|
+
if (buffers[ch]) {
|
|
6567
|
+
var cpPrt = buffers[ch].slice(copied, sliceEnd);
|
|
6568
|
+
var buf = this.bufs[ch];
|
|
6569
|
+
buf.set(cpPrt, this.filled);
|
|
6570
|
+
}
|
|
6127
6571
|
}
|
|
6128
6572
|
copied += toFill;
|
|
6129
6573
|
avail -= toFill;
|
|
@@ -6759,6 +7203,7 @@
|
|
|
6759
7203
|
type: i0.Input
|
|
6760
7204
|
}] } });
|
|
6761
7205
|
|
|
7206
|
+
var FORCE_REQUEST_AUDIO_PERMISSIONS = false;
|
|
6762
7207
|
var RECFILE_API_CTX = 'recfile';
|
|
6763
7208
|
var MAX_RECORDING_TIME_MS = 1000 * 60 * 60 * 60; // 1 hour
|
|
6764
7209
|
var DEFAULT_PRE_REC_DELAY = 1000;
|
|
@@ -6810,6 +7255,9 @@
|
|
|
6810
7255
|
this.selCaptureDeviceId = null;
|
|
6811
7256
|
this.levelMeasure = new LevelMeasure();
|
|
6812
7257
|
this.streamLevelMeasure = new StreamLevelMeasure();
|
|
7258
|
+
this.userAgent = UserAgentBuilder.userAgent();
|
|
7259
|
+
console.debug("Detected platform: " + this.userAgent.detectedPlatform);
|
|
7260
|
+
console.debug("Detected browser: " + this.userAgent.detectedBrowser);
|
|
6813
7261
|
if (this.config && this.config.enableUploadRecordings !== undefined) {
|
|
6814
7262
|
this.enableUploadRecordings = this.config.enableUploadRecordings;
|
|
6815
7263
|
}
|
|
@@ -6994,6 +7442,13 @@
|
|
|
6994
7442
|
enumerable: false,
|
|
6995
7443
|
configurable: true
|
|
6996
7444
|
});
|
|
7445
|
+
Object.defineProperty(SessionManager.prototype, "autoGainControlConfigs", {
|
|
7446
|
+
set: function (autoGainControlConfigs) {
|
|
7447
|
+
this._autoGainControlConfigs = autoGainControlConfigs;
|
|
7448
|
+
},
|
|
7449
|
+
enumerable: false,
|
|
7450
|
+
configurable: true
|
|
7451
|
+
});
|
|
6997
7452
|
SessionManager.prototype.update = function (e) {
|
|
6998
7453
|
if (e.type == exports.EventType.STARTED) {
|
|
6999
7454
|
this.playStartAction.disabled = true;
|
|
@@ -7076,7 +7531,7 @@
|
|
|
7076
7531
|
else {
|
|
7077
7532
|
console.log("Open session with default audio device for " + this._channelCount + " channels");
|
|
7078
7533
|
}
|
|
7079
|
-
this.ac.open(this._channelCount, this._selectedDeviceId);
|
|
7534
|
+
this.ac.open(this._channelCount, this._selectedDeviceId, this._autoGainControlConfigs);
|
|
7080
7535
|
}
|
|
7081
7536
|
else {
|
|
7082
7537
|
this.ac.start();
|
|
@@ -7328,9 +7783,22 @@
|
|
|
7328
7783
|
this.sessionService.patchSessionObserver(this._session, body).subscribe();
|
|
7329
7784
|
}
|
|
7330
7785
|
}
|
|
7786
|
+
// Check browser compatibility
|
|
7787
|
+
if (this.userAgent.detectedBrowser === Browser$1.Safari && this._channelCount > 1) {
|
|
7788
|
+
var eMsg = "Error: Safari browser does not support stereo recordings.";
|
|
7789
|
+
console.error(eMsg);
|
|
7790
|
+
this.dialog.open(MessageDialog, {
|
|
7791
|
+
data: {
|
|
7792
|
+
type: 'error',
|
|
7793
|
+
title: 'Browser not supported',
|
|
7794
|
+
msg: eMsg,
|
|
7795
|
+
advice: "Please use a supported browser, e.g. Mozilla Firefox."
|
|
7796
|
+
}
|
|
7797
|
+
});
|
|
7798
|
+
}
|
|
7331
7799
|
//console.log("Session ID: "+this._session.session+ " status: "+this._session.status)
|
|
7332
7800
|
this._selectedDeviceId = undefined;
|
|
7333
|
-
if (!this.readonly && this.ac) {
|
|
7801
|
+
if (!this.readonly && this.ac && (FORCE_REQUEST_AUDIO_PERMISSIONS || (this._audioDevices && this._audioDevices.length > 0))) {
|
|
7334
7802
|
this.statusMsg = 'Requesting audio permissions...';
|
|
7335
7803
|
this.statusAlertType = 'info';
|
|
7336
7804
|
this.ac.deviceInfos(function (mdis) {
|
|
@@ -7447,6 +7915,7 @@
|
|
|
7447
7915
|
}
|
|
7448
7916
|
});
|
|
7449
7917
|
}
|
|
7918
|
+
// Safari does not list playback devices
|
|
7450
7919
|
if (!audioPlayDeviceAvail) {
|
|
7451
7920
|
// Firefox does not enumerate audiooutput devices
|
|
7452
7921
|
// Do not show this warning, because it would always appear on Firefox
|
|
@@ -7454,7 +7923,8 @@
|
|
|
7454
7923
|
// It is already implemneted but kept behind a preference setting https://bugzilla.mozilla.org/show_bug.cgi?id=1152401
|
|
7455
7924
|
// Output devices are listed if about:config media.setsinkid.enabled=true
|
|
7456
7925
|
// but default setting is false
|
|
7457
|
-
|
|
7926
|
+
// Same problem with Safari
|
|
7927
|
+
if (!(_this.userAgent.detectedBrowser === Browser$1.Safari || _this.userAgent.detectedBrowser === Browser$1.Firefox)) {
|
|
7458
7928
|
// no device found
|
|
7459
7929
|
_this.statusMsg = 'WARNING: No audio playback device available!';
|
|
7460
7930
|
_this.statusAlertType = 'warn';
|
|
@@ -7865,13 +8335,13 @@
|
|
|
7865
8335
|
return SessionManager;
|
|
7866
8336
|
}());
|
|
7867
8337
|
SessionManager.ɵfac = i0__namespace.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "12.2.10", ngImport: i0__namespace, type: SessionManager, deps: [{ token: i0__namespace.ChangeDetectorRef }, { token: i0__namespace.Renderer2 }, { token: i1__namespace$3.MatDialog }, { token: SessionService }, { token: RecordingService }, { token: SpeechRecorderUploader }, { token: SPEECHRECORDER_CONFIG }], target: i0__namespace.ɵɵFactoryTarget.Component });
|
|
7868
|
-
SessionManager.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.10", 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: LevelBarDisplay, descendants: true, static: true }], ngImport: i0__namespace, template: "\n <app-warningbar [show]=\"isTestSession()\" warningText=\"Test recording only!\"></app-warningbar>\n <app-warningbar [show]=\"isDefaultAudioTestSession()\" warningText=\"This test uses default audio device! Regular sessions may require a particular audio device (microphone)!\"></app-warningbar>\n <app-sprprompting [projectName]=\"projectName\"\n [startStopSignalState]=\"startStopSignalState\" [promptItem]=\"promptItem\" [showPrompt]=\"showPrompt\"\n [items]=\"items\"\n [transportActions]=\"transportActions\"\n [selectedItemIdx]=\"promptIndex\" (onItemSelect)=\"itemSelect($event)\" (onNextItem)=\"nextItem()\" (onPrevItem)=\"prevItem()\"\n [audioSignalCollapsed]=\"audioSignalCollapsed\" [displayAudioClip]=\"displayAudioClip\"\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playSelectionAction]=\"controlAudioPlayer?.startSelectionAction\"\n [autoPlayOnSelectToggleAction]=\"controlAudioPlayer?.autoPlayOnSelectToggleAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\">\n\n </app-sprprompting>\n <mat-progress-bar [value]=\"progressPercentValue()\" fxShow=\"false\" fxShow.xs=\"true\" ></mat-progress-bar>\n\n <spr-recordingitemdisplay #levelbardisplay\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\"\n [streamingMode]=\"isRecording()\"\n [displayLevelInfos]=\"displayLevelInfos\"\n [displayAudioBuffer]=\"displayAudioClip?.buffer\"
|
|
8338
|
+
SessionManager.ɵcmp = i0__namespace.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "12.2.10", 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: LevelBarDisplay, descendants: true, static: true }], ngImport: i0__namespace, template: "\n <app-warningbar [show]=\"isTestSession()\" warningText=\"Test recording only!\"></app-warningbar>\n <app-warningbar [show]=\"isDefaultAudioTestSession()\" warningText=\"This test uses default audio device! Regular sessions may require a particular audio device (microphone)!\"></app-warningbar>\n <app-sprprompting [projectName]=\"projectName\"\n [startStopSignalState]=\"startStopSignalState\" [promptItem]=\"promptItem\" [showPrompt]=\"showPrompt\"\n [items]=\"items\"\n [transportActions]=\"transportActions\"\n [selectedItemIdx]=\"promptIndex\" (onItemSelect)=\"itemSelect($event)\" (onNextItem)=\"nextItem()\" (onPrevItem)=\"prevItem()\"\n [audioSignalCollapsed]=\"audioSignalCollapsed\" [displayAudioClip]=\"displayAudioClip\"\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playSelectionAction]=\"controlAudioPlayer?.startSelectionAction\"\n [autoPlayOnSelectToggleAction]=\"controlAudioPlayer?.autoPlayOnSelectToggleAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\">\n\n </app-sprprompting>\n <mat-progress-bar [value]=\"progressPercentValue()\" fxShow=\"false\" fxShow.xs=\"true\" ></mat-progress-bar>\n\n <spr-recordingitemdisplay #levelbardisplay\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\"\n [streamingMode]=\"isRecording()\"\n [displayLevelInfos]=\"displayLevelInfos\"\n [displayAudioBuffer]=\"displayAudioClip?.buffer\"\n [agc]=\"this.ac?.agcStatus\"\n [audioSignalCollapsed]=\"audioSignalCollapsed\"\n (onShowRecordingDetails)=\"audioSignalCollapsed=!audioSignalCollapsed\"\n (onDownloadRecording)=\"downloadRecording()\"\n [enableDownload]=\"enableDownloadRecordings\"></spr-recordingitemdisplay>\n <app-sprcontrolpanel [enableUploadRecordings]=\"enableUploadRecordings\" [readonly]=\"readonly\" [currentRecording]=\"displayAudioClip?.buffer\"\n [transportActions]=\"transportActions\" [statusMsg]=\"statusMsg\" [statusWaiting]=\"statusWaiting\"\n [statusAlertType]=\"statusAlertType\" [uploadProgress]=\"uploadProgress\"\n [uploadStatus]=\"uploadStatus\" [ready]=\"dataSaved && !isActive()\" [processing]=\"processingRecording\" [navigationEnabled]=\"items==null || items.length>1\"></app-sprcontrolpanel>\n\n ", isInline: true, styles: [":host {\n flex: 2;\n background: lightgrey;\n display: flex; /* Vertical flex container: Bottom transport panel, above prompting panel */\n flex-direction: column;\n margin: 0;\n padding: 0;\n min-height: 0px;\n\n /* Prevents horizontal scroll bar on swipe right */\n overflow: hidden;\n }"], components: [{ type: WarningBar, selector: "app-warningbar", inputs: ["warningText", "show"] }, { type: Prompting, selector: "app-sprprompting", inputs: ["projectName", "startStopSignalState", "promptItem", "showPrompt", "items", "selectedItemIdx", "transportActions", "enableDownload", "audioSignalCollapsed", "displayAudioClip", "playStartAction", "playSelectionAction", "autoPlayOnSelectToggleAction", "playStopAction"], outputs: ["onItemSelect", "onNextItem", "onPrevItem"] }, { type: i7__namespace.MatProgressBar, selector: "mat-progress-bar", inputs: ["color", "mode", "value", "bufferValue"], outputs: ["animationEnd"], exportAs: ["matProgressBar"] }, { type: LevelBarDisplay, selector: "spr-recordingitemdisplay", inputs: ["streamingMode", "audioSignalCollapsed", "enableDownload", "agc", "playStartAction", "playStopAction", "displayAudioBuffer", "displayLevelInfos"], outputs: ["onShowRecordingDetails", "onDownloadRecording"] }, { type: ControlPanel, selector: "app-sprcontrolpanel", inputs: ["readonly", "transportActions", "processing", "statusMsg", "statusAlertType", "statusWaiting", "uploadStatus", "uploadProgress", "currentRecording", "enableUploadRecordings", "navigationEnabled", "ready"] }], directives: [{ type: i6__namespace.DefaultShowHideDirective, selector: " [fxShow], [fxShow.print], [fxShow.xs], [fxShow.sm], [fxShow.md], [fxShow.lg], [fxShow.xl], [fxShow.lt-sm], [fxShow.lt-md], [fxShow.lt-lg], [fxShow.lt-xl], [fxShow.gt-xs], [fxShow.gt-sm], [fxShow.gt-md], [fxShow.gt-lg], [fxHide], [fxHide.print], [fxHide.xs], [fxHide.sm], [fxHide.md], [fxHide.lg], [fxHide.xl], [fxHide.lt-sm], [fxHide.lt-md], [fxHide.lt-lg], [fxHide.lt-xl], [fxHide.gt-xs], [fxHide.gt-sm], [fxHide.gt-md], [fxHide.gt-lg]", inputs: ["fxShow", "fxShow.print", "fxShow.xs", "fxShow.sm", "fxShow.md", "fxShow.lg", "fxShow.xl", "fxShow.lt-sm", "fxShow.lt-md", "fxShow.lt-lg", "fxShow.lt-xl", "fxShow.gt-xs", "fxShow.gt-sm", "fxShow.gt-md", "fxShow.gt-lg", "fxHide", "fxHide.print", "fxHide.xs", "fxHide.sm", "fxHide.md", "fxHide.lg", "fxHide.xl", "fxHide.lt-sm", "fxHide.lt-md", "fxHide.lt-lg", "fxHide.lt-xl", "fxHide.gt-xs", "fxHide.gt-sm", "fxHide.gt-md", "fxHide.gt-lg"] }] });
|
|
7869
8339
|
i0__namespace.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "12.2.10", ngImport: i0__namespace, type: SessionManager, decorators: [{
|
|
7870
8340
|
type: i0.Component,
|
|
7871
8341
|
args: [{
|
|
7872
8342
|
selector: 'app-sprrecordingsession',
|
|
7873
8343
|
providers: [SessionService],
|
|
7874
|
-
template: "\n <app-warningbar [show]=\"isTestSession()\" warningText=\"Test recording only!\"></app-warningbar>\n <app-warningbar [show]=\"isDefaultAudioTestSession()\" warningText=\"This test uses default audio device! Regular sessions may require a particular audio device (microphone)!\"></app-warningbar>\n <app-sprprompting [projectName]=\"projectName\"\n [startStopSignalState]=\"startStopSignalState\" [promptItem]=\"promptItem\" [showPrompt]=\"showPrompt\"\n [items]=\"items\"\n [transportActions]=\"transportActions\"\n [selectedItemIdx]=\"promptIndex\" (onItemSelect)=\"itemSelect($event)\" (onNextItem)=\"nextItem()\" (onPrevItem)=\"prevItem()\"\n [audioSignalCollapsed]=\"audioSignalCollapsed\" [displayAudioClip]=\"displayAudioClip\"\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playSelectionAction]=\"controlAudioPlayer?.startSelectionAction\"\n [autoPlayOnSelectToggleAction]=\"controlAudioPlayer?.autoPlayOnSelectToggleAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\">\n\n </app-sprprompting>\n <mat-progress-bar [value]=\"progressPercentValue()\" fxShow=\"false\" fxShow.xs=\"true\" ></mat-progress-bar>\n\n <spr-recordingitemdisplay #levelbardisplay\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\"\n [streamingMode]=\"isRecording()\"\n [displayLevelInfos]=\"displayLevelInfos\"\n [displayAudioBuffer]=\"displayAudioClip?.buffer\"
|
|
8344
|
+
template: "\n <app-warningbar [show]=\"isTestSession()\" warningText=\"Test recording only!\"></app-warningbar>\n <app-warningbar [show]=\"isDefaultAudioTestSession()\" warningText=\"This test uses default audio device! Regular sessions may require a particular audio device (microphone)!\"></app-warningbar>\n <app-sprprompting [projectName]=\"projectName\"\n [startStopSignalState]=\"startStopSignalState\" [promptItem]=\"promptItem\" [showPrompt]=\"showPrompt\"\n [items]=\"items\"\n [transportActions]=\"transportActions\"\n [selectedItemIdx]=\"promptIndex\" (onItemSelect)=\"itemSelect($event)\" (onNextItem)=\"nextItem()\" (onPrevItem)=\"prevItem()\"\n [audioSignalCollapsed]=\"audioSignalCollapsed\" [displayAudioClip]=\"displayAudioClip\"\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playSelectionAction]=\"controlAudioPlayer?.startSelectionAction\"\n [autoPlayOnSelectToggleAction]=\"controlAudioPlayer?.autoPlayOnSelectToggleAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\">\n\n </app-sprprompting>\n <mat-progress-bar [value]=\"progressPercentValue()\" fxShow=\"false\" fxShow.xs=\"true\" ></mat-progress-bar>\n\n <spr-recordingitemdisplay #levelbardisplay\n [playStartAction]=\"controlAudioPlayer?.startAction\"\n [playStopAction]=\"controlAudioPlayer?.stopAction\"\n [streamingMode]=\"isRecording()\"\n [displayLevelInfos]=\"displayLevelInfos\"\n [displayAudioBuffer]=\"displayAudioClip?.buffer\"\n [agc]=\"this.ac?.agcStatus\"\n [audioSignalCollapsed]=\"audioSignalCollapsed\"\n (onShowRecordingDetails)=\"audioSignalCollapsed=!audioSignalCollapsed\"\n (onDownloadRecording)=\"downloadRecording()\"\n [enableDownload]=\"enableDownloadRecordings\"></spr-recordingitemdisplay>\n <app-sprcontrolpanel [enableUploadRecordings]=\"enableUploadRecordings\" [readonly]=\"readonly\" [currentRecording]=\"displayAudioClip?.buffer\"\n [transportActions]=\"transportActions\" [statusMsg]=\"statusMsg\" [statusWaiting]=\"statusWaiting\"\n [statusAlertType]=\"statusAlertType\" [uploadProgress]=\"uploadProgress\"\n [uploadStatus]=\"uploadStatus\" [ready]=\"dataSaved && !isActive()\" [processing]=\"processingRecording\" [navigationEnabled]=\"items==null || items.length>1\"></app-sprcontrolpanel>\n\n ",
|
|
7875
8345
|
styles: [":host {\n flex: 2;\n background: lightgrey;\n display: flex; /* Vertical flex container: Bottom transport panel, above prompting panel */\n flex-direction: column;\n margin: 0;\n padding: 0;\n min-height: 0px;\n\n /* Prevents horizontal scroll bar on swipe right */\n overflow: hidden;\n }"]
|
|
7876
8346
|
}]
|
|
7877
8347
|
}], ctorParameters: function () {
|
|
@@ -7897,23 +8367,6 @@
|
|
|
7897
8367
|
args: ['window:keydown', ['$event']]
|
|
7898
8368
|
}] } });
|
|
7899
8369
|
|
|
7900
|
-
var ProjectUtil = /** @class */ (function () {
|
|
7901
|
-
function ProjectUtil() {
|
|
7902
|
-
}
|
|
7903
|
-
ProjectUtil.audioChannelCount = function (project) {
|
|
7904
|
-
var chs = ProjectUtil.DEFAULT_AUDIO_CHANNEL_COUNT;
|
|
7905
|
-
if (project.mediaCaptureFormat) {
|
|
7906
|
-
chs = project.mediaCaptureFormat.audioChannelCount;
|
|
7907
|
-
}
|
|
7908
|
-
else if (project.audioFormat) {
|
|
7909
|
-
chs = project.audioFormat.channels;
|
|
7910
|
-
}
|
|
7911
|
-
return chs;
|
|
7912
|
-
};
|
|
7913
|
-
return ProjectUtil;
|
|
7914
|
-
}());
|
|
7915
|
-
ProjectUtil.DEFAULT_AUDIO_CHANNEL_COUNT = 2;
|
|
7916
|
-
|
|
7917
8370
|
/**
|
|
7918
8371
|
* Created by klausj on 17.06.2017.
|
|
7919
8372
|
*/
|
|
@@ -8249,6 +8702,7 @@
|
|
|
8249
8702
|
this.sm.audioDevices = project.audioDevices;
|
|
8250
8703
|
chCnt = ProjectUtil.audioChannelCount(project);
|
|
8251
8704
|
console.info("Project requested recording channel count: " + chCnt);
|
|
8705
|
+
this.sm.autoGainControlConfigs = project.autoGainControlConfigs;
|
|
8252
8706
|
}
|
|
8253
8707
|
else {
|
|
8254
8708
|
console.error("Empty project configuration!");
|
|
@@ -9451,7 +9905,7 @@
|
|
|
9451
9905
|
}]
|
|
9452
9906
|
}] });
|
|
9453
9907
|
|
|
9454
|
-
var VERSION = '2.
|
|
9908
|
+
var VERSION = '2.19.0';
|
|
9455
9909
|
|
|
9456
9910
|
/*
|
|
9457
9911
|
* Public API Surface of speechrecorderng
|