mirror of
https://github.com/cookiengineer/audacity
synced 2025-04-29 15:19:44 +02:00
Improve octave test framework and refactor loudness test.
Add helper functions "import_from_aud" and "export_to_aud" to de-deplicate common code in tests. The export functions reads back the exported signal to remove the impact of quantization errors during wav export from test results. Signed-off-by: Max Maisel <max.maisel@posteo.de>
This commit is contained in:
parent
ae4189a533
commit
1d728bec89
1
tests/octave/.gitignore
vendored
Normal file
1
tests/octave/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
*.wav
|
@ -125,20 +125,12 @@ end
|
||||
## Test Loudness LUFS mode: block to short and all silent
|
||||
CURRENT_TEST = "Loudness LUFS mode, short silent block";
|
||||
fs= 44100;
|
||||
x = zeros(ceil(fs*0.35), 2);
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
if EXPORT_TEST_SIGNALS
|
||||
audiowrite(cstrcat(pwd(), "/Loudness-LUFS-silence-test.wav"), x, fs);
|
||||
end
|
||||
x1 = zeros(ceil(fs*0.35), 2);
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs, "Loudness-LUFS-silence-test.wav");
|
||||
aud_do("LoudnessNormalization: LUFSLevel=-23 DualMono=1 NormalizeTo=0 StereoIndependent=0\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=2\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(2);
|
||||
do_test_equ(y, x, "identity");
|
||||
|
||||
## Test Loudness LUFS mode: stereo dependent
|
||||
@ -146,76 +138,50 @@ CURRENT_TEST = "Loudness LUFS mode, keep DC and stereo balance";
|
||||
randn("seed", 1);
|
||||
# Include some silence in the test signal to test loudness gating
|
||||
# and vary the overall loudness over time.
|
||||
x = [0.1*randn(15*fs, 2).', zeros(5*fs, 2).', 0.1*randn(15*fs, 2).'].';
|
||||
x(:,1) = x(:,1) .* sin(2*pi/fs/35*(1:1:35*fs)).' .* 1.2;
|
||||
x(:,2) = x(:,2) .* sin(2*pi/fs/35*(1:1:35*fs)).';
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
if EXPORT_TEST_SIGNALS
|
||||
audiowrite(cstrcat(pwd(), "/Loudness-LUFS-stereo-test.wav"), x, fs);
|
||||
end
|
||||
x1 = [0.1*randn(15*fs, 2).', zeros(5*fs, 2).', 0.1*randn(15*fs, 2).'].';
|
||||
x1(:,1) = x1(:,1) .* sin(2*pi/fs/35*(1:1:35*fs)).' .* 1.2;
|
||||
x1(:,2) = x1(:,2) .* sin(2*pi/fs/35*(1:1:35*fs)).';
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs, "Loudness-LUFS-stereo-test.wav");
|
||||
aud_do("LoudnessNormalization: LUFSLevel=-23 DualMono=1 NormalizeTo=0 StereoIndependent=0\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=2\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(2);
|
||||
do_test_equ(calc_LUFS(y, fs), -23, "loudness", LUFS_epsilon);
|
||||
do_test_neq(calc_LUFS(y(:,1), fs), calc_LUFS(y(:,2), fs), "stereo balance", 1);
|
||||
|
||||
## Test Loudness LUFS mode, stereo independent
|
||||
CURRENT_TEST = "Loudness LUFS mode, stereo independence";
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs);
|
||||
aud_do("LoudnessNormalization: LUFSLevel=-23 DualMono=0 NormalizeTo=0 StereoIndependent=1\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=2\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(2);
|
||||
# Independently processed stereo channels have half the target loudness.
|
||||
do_test_equ(calc_LUFS(y(:,1), fs), -26, "channel 1 loudness", LUFS_epsilon);
|
||||
do_test_equ(calc_LUFS(y(:,2), fs), -26, "channel 2 loudness", LUFS_epsilon);
|
||||
|
||||
## Test Loudness LUFS mode: mono as mono
|
||||
CURRENT_TEST = "Test Loudness LUFS mode: mono as mono";
|
||||
x = x(:,1);
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
if EXPORT_TEST_SIGNALS
|
||||
audiowrite(cstrcat(pwd(), "/Loudness-LUFS-mono-test.wav"), x, fs);
|
||||
end
|
||||
x1 = x1(:,1);
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs, "Loudness-LUFS-mono-test.wav");
|
||||
aud_do("LoudnessNormalization: LUFSLevel=-26 DualMono=0 NormalizeTo=0 StereoIndependent=1\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=1\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(1);
|
||||
do_test_equ(calc_LUFS(y, fs), -26, "loudness", LUFS_epsilon);
|
||||
|
||||
## Test Loudness LUFS mode: mono as dual-mono
|
||||
CURRENT_TEST = "Test Loudness LUFS mode: mono as dual-mono";
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs);
|
||||
aud_do("LoudnessNormalization: LUFSLevel=-26 DualMono=1 NormalizeTo=0 StereoIndependent=0\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=1\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(1);
|
||||
# This shall be 3 LU quieter as it is compared to strict spec.
|
||||
do_test_equ(calc_LUFS(y, fs), -29, "loudness", LUFS_epsilon);
|
||||
|
||||
## Test Loudness LUFS mode: multi-rate project
|
||||
CURRENT_TEST = "Test Loudness LUFS mode: multi-rate project";
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
audiowrite(TMP_FILENAME, x1, fs);
|
||||
x = audioread(TMP_FILENAME);
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
@ -228,6 +194,7 @@ audiowrite(TMP_FILENAME, x1, fs1);
|
||||
if EXPORT_TEST_SIGNALS
|
||||
audiowrite(cstrcat(pwd(), "/Loudness-LUFS-stereo-test-8kHz.wav"), x1, fs1);
|
||||
end
|
||||
x1 = audioread(TMP_FILENAME);
|
||||
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
@ -255,36 +222,22 @@ do_test_neq(calc_LUFS(y1(:,1), fs), calc_LUFS(y1(:,2), fs), "stereo balance trac
|
||||
CURRENT_TEST = "Loudness RMS mode, stereo independent";
|
||||
randn("seed", 1);
|
||||
fs= 44100;
|
||||
x = 0.1*randn(30*fs, 2);
|
||||
x(:,1) = x(:,1) * 0.6;
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
if EXPORT_TEST_SIGNALS
|
||||
audiowrite(cstrcat(pwd(), "/Loudness-RMS-test.wav"), x, fs);
|
||||
end
|
||||
x1 = 0.1*randn(30*fs, 2);
|
||||
x1(:,1) = x1(:,1) * 0.6;
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs, "Loudness-RMS-test.wav");
|
||||
aud_do("LoudnessNormalization: RMSLevel=-20 DualMono=0 NormalizeTo=1 StereoIndependent=1\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=2\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(2);
|
||||
do_test_equ(20*log10(sqrt(sum(y(:,1).*y(:,1)/length(y)))), -20, "channel 1 RMS");
|
||||
do_test_equ(20*log10(sqrt(sum(y(:,2).*y(:,2)/length(y)))), -20, "channel 2 RMS");
|
||||
|
||||
## Test Loudness RMS mode: stereo dependent
|
||||
CURRENT_TEST = "Loudness RMS mode, stereo dependent";
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
|
||||
remove_all_tracks();
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
x = export_to_aud(x1, fs);
|
||||
aud_do("LoudnessNormalization: RMSLevel=-22 DualMono=1 NormalizeTo=1 StereoIndependent=0\n");
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=2\n"));
|
||||
system("sync");
|
||||
|
||||
y = audioread(TMP_FILENAME);
|
||||
y = import_from_aud(2);
|
||||
# Stereo RMS must be calculated in quadratic domain.
|
||||
do_test_equ(20*log10(sqrt(sum(rms(y).^2)/size(y)(2))), -22, "RMS");
|
||||
do_test_neq(20*log10(rms(y(:,1))), 20*log10(rms(y(:,2))), "stereo balance", 1);
|
||||
|
@ -29,10 +29,13 @@ if nargin == 2
|
||||
end
|
||||
|
||||
## Initialization and helper functions
|
||||
global TMP_FILENAME;
|
||||
global EXPORT_TEST_SIGNALS;
|
||||
UID=num2str(getuid());
|
||||
PIPE_TO_PATH=strcat("/tmp/audacity_script_pipe.to.", UID);
|
||||
PIPE_FROM_PATH=strcat("/tmp/audacity_script_pipe.from.", UID);
|
||||
TMP_FILENAME=strcat(pwd(), "/tmp.wav");
|
||||
EXPORT_TEST_SIGNALS = false;
|
||||
|
||||
printf("Open scripting pipes, this may freeze if Audacity does not run...\n");
|
||||
|
||||
@ -74,6 +77,27 @@ function select_tracks(num, count)
|
||||
aud_do(sprintf("SelectTracks: Track=%d TrackCount=%d Mode=Set\n", num, count));
|
||||
end
|
||||
|
||||
function x_in = import_from_aud(channels)
|
||||
global TMP_FILENAME;
|
||||
aud_do(cstrcat("Export2: Filename=\"", TMP_FILENAME, "\" NumChannels=", ...
|
||||
num2str(channels), "\n"));
|
||||
system("sync");
|
||||
x_in = audioread(TMP_FILENAME);
|
||||
end
|
||||
|
||||
function x_out = export_to_aud(x, fs, name = "")
|
||||
global TMP_FILENAME;
|
||||
global EXPORT_TEST_SIGNALS;
|
||||
audiowrite(TMP_FILENAME, x, fs);
|
||||
if EXPORT_TEST_SIGNALS && length(name) != 0
|
||||
audiowrite(cstrcat(pwd(), "/", name), x, fs);
|
||||
end
|
||||
# Read it back to avoid quantization-noise in tests
|
||||
x_out = audioread(TMP_FILENAME);
|
||||
aud_do(cstrcat("Import2: Filename=\"", TMP_FILENAME, "\"\n"));
|
||||
select_tracks(0, 100);
|
||||
end
|
||||
|
||||
## Float equal comparison helper
|
||||
function [ret] = float_eq(x, y, eps=0.001)
|
||||
ret = abs(x - y) < eps;
|
||||
@ -99,41 +123,43 @@ function plot_failure(x, y)
|
||||
plot(x, 'r')
|
||||
hold on
|
||||
plot(y, 'b')
|
||||
plot(log10(abs(x-y)), 'g')
|
||||
delta = abs(x-y);
|
||||
max(delta)
|
||||
plot(log10(delta), 'g')
|
||||
hold off
|
||||
legend("Audacity", "Octave", "log-delta", "location", "southeast")
|
||||
input("Press enter to continue", "s")
|
||||
end
|
||||
|
||||
function do_test_equ(x, y, msg, eps=0.001, skip = false)
|
||||
function do_test_equ(x, y, msg = "", eps = 0.001, skip = false)
|
||||
cmp = all(all(float_eq(x, y, eps)));
|
||||
if do_test(cmp, msg, skip) == 0
|
||||
plot_failure(x, y);
|
||||
end
|
||||
end
|
||||
|
||||
function do_test_neq(x, y, msg, eps=0.001, skip = false)
|
||||
function do_test_neq(x, y, msg = "", eps = 0.001, skip = false)
|
||||
cmp = all(all(!float_eq(x, y, eps)));
|
||||
if do_test(cmp, msg, skip) == 0
|
||||
plot_failure(x, y);
|
||||
end
|
||||
end
|
||||
|
||||
function do_test_gte(x, y, msg, skip = false)
|
||||
function do_test_gte(x, y, msg = "", skip = false)
|
||||
cmp = all(all(x >= y));
|
||||
if do_test(cmp, msg, skip) == 0
|
||||
plot_failure(x, y);
|
||||
end
|
||||
end
|
||||
|
||||
function do_test_lte(x, y, msg, skip = false)
|
||||
function do_test_lte(x, y, msg = "", skip = false)
|
||||
cmp = all(all(x <= y));
|
||||
if do_test(cmp, msg, skip) == 0
|
||||
plot_failure(x, y);
|
||||
end
|
||||
end
|
||||
|
||||
function result = do_test(result, msg, skip = false)
|
||||
function result = do_test(result, msg = "", skip = false)
|
||||
global TESTS_RUN;
|
||||
global TESTS_FAILED;
|
||||
global TESTS_SKIPPED;
|
||||
|
Loading…
x
Reference in New Issue
Block a user