VA_example_ppa.m 10.3 KB
Newer Older
1
2
3
4
5
6
7
8
%% VA offline simulation/auralization example for outputs of the propagation path algorithm

% Requires VA to run with a virtual audio device that can be triggered by
% the user. Also the generic path prototype rendering module(s) has to record the output
% to hard drive.

% Requires ITA-Toolbox, obtain from http://www.ita-toolbox.org

9
10
record_paths = true;

11
ppa_folder = '../../../dist/win32-x64.vc12/bin/UrbanTrajectory';
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
12
output_folder = 'example_ppa_out';
13

14
15
16
17
18
if ~exist( ppa_folder, 'dir' )
    ppa_folder = '../../../ITAGeometricalAcoustics/ITAPropagationPathSim/tests/CombinedModel/UrbanTrajectory';
end

if ~exist( ppa_folder, 'dir' )
19
    error( 'Could not find trajectory source folder "%s".', ppa_folder )
20
end
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
21

22
ppa_diffraction_model = 'utd';
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
23
frame_rate = 128 / 44100; % here: depends on block size and sample rate
24

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
25
%% Prepare run data
26
27
28
29

file_listing = dir( strcat( ppa_folder, '/*.json' ) );

f = ita_ANSI_center_frequencies;
30
c = 343;
31

henryjandrew's avatar
henryjandrew committed
32
all_path_names = cell(1);
33
path_count = 0; %The total number of paths, NOTE -NOT a count of paths in current frame, if paths are deleted, they are not removed from this count
34
source_str = struct; %struct with fields of source ID's and data of source positions for each frame
henryjandrew's avatar
henryjandrew committed
35
receiver_str = struct;
36
all_paths_data = struct;
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
37
38
S = 1;
R = 1;
henryjandrew's avatar
henryjandrew committed
39

40

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
41
N = numel( file_listing );
42
43
disp( [ 'Simulation result duration: ' num2str( N * frame_rate ) ' s' ] )

henryjandrew's avatar
henryjandrew committed
44
h = waitbar( 0, 'Hold on, running simulation of path data for each frame' );
45
46

% Iterate over frames
47
n_continue = 1;
henryjandrew's avatar
henryjandrew committed
48
49
50
51
for n = n_continue:N %loop over frames
    all_path_name = [];
    path_number = 1;
    
52
53
    % Load propagation paths for current frame
    ppa_file_path = fullfile( file_listing( n ).folder, file_listing( n ).name );
54
    pps = ita_propagation_load_paths( ppa_file_path ); %pps = struct containing the current time frame
55
56
    pps = ita_propagation_paths_add_identifiers( pps );
    
henryjandrew's avatar
henryjandrew committed
57
    if n == n_continue
58
59
60
61
62
63
64
        pps_new = pps;
        pps_del = [];
        pps_common = [];
    else
        [ pps_new, pps_del, pps_common ] = ita_propagation_paths_diff( pps_last, pps );
    end
    pps_last = pps;
65
    
66
    
67
    % Update source (first anchor)
68
    if isa( pps( 1 ).propagation_anchors, 'struct' )
69
70
        source_pos = pps( 1 ).propagation_anchors( 1 ).interaction_point(1:3); % OpenGL coordinates?! -> transform using 
        receiver_pos = pps( 1 ).propagation_anchors( end ).interaction_point(1:3); % OpenGL coordinates?! -> transform using 
71
    else
72
73
74
75
76
        source_pos = pps( 1 ).propagation_anchors{ 1 }.interaction_point(1:3); % OpenGL coordinates?! -> transform using 
        receiver_pos = pps( 1 ).propagation_anchors{ end }.interaction_point(1:3); % OpenGL coordinates?! -> transform using 
    end    
    source_str.(strcat('source_',num2str(S))) = source_pos;
    receiver_str.(strcat('receiver_',num2str(R))) = receiver_pos; 
77
        
78
79
    paths_update = struct();
    
80
81
82
83
84
85
86
87
88
89
90
    % Delete non-available paths
    for p = 1:numel( pps_del )  
        pu = struct(); % Path update
        pu.source = S;
        pu.receiver = R;
        pu.identifier = pps_del( p ).identifier;
        pu.delete = true;
        paths_update.( strcat( 'path_', pu.identifier ) ) = pu;
    end
    
    for p = 1:numel( pps_new )
91
        
henryjandrew's avatar
henryjandrew committed
92
        pp = pps_new( p ); % Propagation path     
93
94
95
96
97
        pu = struct(); % Path update
        
        % Assemble DSP settings (gain, delay & filter coefficients)
        pu.source = S;
        pu.receiver = R;
98
        pu.identifier = pp.identifier;
henryjandrew's avatar
henryjandrew committed
99
100
101
        
        path_count = path_count + 1;
        all_path_names{path_count} = pp.identifier;
102
                
103
104
105
106
107
108
109
        if( record_paths )
            [ frequency_mags, gain, delay, valid_p, path_data ] = ita_propagation_path_get_data( pp, f, c, 'record_paths' );
            all_paths_data.( strcat( 'path_', pu.identifier ) ) = path_data;
        else
            [ frequency_mags, gain, delay, valid_p ] = ita_propagation_path_get_data( pp, f, c );
        end
        %{
110
111
112
113
        if ~valid_p %catch for error in ita_propagation_path_get_data
            warning( 'Error in ita_propagation_path_get_data, found invalid path ''%s'', skipping', pp.identifier );
            continue
        end
114
115
116
117
118
        %}
        if valid_p
            pu.gain = gain;
            pu.frequency_magnitudes = abs(frequency_mags);   
        end
119
        pu.frequencies = f;
120
        pu.delay = delay;
121
122
        if isa(pp.propagation_anchors, 'struct')
            pu.position = pp.propagation_anchors( end-1 ).interaction_point( 1:3 ); % next to last anchor            
123
        else
124
            pu.position = pp.propagation_anchors{ end-1 }.interaction_point( 1:3 ); % next to last anchor
125
        end
126
127
128
        pu.delete = false;
        pu.audible = true;
        
henryjandrew's avatar
henryjandrew committed
129
        paths_update.( strcat( 'path_', pu.identifier ) ) = pu;       
130
131
132
133
    end
    
    for p = 1:numel( pps_common )
        
henryjandrew's avatar
henryjandrew committed
134
        pp = pps_common( p ); % Propagation path     
135
136
137
138
139
140
141
        pu = struct(); % Path update
        
        % Assemble DSP settings (gain, delay & filter coefficients)
        pu.source = S;
        pu.receiver = R;
        pu.identifier = pp.identifier;
                
142
143
144
145
146
147
148
        if( record_paths )
            [ frequency_mags, gain, delay, valid_p, path_data ] = ita_propagation_path_get_data( pp, f, c, 'record_paths' );
            all_paths_data.( strcat( 'path_', pu.identifier ) ) = path_data;
        else
            [ frequency_mags, gain, delay, valid_p ] = ita_propagation_path_get_data( pp, f, c );
        end
        %{
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
149
150
        if ~valid_p %catch for error in ita_propagation_path_get_data
            warning( 'Error in ita_propagation_path_get_data, found invalid path ''%s'', skipping', pp.identifier );
151
152
            continue
        end
153
154
155
156
157
        %}
        if( valid_p )
            pu.gain = gain;
            pu.frequency_magnitudes = abs(frequency_mags);
        end
158
        pu.frequencies = f;
159
        pu.delay = delay;
160
        if isa(pp.propagation_anchors, 'struct')
161
            pu.position = pp.propagation_anchors( end-1 ).interaction_point( 1:3 ); % next to last anchor            
162
        else
163
            pu.position = pp.propagation_anchors{ end-1 }.interaction_point( 1:3 ); % next to last anchor
164
        end
165
        pu.delete = false;
166
167
        pu.audible = true;
        
168
        paths_update.( strcat( 'path_', pu.identifier ) ) = pu;
169
    end
170
    
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
171
172
    file_name = sprintf( 'frame%04idata.mat', n );
    file_path = fullfile( output_folder, file_name );
173
    save( file_path, 'paths_update', 'source_str', 'receiver_str' ); %save current frame data
174
    if( record_paths )
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
175
        save( file_path, 'all_paths_data', '-append' );
176
177
    end
    
178
    waitbar( n / N )
henryjandrew's avatar
henryjandrew committed
179
180
181
end

close( h )
182
save( 'example_ppa_out\example_ppa_output_data.mat', 'all_path_names' ); %save variables to file
henryjandrew's avatar
henryjandrew committed
183
184
185

disp('Finished generating path data for every frame. Data is saved in struct "run_data".'); 

Dipl.-Ing. Jonas Stienen's avatar
Dipl.-Ing. Jonas Stienen committed
186

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
187
%% Run auralization
henryjandrew's avatar
henryjandrew committed
188

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
189
190
191
192
193
194
195
196
197
198
file_listing = dir( strcat( output_folder, '/frame*data.mat' ) );
N = numel( file_listing );
fprintf( 'Found data on %i frames in folder ''%s''\n', N, output_folder )

frame_datenums = [];
for n=1:N
    frame_datenums = [ frame_datenums file_listing( n ).datenum ];
end
[ ~, idx ] = sort( frame_datenums );

199
load( 'example_ppa_out\example_ppa_output_data.mat', 'all_path_names' )
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216

va = VA;

va.connect;
dry_run = false;

va.add_search_path( 'D:/Users/andrew/dev/ITASuite/VA/VACore/data' );
va.add_search_path( 'D:/Users/andrew/dev/ITASuite/VA/VAMatlab/matlab' );
va.add_search_path( 'C:/dev/VA/VACore/data' );
va.add_search_path( 'D:/Users/stienen/dev/VA/VACore/data' );
va.add_search_path( 'C:\ITASoftware\Raven\RavenDatabase\SoundDatabase' );

c = va.get_homogeneous_medium_sound_speed();

R = va.create_sound_receiver( 'PPA_sensor' );
H = va.create_directivity_from_file( 'ITA_Artificial_Head_5x5_44kHz_128.v17.ir.daff' );
va.set_sound_receiver_directivity( R, H );
217

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
218
219
220
221
222
223
224
225
226
227
228
229
230
S = va.create_sound_source( 'PPA_emitter' );
%X = va.create_signal_source_buffer_from_file( 'WelcomeToVA.wav' );
X = va.create_signal_source_buffer_from_file( 'LKW Leerlauf 2.wav' );

va.set_signal_source_buffer_playback_action( X, 'play' )
va.set_signal_source_buffer_looping( X, true );
va.set_sound_source_signal_source( S, X )

manual_clock = 0;
va.set_core_clock( 0 );
h = waitbar( 0, 'Hold on, running auralisation using generated data' );  

for n = 1:N
henryjandrew's avatar
henryjandrew committed
231
    
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
232
    idx_current = idx( n );
233
    load( fullfile( output_folder, file_listing( idx_current ).name ), '-mat' );
234
    
235
236
    source_pos = source_str.(strcat('source_',num2str(S)));
    receiver_pos = receiver_str.(strcat('receiver_',num2str(R)));
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
237
238
    
    % Update all propagation paths
239
240
    source_pos_OpenGL = ita_matlab2openGL( source_pos' );
    receiver_pos_OpenGL = ita_matlab2openGL( receiver_pos' );
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
241

242
243
    va.lock_update
    
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
244
245
246
247
    % Update receiver (last anchor)
    va.set_sound_source_position( S, source_pos_OpenGL );
    va.set_sound_receiver_position( R, receiver_pos_OpenGL );

248
    va.set_rendering_module_parameters( 'MyBinauralOutdoorNoise', paths_update );
249
250
    
    va.unlock_update
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
251
252
253
254
255
256
257
258
259

    % Increment core clock
    manual_clock = manual_clock + frame_rate;    
    va.call_module( 'manualclock', struct( 'time', manual_clock ) );

    % Process audio chain by incrementing one block
    va.call_module( 'virtualaudiodevice', struct( 'trigger', true ) );

    waitbar( n / N ) 
260

261
end
262

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
263
va.disconnect
264
disp( 'Stop VA to export simulation results from rendering module(s)' )
265
266
267
268
269



%%
function path_name = get_path( path_struct )
270
271
    path_data = path_struct.propagation_anchors;
    num_interactions = numel( path_data );
272
273
    path_name = '';
    for i = 1:num_interactions
274
275
276
277
278
279
        if isa( path_data, 'struct' )
            t = path_data(i);            
        else
            t = path_data{i};
        end
        switch t.anchor_type
280
            case 'source'
281
                ID = t.name;
282
283
                path_name = strcat( path_name, 'SRC', num2str(ID), '_' );
            case 'receiver'
284
                ID = t.name;
285
286
                path_name = strcat( path_name, 'RCVR', num2str(ID) );
            case 'specular_reflection'
287
                ID = t.polygon_id;
288
289
                path_name = strcat( path_name, 'SR', num2str(ID), '_' );
            case 'outer_edge_diffraction'
290
291
                ID1 = t.main_wedge_face_id;
                ID2 = t.opposite_wedge_face_id;
292
293
294
295
296
                path_name = strcat( path_name, 'EDMF', num2str(ID1), 'OF', num2str(ID2), '_' );
        end
    end
end

297
298
299
300
301
302
%{
function absorption = readMaterial(name)
    path = 'C:\ITASoftware\Raven\RavenDatabase\MaterialDatabase';
    data = dlmread( fullfile(path,name), ',' );
end
%}