1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
|
// META: global=window
// META: script=/webcodecs/utils.js
function make_silent_audio_data(timestamp, channels, sampleRate, frames) {
let data = new Float32Array(frames*channels);
return new AudioData({
timestamp: timestamp,
data: data,
numberOfChannels: channels,
numberOfFrames: frames,
sampleRate: sampleRate,
format: "f32-planar",
});
}
// The Opus DTX flag (discontinuous transmission) reduces the encoding bitrate
// for silence. This test ensures the DTX flag is working properly by encoding
// almost 10s of silence and comparing the bitrate with and without the flag.
promise_test(async t => {
let sample_rate = 48000;
let total_duration_s = 10;
let data_count = 100;
let normal_outputs = [];
let dtx_outputs = [];
let normal_encoder = new AudioEncoder({
error: e => {
assert_unreached('error: ' + e);
},
output: chunk => {
normal_outputs.push(chunk);
}
});
let dtx_encoder = new AudioEncoder({
error: e => {
assert_unreached('error: ' + e);
},
output: chunk => {
dtx_outputs.push(chunk);
}
});
let config = {
codec: 'opus',
sampleRate: sample_rate,
numberOfChannels: 2,
bitrate: 256000, // 256kbit
};
let normal_config = {...config, opus: {usedtx: false}};
let dtx_config = {...config, opus: {usedtx: true}};
let normal_config_support = await AudioEncoder.isConfigSupported(normal_config);
assert_implements_optional(normal_config_support.supported, "Opus not supported");
let dtx_config_support = await AudioEncoder.isConfigSupported(dtx_config);
assert_implements_optional(dtx_config_support.supported, "Opus DTX not supported");
// Configure one encoder with and one without the DTX flag
normal_encoder.configure(normal_config);
dtx_encoder.configure(dtx_config);
let timestamp_us = 0;
let data_duration_s = total_duration_s / data_count;
let data_length = data_duration_s * config.sampleRate;
for (let i = 0; i < data_count; i++) {
let data;
if (i == 0 || i == (data_count - 1)) {
// Send real data for the first and last 100ms.
data = make_audio_data(
timestamp_us, config.numberOfChannels, config.sampleRate,
data_length);
} else {
// Send silence for the rest of the 10s.
data = make_silent_audio_data(
timestamp_us, config.numberOfChannels, config.sampleRate,
data_length);
}
normal_encoder.encode(data);
dtx_encoder.encode(data);
data.close();
timestamp_us += data_duration_s * 1_000_000;
}
await Promise.all([normal_encoder.flush(), dtx_encoder.flush()])
normal_encoder.close();
dtx_encoder.close();
// We expect a significant reduction in the number of packets, over ~10s of silence.
assert_less_than(dtx_outputs.length, (normal_outputs.length / 2));
}, 'Test the Opus DTX flag works.');
|