in integration/js/pages/AppPage.js [669:829]
async audioCheck(stepInfo, expectedState, checkStereoTones = false) {
let res = undefined;
try {
res = await this.driver.executeAsyncScript(async (expectedState, checkStereoTones) => {
let logs = [];
let callback = arguments[arguments.length - 1];
const sleep = (milliseconds) => {
return new Promise(resolve => setTimeout(resolve, milliseconds))
};
const channelCount = checkStereoTones ? 2 : 1;
const successfulToneChecks = Array(channelCount).fill(0);
const totalToneChecks = Array(channelCount).fill(0);
const audioContext = new (window.AudioContext || window.webkitAudioContext)();
const minToneError = Array(channelCount).fill(Infinity);
const maxToneError = Array(channelCount).fill(-Infinity);
const percentages = Array(channelCount).fill(0);
try {
const stream = document.getElementById('meeting-audio').srcObject;
const source = audioContext.createMediaStreamSource(stream);
let analyser = [];
for(let i=0; i<channelCount; i++) {
analyser.push(audioContext.createAnalyser());
}
let byteFrequencyData = [];
for(let i=0; i<channelCount; i++) {
byteFrequencyData.push(new Uint8Array(analyser[i].frequencyBinCount));
}
let floatFrequencyData = [];
for(let i=0; i<channelCount; i++) {
floatFrequencyData.push(new Float32Array(analyser[i].frequencyBinCount));
}
if (checkStereoTones) {
const splitterNode = audioContext.createChannelSplitter(2);
source.connect(splitterNode);
splitterNode.connect(analyser[0], 0);
splitterNode.connect(analyser[1], 1);
} else {
source.connect(analyser[0]);
}
await sleep(5000);
const getAverageVolume = (channelIndex) => {
analyser[channelIndex].getByteFrequencyData(byteFrequencyData[channelIndex]);
let values = 0;
let average;
const length = byteFrequencyData[channelIndex].length;
// get all the frequency amplitudes
for (let i = 0; i < length; i++) {
values += byteFrequencyData[channelIndex][i];
}
average = values / length;
return average;
};
const checkVolumeFor = async (runCount, channelIndex) => {
for (let i = 0; i < runCount; i++) {
totalToneChecks[channelIndex]++;
const avgTestVolume = getAverageVolume(channelIndex);
logs.push(`Resulting volume ${avgTestVolume}`);
if (
(expectedState === "AUDIO_ON" && avgTestVolume > 0) ||
(expectedState === "AUDIO_OFF" && avgTestVolume === 0)
) {
successfulToneChecks[channelIndex]++;
}
await sleep(100)
}
};
const checkFrequency = (targetReceiveFrequency, channelIndex) => {
analyser[channelIndex].getFloatFrequencyData(floatFrequencyData[channelIndex]);
// logs.push(`frequency data : ${floatFrequencyData}`);
let maxBinDb = -Infinity;
let hotBinFrequency = 0;
const binSize = audioContext.sampleRate / analyser[channelIndex].fftSize; // default fftSize is 2048
for (let i = 0; i < floatFrequencyData[channelIndex].length; i++) {
const v = floatFrequencyData[channelIndex][i];
if (v > maxBinDb) {
maxBinDb = v;
hotBinFrequency = i * binSize;
}
}
const error = Math.abs(hotBinFrequency - targetReceiveFrequency);
if (maxBinDb > -Infinity) {
if (error < minToneError[channelIndex]) {
minToneError[channelIndex] = error;
}
if (error > maxToneError[channelIndex]) {
maxToneError[channelIndex] = error;
}
}
if (error <= 2 * binSize) {
successfulToneChecks[channelIndex]++;
}
totalToneChecks[channelIndex]++;
return hotBinFrequency
};
const checkFrequencyFor = async (runCount, freq, channelIndex) => {
for (let i = 0; i < runCount; i++) {
const testFrequency = checkFrequency(freq, channelIndex);
logs.push(`Resulting Frequency ${testFrequency} for channel ${channelIndex}`);
await sleep(100)
}
};
if (expectedState === "AUDIO_OFF") {
await checkVolumeFor(50, 0);
if (checkStereoTones) {
await checkVolumeFor(50, 1);
}
}
if (expectedState === "AUDIO_ON") {
if (checkStereoTones) {
await checkFrequencyFor(50, 500, 0);
await checkFrequencyFor(50, 1000, 1);
} else {
await checkFrequencyFor(50, 440, 0);
}
}
for (let i=0; i<channelCount; i++) {
percentages[i] = successfulToneChecks[i] / totalToneChecks[i];
}
} catch (e) {
logs.push(`${e}`)
} finally {
logs.push(`test completed`);
await audioContext.close();
callback({
percentages,
logs
});
}
}, expectedState, checkStereoTones);
} catch (e) {
this.logger(`Audio Check Failed ${e}`)
} finally {
if (res) {
res.logs.forEach(l => {
this.logger(l)
})
}
}
if (!res) {
return false;
}
for (let i=0; i<res.percentages.length; i++) {
this.logger(`Audio check success rate channel ${i}: ${res.percentages[i] * 100}%`);
if (res.percentages[i] < 0.75) {
return false;
}
}
return true;
}