@audio/loudness-dr 1.0.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/dr.js +40 -0
- package/package.json +29 -0
package/dr.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// DR value — crest-factor dynamic range meter (TT/dr14 method):
|
|
2
|
+
// per-channel 3 s blocks → block RMS with the ×2 sine convention (full-scale sine → 0 dB)
|
|
3
|
+
// and block peak; DR_ch = 20·log10(secondHighestPeak / rms of loudest 20% blocks); average channels.
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @param {Float32Array|Float32Array[]} channels
|
|
7
|
+
* @param {object} opts — { fs=48000, blockSeconds=3 }
|
|
8
|
+
* @returns {number|null} DR value in dB
|
|
9
|
+
*/
|
|
10
|
+
export default function dr (channels, { fs = 48000, blockSeconds = 3 } = {}) {
|
|
11
|
+
if (channels[0]?.length === undefined) channels = [channels]
|
|
12
|
+
let win = Math.round(blockSeconds * fs)
|
|
13
|
+
let drs = []
|
|
14
|
+
|
|
15
|
+
for (let ch of channels) {
|
|
16
|
+
if (ch.length < win * 2) win = Math.max(1, Math.floor(ch.length / 2))
|
|
17
|
+
let rms = [], peaks = []
|
|
18
|
+
for (let i = 0; i + win <= ch.length; i += win) {
|
|
19
|
+
let e = 0, p = 0
|
|
20
|
+
for (let j = i; j < i + win; j++) {
|
|
21
|
+
let v = ch[j]
|
|
22
|
+
e += v * v
|
|
23
|
+
let a = Math.abs(v)
|
|
24
|
+
if (a > p) p = a
|
|
25
|
+
}
|
|
26
|
+
rms.push(Math.sqrt(2 * e / win))
|
|
27
|
+
peaks.push(p)
|
|
28
|
+
}
|
|
29
|
+
if (rms.length < 2) continue
|
|
30
|
+
peaks.sort((a, b) => b - a)
|
|
31
|
+
rms.sort((a, b) => b - a)
|
|
32
|
+
let top = Math.max(1, Math.round(rms.length * 0.2))
|
|
33
|
+
let e20 = 0
|
|
34
|
+
for (let i = 0; i < top; i++) e20 += rms[i] * rms[i]
|
|
35
|
+
let r = Math.sqrt(e20 / top)
|
|
36
|
+
let p2 = peaks[1]
|
|
37
|
+
if (r > 0 && p2 > 0) drs.push(20 * Math.log10(p2 / r))
|
|
38
|
+
}
|
|
39
|
+
return drs.length ? drs.reduce((a, b) => a + b, 0) / drs.length : null
|
|
40
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@audio/loudness-dr",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "DR value — TT/dr14 crest-factor dynamic range meter",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "dr.js",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./dr.js",
|
|
10
|
+
"./package.json": "./package.json"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"dr.js"
|
|
14
|
+
],
|
|
15
|
+
"keywords": [
|
|
16
|
+
"audio",
|
|
17
|
+
"dsp",
|
|
18
|
+
"loudness",
|
|
19
|
+
"dr"
|
|
20
|
+
],
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"author": "Dmitry Iv. <dfcreative@gmail.com>",
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18"
|
|
25
|
+
},
|
|
26
|
+
"publishConfig": {
|
|
27
|
+
"access": "public"
|
|
28
|
+
}
|
|
29
|
+
}
|