-
Notifications
You must be signed in to change notification settings - Fork 3
/
play_demo.m
185 lines (159 loc) · 5.28 KB
/
play_demo.m
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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
# This file is part of the ZDAC reference implementation
# Author (2020) Marc René Schädler ([email protected])
close all
clear
clc
graphics_toolkit qt;
% Assume 32kHz input with arbitrary precision (double float)
fs = 32000;
quality = 0; % Steers width of the masking threshold filters (0 default, probably useful values -5..1)
entry = 8; % period of entry points in ms
rate = 1024; % soft-limit rate
% Generate a stimulus: Vary frequency and level over time
level = [0 -20]; % dB
period = [1/2000 1/2]; % 16Hz to 16000kHz
signal = (10.^(linspace(level(1),level(2),fs/8)./20).*sin(2.*pi*cumsum(linspace(period(1),period(2),fs/8)))).';
%% Add some noise (to see how the birate reduces)
noiselevel = -90; % dB full-scale
noise = 2.*(rand(size(signal))-0.5);
noise = noise./rms(noise) .* 10.^(noiselevel./20);
signal = signal + noise;
% Only use blocks of 32 samples for later alignment in bitmap
signal = signal(1:floor(numel(signal)/32).*32);
audiowrite('orginal.wav',signal,fs,'BitsPerSample',32);
% Reference: Quantization with 16 bits
audiowrite('reference.wav',signal,fs,'BitsPerSample',16);
signal_ref = audioread('reference.wav');
audiowrite('reference.wav',signal,fs,'BitsPerSample',32);
% Zero-delay audio codec (ZDAC)
%% ENCODER
num_samples = size(signal,1);
num_channels = size(signal,2);
[message bits amplitude_tracker quantnoise_tracker exponent spectral_energy debug_message] = zdaenc(signal, fs, quality, entry, rate);
num_bits = numel(message);
num_significant_bits = sum(bits(1,:));
num_entry_bits = sum(bits(2,:));
num_exponent_bits = sum(bits(3,:));
num_codebook_bits = sum(bits(4,:));
num_stop_bits = sum(bits(5,:));
bits_per_sample = num_bits./num_samples;
bits_per_second = bits_per_sample.*fs;
printf('%.1f %.3f %i %i/%i/%i/%i/%i\n',bits_per_second,bits_per_sample,num_samples,num_bits,num_significant_bits,num_entry_bits,num_exponent_bits,num_codebook_bits);
writebinary('demo.zda', [dec2bin(fs,24)=='1' dec2bin(num_channels,8)=='1' message]);
filesize = stat('demo.zda').size;
printf('binary data written to demo.zda (%d bytes)\n',filesize);
% Colorscheme
linecolors = lines(7);
zerodimfactor = 0.9;
colors = [
linecolors(3,:).*zerodimfactor;
linecolors(3,:);
(linecolors(3,:)+[0 0.15 0]).*zerodimfactor;
(linecolors(3,:)+[0 0.15 0]);
linecolors(7,:).*zerodimfactor;
linecolors(7,:);
linecolors(1,:).*zerodimfactor;
linecolors(1,:);
linecolors(4,:).*zerodimfactor;
linecolors(4,:);
linecolors(5,:).*zerodimfactor;
linecolors(5,:);
[0.5 0.5 0.5];
];
figure('Position',[0 0 1600 800]);
subplot(2,3,[1 2 3]);
plot(bits(1,:),'color',colors(2,:));
hold on;
plot(bits(2,:),'color',colors(6,:));
plot(bits(3,:),'color',colors(8,:));
plot(bits(4,:),'color',colors(10,:));
plot(bits(5,:),'color',colors(12,:));
ylabel('Bit');
xlabel('Sample');
grid on;
title('Contol codes');
legend({'significant' 'entry' 'exponent' 'codebook' 'stop'});
subplot(2,3,4);
bar(log10(histc(sum(bits),[0:40],2)));
yticks(log10(2.^(0:1:15)));
yticklabels(2.^(0:1:15));
ylabel('Absolute frequency');
xlabel('Bit per sample');
grid on;
title('Absolute frequencies of bits per sample');
subplot(2,3,5);
bar([0 1 2 3 4],log10(sum(bits>0,2)));
yticks(log10(2.^(0:1:15)));
yticklabels(2.^(0:1:15));
xticklabels({'significant','entry','exponent','codebook','stop'});
ylabel('Absolute frequency');
xlabel('Control code');
grid on;
title('Control codes: Absolute frequency')
subplot(2,3,6);
bar([0 1 2 3 4],log10(sum(bits,2)));
yticks(log10(2.^(0:1:20)));
yticklabels(2.^(0:1:20));
xticklabels({'significant','entry','exponent','codebook','stop'});
ylabel('Absolute frequency');
xlabel('Control code');
grid on;
title('Control codes: Cumulative bits')
drawnow;
figure('Position',[0 0 1600 800]);
debug_message_padded = [debug_message,11.*ones(1,numel(signal)*16-numel(debug_message))];
bitmap = reshape(debug_message_padded,128,[])+3;
image(bitmap); axis image;
colormap(colors);
grid on
xticks(0:50:size(bitmap,2));
yticks(0:16:size(bitmap,1));
ylabel('bit number');
title('Coloured bitmap: yellow/orange - significant, red - entry, blue - exponent, purple - codebook, green - stop');
drawnow;
printf('clear message and fs\n');
clear message fs
%% DECODER
message = readbinary('demo.zda');
fs = bin2dec('01'(1+message(1:24)));
num_channels = bin2dec('01'(1+message(25:32)));
message = message(33:end);
printf('%i message bits read from demo.zda\n',numel(message));
signal_reconst = zdadec(message, fs, num_channels);
audiowrite('reconstructed.wav',signal_reconst,fs,'BitsPerSample',32);
signal = signal(:,1);
signal_ref = signal_ref(:,1);
signal_reconst = signal_reconst(:,1);
quantnoise_ref = signal-signal_ref;
quantnoise = signal-signal_reconst;
figure('Position',[0 0 1600 800]);
subplot(4,1,1);
plot(signal);
hold on;
plot(signal_ref);
plot(quantnoise_ref);
legend({'Original' 'Reconstructed' 'Difference'});
ylabel('Amplitude');
title('Reference 16 bit/sample');
subplot(4,1,2);
plot(signal);
hold on;
plot(signal_reconst);
plot(quantnoise);
legend({'Original' 'Reconstructed' 'Difference'});
ylabel('Amplitude');
title('ZDAC')
subplot(4,1,3);
plot(10*log10(max(spectral_energy,[],1)));
ylim([-100 0]);
ylabel('Energy / dB');
title('Maximum of spectral energy');
subplot(4,1,4);
plot(amplitude_tracker);
hold on;
plot(quantnoise_tracker);
hold on;
plot(exponent);
legend({'Amplitude' 'Quantnoise' 'Exponent'});
ylabel('log2(amplitude)');
title('Tracker');