VA_example_ppa.m 10.1 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

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
9
output_folder = fullfile( 'C:\Users\jonas\sciebo\Thesis stuff\auralization\resources', 'example_ppa/s1_r1' );
10
frame_rate = 128 / 44100; % block length / sampling frequency
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
11
12
13
14
sort_by_date = false;

record_paths = true;
ppa_diffraction_model = 'utd';
15

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
16
17
S = 1;
R = 1;
henryjandrew's avatar
henryjandrew committed
18

19
ppa_example_mode = questdlg( 'Please select', 'VA example ppa mode selection', ...
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
20
    'simulation', 'auralization', 'both', 'auralization');
21

Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
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

%% Prepare run data
if any( strcmpi( ppa_example_mode, { 'simulation', 'both' } ) )
    
    if ~exist( output_folder, 'dir' )
        mkdir( output_folder )
    end
        
    ppa_folder = '../../../dist/win32-x64.vc12/bin/UrbanTrajectory';
    
    if ~exist( ppa_folder, 'dir' )
        ppa_folder = '../../../ITAGeometricalAcoustics/ITAPropagationPathSim/tests/CombinedModel/UrbanTrajectory';
    end
    
    if ~exist( ppa_folder, 'dir' )
        error( 'Could not find trajectory source folder "%s".', ppa_folder )
    end
    
    file_listing = dir( strcat( ppa_folder, '/*.json' ) );
    
    f = ita_ANSI_center_frequencies;
    c = 343;
    
    all_path_names = cell(1);
    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
    all_paths_data = struct;
    
    
    N = numel( file_listing );
    disp( [ 'Simulation result duration: ' num2str( N * frame_rate ) ' s' ] )
    
    h = waitbar( 0, 'Hold on, running simulation of path data for each frame' );
    
    % Iterate over frames
    n_continue = 1;
    for n = n_continue:N
                
        % Load propagation paths for current frame
        ppa_file_path = fullfile( file_listing( n ).folder, file_listing( n ).name );
        pps = ita_propagation_load_paths( ppa_file_path ); %pps = struct containing the current time frame
        pps = ita_propagation_paths_add_identifiers( pps );
        
        if n == n_continue
            pps_new = pps;
            pps_del = [];
            pps_common = [];
        else
            [ pps_new, pps_del, pps_common ] = ita_propagation_paths_diff( pps_last, pps );
70
        end
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
71
        pps_last = pps;
72
73
        
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
74
75
76
77
78
79
80
81
        % Update source (first anchor)
        if isa( pps( 1 ).propagation_anchors, 'struct' )
            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
        else
            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
82
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
83
        paths_update = struct();
84
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
85
86
87
88
89
90
91
92
93
        % 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
94
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
95
        for p = 1:numel( pps_new )
96
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
97
98
            pp = pps_new( p ); % Propagation path
            pu = struct(); % Path update
99
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
100
101
102
103
            % Assemble DSP settings (gain, delay & filter coefficients)
            pu.source = S;
            pu.receiver = R;
            pu.identifier = pp.identifier;
104
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
105
106
            path_count = path_count + 1;
            all_path_names{path_count} = pp.identifier;
107
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
108
109
110
            if( record_paths )
                [ frequency_mags, gain, delay, valid_path, path_data ] = ita_propagation_path_get_data( pp, f, c, 'record_paths' );
                all_paths_data.( strcat( 'path_', pu.identifier ) ) = path_data;
111
            else
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
112
                [ frequency_mags, gain, delay, valid_path ] = ita_propagation_path_get_data( pp, f, c );
113
114
            end
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
115
116
117
            if valid_path
                pu.gain = gain;
                pu.frequency_magnitudes = abs(frequency_mags);
118
            end
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
119
120
121
122
123
124
            pu.frequencies = f;
            pu.delay = delay;
            if isa(pp.propagation_anchors, 'struct')
                pu.position = pp.propagation_anchors( end-1 ).interaction_point( 1:3 ); % next to last anchor
            else
                pu.position = pp.propagation_anchors{ end-1 }.interaction_point( 1:3 ); % next to last anchor
125
            end
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
126
127
            pu.delete = false;
            pu.audible = true;
128
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
129
            paths_update.( strcat( 'path_', pu.identifier ) ) = pu;
130
        end
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
131
132
133
134
135
136
137
138
139
140
        
        for p = 1:numel( pps_common )
            
            pp = pps_common( p ); % Propagation path
            pu = struct(); % Path update
            
            % Assemble DSP settings (gain, delay & filter coefficients)
            pu.source = S;
            pu.receiver = R;
            pu.identifier = pp.identifier;
141
142
            
            if( record_paths )
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
143
144
145
146
                [ frequency_mags, gain, delay, valid_path, 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_path ] = ita_propagation_path_get_data( pp, f, c );
147
148
            end
            
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
            if valid_path
                pu.gain = gain;
                pu.frequency_magnitudes = abs(frequency_mags);
            end
            pu.frequencies = f;
            pu.delay = delay;
            if isa( pp.propagation_anchors, 'struct' )
                pu.position = pp.propagation_anchors( end-1 ).interaction_point( 1:3 ); % next to last anchor
            else
                pu.position = pp.propagation_anchors{ end-1 }.interaction_point( 1:3 ); % next to last anchor
            end
            pu.delete = false;
            pu.audible = true;
            
            paths_update.( strcat( 'path_', pu.identifier ) ) = pu;
164
        end
165
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
166
167
168
169
170
171
        file_name = sprintf( 'frame%04idata.mat', n );
        file_path = fullfile( output_folder, file_name );
        save( file_path, 'paths_update', 'source_pos', 'receiver_pos' ); % save current frame data
        if( record_paths )
            save( file_path, 'all_paths_data', '-append' );
        end
172
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
        waitbar( n / N )
        
    end    
    close( h )
    
    if record_paths
        save( fullfile( output_folder, 'analysis_data.mat' ), 'all_path_names' ) %save variables to file
    end
    
    fprintf( 'Finished generating path data for every frame. Data is saved into separate files in folder ''%s''\n', output_folder );
    
end


%% Run auralization
if any( strcmpi( ppa_example_mode, { 'auralization', 'both' } ) )
        
    % Load data
    
    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 )
    
    if sort_by_date
197
198
199
        frame_datenums = zeros( N, 1 );
        for n=1:N
            frame_datenums( n ) = file_listing( n ).datenum;
200
        end
201
        [ ~, idx ] = sort( frame_datenums );
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
    else
        idx = 1:N;
    end
    
    % Set up VA scene
    
    va = VA;
    va.connect;
    
    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' );
    va.add_search_path( 'C:\Users\jonas\sciebo\Thesis stuff\auralization\resources' );
    
    c = va.get_homogeneous_medium_sound_speed();
    
    R = va.create_sound_receiver( 'PPA_sensor' );
    H = va.create_directivity_from_file( 'ITA-Kunstkopf_HRIR_AP11_Pressure_Equalized_3x3_256.v17.ir.daff' );
    va.set_sound_receiver_directivity( R, H );
    
    S = va.create_sound_source( 'PPA_emitter' );
    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' );
    
    % Run auralization update loop
    for n = 1:N
        
        idx_current = idx( n );
        
        % Make source_pos, receiver_pos and paths_update available for this
        % frame
        load( fullfile( output_folder, file_listing( idx_current ).name ), '-mat' );
        
        
        % Update all propagation paths
        source_pos_OpenGL = ita_matlab2openGL( source_pos( 1:3 )' );
        receiver_pos_OpenGL = ita_matlab2openGL( receiver_pos( 1:3 )' );
        
        % Update receiver (last anchor)
        va.set_sound_source_position( S, source_pos_OpenGL );
        va.set_sound_receiver_position( R, receiver_pos_OpenGL );
        
        single_path_id = 'path_003ca6d3a74540310873574908219251';
        if isfield( paths_update, single_path_id )
            single_path_update = struct( 'p', paths_update.( single_path_id ) );
            va.set_rendering_module_parameters( 'MyBinauralOutdoorNoise', single_path_update );
        else
            disp( 'not found, skipping update' )
259
        end
260
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
261
262
263
264
265
266
        % 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 ) );
Dipl.-Ing. Jonas Stienen's avatar
WiP    
Dipl.-Ing. Jonas Stienen committed
267
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
268
        waitbar( n / N )
269
        
Dipl.-Ing. Jonas Stienen's avatar
WIP    
Dipl.-Ing. Jonas Stienen committed
270
271
272
273
274
275
276
277
    end
    
    close( h )
    
    va.disconnect
    disp( 'Stop VA to export simulation results from rendering module(s)' )
    
end