|
| 1 | +"""Tests for NTSC-locked analog audio output (--ntsc_audio_rate). |
| 2 | +
|
| 3 | +The flag maps to a negative output frequency, which downscale_audio |
| 4 | +interprets as a multiple of the horizontal line frequency. -2.8 must |
| 5 | +produce exactly 2.8 audio samples per line (1470 per 525-line NTSC |
| 6 | +frame), keeping the audio perfectly aligned to the video with no drift. |
| 7 | +""" |
| 8 | + |
| 9 | +import numpy as np |
| 10 | + |
| 11 | +from lddecode.core import _downscale_audio_compute_locs_and_swow, SysParams_NTSC |
| 12 | + |
| 13 | +NTSC_LINE_PERIOD = SysParams_NTSC["line_period"] # microseconds |
| 14 | +NTSC_FRAME_LINES = 525 |
| 15 | + |
| 16 | + |
| 17 | +def _even_lineinfo(linecount, linelen): |
| 18 | + """Evenly spaced line locations (no wow), with a few lines of padding.""" |
| 19 | + return np.arange(0, (linecount + 4) * linelen, linelen, dtype=np.double) |
| 20 | + |
| 21 | + |
| 22 | +def _output_sample_count(freq, linecount=NTSC_FRAME_LINES, linelen=910, scale=32): |
| 23 | + """Run the locs/wow computation and return (n_output_samples, swow).""" |
| 24 | + lineinfo = _even_lineinfo(linecount, linelen) |
| 25 | + _, swow, arange, _ = _downscale_audio_compute_locs_and_swow( |
| 26 | + lineinfo, |
| 27 | + NTSC_LINE_PERIOD, |
| 28 | + linelen, |
| 29 | + linecount, |
| 30 | + 0.0, # timeoffset (ignored for negative freq) |
| 31 | + freq, |
| 32 | + scale, |
| 33 | + ) |
| 34 | + # arange carries one extra interpolation tick, so samples = len - 1. |
| 35 | + return len(arange) - 1, swow |
| 36 | + |
| 37 | + |
| 38 | +def test_ntsc_locked_rate_is_exactly_2_8_samples_per_line(): |
| 39 | + """freq=-2.8 yields exactly 1470 samples for a full 525-line frame.""" |
| 40 | + n_samples, swow = _output_sample_count(-2.8) |
| 41 | + |
| 42 | + assert n_samples == 1470 # == 525 * 2.8, integer => no drift |
| 43 | + # Evenly spaced lines means unity wow throughout. |
| 44 | + np.testing.assert_allclose(swow, 1.0, atol=1e-9) |
| 45 | + |
| 46 | + |
| 47 | +def test_negative_freq_resolves_to_ntsc_locked_hz(): |
| 48 | + """-2.8 corresponds to ~44055.944 Hz (2.8 x the NTSC line frequency).""" |
| 49 | + line_freq = 1_000_000 / NTSC_LINE_PERIOD |
| 50 | + assert line_freq * 2.8 == 44055.944055944055 |
| 51 | + |
| 52 | + |
| 53 | +def test_default_44100_does_not_frame_lock(): |
| 54 | + """The default 44100 Hz rate is a non-integer 1471.47 samples/frame.""" |
| 55 | + n_samples, _ = _output_sample_count(44100) |
| 56 | + |
| 57 | + # 44100 / (30000/1001) ~= 1471.47, so it cannot equal the locked 1470. |
| 58 | + assert n_samples != 1470 |
| 59 | + assert n_samples == 1471 |
0 commit comments