40 lines
2.2 KiB
Python
40 lines
2.2 KiB
Python
"""독립 BS.1770 구현으로 exact WAV를 검사한다. 일반 npm test에서는 실행하지 않는다."""
|
|
import hashlib
|
|
from importlib.metadata import version
|
|
import json
|
|
from pathlib import Path
|
|
import platform
|
|
import sys
|
|
import pyloudnorm as pyln
|
|
import soundfile as sf
|
|
|
|
ROOT = Path(__file__).resolve().parents[3]
|
|
EVIDENCE = Path(__file__).resolve().parent
|
|
assert version('pyloudnorm') == '0.2.0'
|
|
assert version('soundfile') == '0.13.1'
|
|
def sha(path):
|
|
return hashlib.sha256(path.read_bytes()).hexdigest()
|
|
rows = []
|
|
# manifest의 loudness나 생성기 함수를 읽지 않고 실제 파일을 독립 구현으로 측정한다.
|
|
for path in sorted((ROOT / 'public/ambience').glob('*.wav')):
|
|
before = sha(path)
|
|
data, rate = sf.read(path, dtype='float64', always_2d=False)
|
|
assert rate == 24000 and data.shape == (288000,)
|
|
meter = pyln.Meter(rate, filter_class='K-weighting', block_size=0.400)
|
|
value = float(meter.integrated_loudness(data))
|
|
assert sha(path) == before
|
|
rows.append({'file': str(path.relative_to(ROOT)), 'sha256': before, 'bytes': path.stat().st_size,
|
|
'frames': len(data), 'sampleRate': rate, 'integratedLUFS': value,
|
|
'targetErrorLU': value + 32.5})
|
|
spread = max(r['integratedLUFS'] for r in rows) - min(r['integratedLUFS'] for r in rows)
|
|
passed = len(rows) == 8 and all(abs(r['targetErrorLU']) <= 0.2 for r in rows) and spread <= 0.4
|
|
report = {'method': 'Independent pyloudnorm BS.1770 K-weighting, 400ms blocks, mono exact PCM16 decoded by soundfile',
|
|
'python': platform.python_version(), 'versions': {name: version(name) for name in ('pyloudnorm','soundfile','numpy','scipy','cffi','pycparser','future')},
|
|
'libsndfileVersion': sf.__libsndfile_version__, 'scriptSha256': sha(Path(__file__)),
|
|
'manifestSha256': sha(ROOT/'public/ambience/manifest.json'), 'targetIntegratedLUFS': -32.5,
|
|
'toleranceLU': 0.2, 'maximumSpreadLU': 0.4, 'spreadLU': spread, 'passed': passed, 'files': rows}
|
|
with (EVIDENCE/'pyloudnorm-results.json').open('x') as stream:
|
|
stream.write(json.dumps(report, indent=2, allow_nan=False)+'\n')
|
|
print(json.dumps(report, indent=2, allow_nan=False))
|
|
if not passed: sys.exit('Independent loudness release criterion failed')
|