Commit 4a219d33 authored by jonasstienen's avatar jonasstienen
Browse files

Manually adding OpenDAFF repository changes

parent 03374612
%% Generates examplary DAFF files of various content type and shape
% 5x5 degree grid resolution
alpha_res = 5;
alpha_res = 5;
beta_res = 5;
channels = 1;
......@@ -20,6 +20,7 @@ unity_dft_config.channels = 1;
unity_dft_config.freqs = [20 25 31.5 40 50 63 80 100 125 160 ...
200 250 315 400 500 630 800 1000 1250 1600 ...
2000 2500 3150 4000 5000 6300 8000 10000 12500 16000 20000];
unity_dft_config.gain = 0.5;
daffv17_write('filename', 'ExampleUnityOmni_ThirdOctave.v17.ms.daff', ...
'content', 'ms', ...
'datafunc', @dfUnityMS, ...
......@@ -96,14 +97,30 @@ daffv17_write('filename', 'ExampleShortDiracOmni_48kHz.v17.ir.daff', ...
disp( ' ' )
%%
dirac_ir_config.numsamples = 128;
dirac_ir_config.channels = 2;
dirac_ir_config.samplerate = 44100;
daffv17_write('filename', 'ExampleMultiChannelDiracOmni_2ch_128_44kHz.v17.ir.daff', ...
dirac_ir_config.numsamples = 4;
dirac_ir_config.channels = channels;
dirac_ir_config.samplerate = 48000;
daffv17_write('filename', 'ExampleShortDiracOmni_48kHz.v17.ir.daff', ...
'content', 'ir', ...
'datafunc', @dfDiracIR, ...
'userdata', dirac_ir_config, ...
'channels', dirac_ir_config.channels, ...
'channels', channels, ...
'alphares', alpha_res, ...
'betares', beta_res, ...
'orient', default_orient, ...
'metadata', metadata, ...
'quantization', 'float32' );
disp( ' ' )
%%
dirac_hrir_config.numsamples = 128;
dirac_hrir_config.channels = 2;
dirac_hrir_config.samplerate = 44100;
daffv17_write('filename', 'ExampleDiracHRIR_128_44kHz.v17.ir.daff', ...
'content', 'ir', ...
'datafunc', @dfDiracIR, ...
'userdata', dirac_hrir_config, ...
'channels', dirac_hrir_config.channels, ...
'alphares', alpha_res, ...
'betares', beta_res, ...
'orient', default_orient, ...
......@@ -147,6 +164,37 @@ daffv17_write('filename', 'ExampleFigureOfEightSide.v17.ms.daff', ...
'quantization', 'float32' );
disp( ' ' )
%% Bunny looking down
metadata_bunny = metadata;
metadata_bunny = daffv17_add_metadata( metadata_bunny, 'BunnyNose (View)', 'String', 'down' );
metadata_bunny = daffv17_add_metadata( metadata_bunny, 'BunnyEars (Up)', 'String', 'front' );
daffv17_write('filename', 'ExampleBunnyLookingDown.v17.ms.daff', ...
'content', 'ms', ...
'datafunc', @dfBunny, ...
'channels', channels, ...
'alphares', alpha_res, ...
'betares', beta_res, ...
'orient', default_orient, ...
'metadata', metadata_bunny, ...
'quantization', 'float32' );
disp( ' ' )
%% Bunny looking to the front
metadata_bunny = metadata;
metadata_bunny = daffv17_add_metadata( metadata_bunny, 'BunnyNose (View)', 'String', 'front' );
metadata_bunny = daffv17_add_metadata( metadata_bunny, 'BunnyEars (Up)', 'String', 'up' );
daffv17_write('filename', 'ExampleBunnyLookingFront.v17.ms.daff', ...
'content', 'ms', ...
'datafunc', @dfBunny, ...
'channels', channels, ...
'alphares', alpha_res, ...
'betares', beta_res, ...
'orient', [ 0 -90 0 ], ... % Procedure: how do I have to turn myself to look match with the data. Pitch down by 90 degree as Bunny is looking down by default.
'metadata', metadata_bunny, ...
'quantization', 'float32' );
disp( ' ' )
%%
daffv17_write('filename', 'ExampleLowPass3dBOmni.v17.ms.daff', ...
'content', 'ms', ...
......
......@@ -431,6 +431,11 @@ function [] = daffv17_write( varargin )
% integers but within epsilon
x = cell( round( args.alphapoints ), round( args.betapoints ), args.channels );
% Speed up for itaHRTF class
if isa( args.userdata, 'itaHRTF' )
args.userdata = args.userdata.buildsearchdatabase;
end
disp( 'Starting to gather data via callback function, this might take a while ...' )
for b=1:args.betapoints
tic
......
......@@ -16,9 +16,15 @@ function [ freqs, mags, metadata ] = dfUnityMS( ~, ~, unity_ms_config )
mags = zeros( channels, numel( freqs ) );
metadata = [];
if isfield( unity_ms_config, 'gain' )
gain = unity_ms_config.gain;
else
gain = 1.0;
end
for c=1:channels
for f=1:length(freqs)
mags(c,f) = 1.0;
mags(c,f) = gain;
end
end
end
%% Prepare
% Note: please make BRAS resource files available
% URL: https://depositonce.tu-berlin.de/handle/11303/7506.2
if ~exist( 'IR', 'var' )
load( 'Genelec8020_DAF_2016_1x1_64442_IR_front_pole.mat' )
end
BRAS_Genelec8020_sampling_rate = 44100;
BRAS_Genelec8020_speed_of_sound = 341.0; % m/s
BRAS_Genelec8020_measurement_distance = 1.8; % m
BRAS_Genelec8020_delay_samples = BRAS_Genelec8020_sampling_rate * BRAS_Genelec8020_measurement_distance / BRAS_Genelec8020_speed_of_sound;
BRAS_Genelec8020_IR_userdata = struct();
BRAS_Genelec8020_IR_userdata.IR = IR;
BRAS_Genelec8020_IR_userdata.Phi = Phi;
BRAS_Genelec8020_IR_userdata.Theta = Theta;
BRAS_Genelec8020_IR_userdata.Peak = max( abs( IR ), [], 'all' );
BRAS_Genelec8020_IR_userdata.Scale = false;
BRAS_Genelec8020_IR_userdata.NormalizeFront = false;
if ~exist( 'MPS', 'var' ) || ~exist( 'Frequency', 'var' )
load( 'Genelec8020_DAF_2016_1x1_64442_MPS_front_pole.mat' )
end
BRAS_Genelec8020_MPS_userdata = struct();
BRAS_Genelec8020_MPS_userdata.MPS = MPS;
BRAS_Genelec8020_MPS_userdata.Frequency = Frequency;
BRAS_Genelec8020_MPS_userdata.Phi = Phi;
BRAS_Genelec8020_MPS_userdata.Theta = Theta;
BRAS_Genelec8020_MPS_userdata.Peak = max( abs( MPS ), [], 'all' );
BRAS_Genelec8020_MPS_userdata.Scale = false;
BRAS_Genelec8020_MPS_userdata.NormalizeFront = false;
addpath( '../..' ) % Find daffv17_write and daffv17_add_metadata function
% @todo correct!
BRAS_metadata_base = [];
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'Description', 'String', 'BRAS Genelec 8020' );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'Creation date', 'String', date );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'License', 'String', 'CC BY-NC 4.0' );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'CC License Deed', 'String', 'https://creativecommons.org/licenses/by-nc/4.0/' );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'Generation script', 'String', 'Opendaff-v1.7/matlab/directivities/BRAS/BRAS_Genelec8020.m' );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'Web Resource (2016)', 'String', 'https://depositonce.tu-berlin.de/handle/11303/7506.2' );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'measurement_distance', 'Float', BRAS_Genelec8020_measurement_distance );
BRAS_metadata_base = daffv17_add_metadata( BRAS_metadata_base, 'delay_samples', 'Float', BRAS_Genelec8020_delay_samples );
%% Impulse response (untouched)
daffv17_write( 'filename', 'Genelec8020_DAF_2016_1x1.v17.ir.daff', ...
'datafunc', @df_BRAS_directivity_ir, ...
'userdata', BRAS_Genelec8020_IR_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'ir', ...
'alphares', 1, ...
'betares', 1, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
% Verification
daff_dir = DAFF( 'Genelec8020_DAF_2016_1x1.v17.ir.daff' );
Genelec8020_front_verify = itaAudio( 1 );
Genelec8020_front_verify.timeData( :, 1 ) = daff_dir.nearest_neighbour_record( 0, 0 )';
Genelec8020_front_verify.timeData( :, 2 ) = IR( :, and( Phi == 0, Theta == 0 ) );
Genelec8020_front_verify.channelNames = { 'DAFF frontal direction', 'BRAS frontal direction' };
Genelec8020_back_verify = itaAudio( 1 );
Genelec8020_back_verify.timeData( :, 1 ) = daff_dir.nearest_neighbour_record( 180, 0 )';
Genelec8020_back_verify.timeData( :, 2 ) = IR( :, and( Phi == 0, Theta == 180 ) );
Genelec8020_back_verify.channelNames = { 'DAFF back direction', 'BRAS back direction' };
Genelec8020_ceil_floor_verify = itaAudio( 1 );
Genelec8020_ceil_floor_verify.timeData( :, 1 ) = daff_dir.nearest_neighbour_record( 0, 90 );
Genelec8020_ceil_floor_verify.timeData( :, 2 ) = IR( :, and( Phi == 0, Theta == 90 ) );
Genelec8020_ceil_floor_verify.timeData( :, 3 ) = daff_dir.nearest_neighbour_record( -90, 0 );
Genelec8020_ceil_floor_verify.timeData( :, 4 ) = IR( :, and( Phi == 180, Theta == 90 ) );
Genelec8020_ceil_floor_verify.channelNames = { 'DAFF ceiling direction (reversed normalization)', 'BRAS ceiling direction', ...
'DAFF floor direction (reversed normalization)', 'BRAS floor direction' };
c = itaAudio( 1 );
c.timeData( :, 1 ) = daff_dir.nearest_neighbour_record( 90, 0 );
c.timeData( :, 2 ) = IR( :, and( Phi == 90, Theta == 90 ) );
c.timeData( :, 3 ) = daff_dir.nearest_neighbour_record( -90, 0 );
c.timeData( :, 4 ) = IR( :, and( Phi == 270, Theta == 90 ) );
c.channelNames = { 'DAFF left direction', 'BRAS left direction', ...
'DAFF right direction', 'BRAS right direction' };
d = itaAudio();
d.timeData( :, 1 ) = daff_dir.nearest_neighbour_record( 135, 45 );
d.timeData( :, 2 ) = IR( :, and( Phi == 45, Theta == 135 ) );
c.channelNames = { 'DAFF rear left elevated direction', 'BRAS rear left elevated direction' };
d.pf
various_directions = ita_merge( Genelec8020_front_verify, Genelec8020_ceil_floor_verify, c, d );
various_directions.pf
prob_channels = ita_merge( Genelec8020_ceil_floor_verify.ch( 3 ), c.ch(4) )
%% Impulse response (scaled by maximum)
BRAS_Genelec8020_IR_userdata.Scale = true;
BRAS_Genelec8020_IR_userdata.NormalizeFront = false;
daffv17_write( 'filename', 'Genelec8020_DAF_2016_1x1_scaled.v17.ir.daff', ...
'datafunc', @df_BRAS_directivity_ir, ...
'userdata', BRAS_Genelec8020_IR_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'ir', ...
'alphares', 1, ...
'betares', 1, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
%% Impulse response (normalized to front direction)
BRAS_Genelec8020_IR_userdata.Scale = false;
BRAS_Genelec8020_IR_userdata.NormalizeFront = true;
daffv17_write( 'filename', 'Genelec8020_DAF_2016_1x1_normalized.v17.ir.daff', ...
'datafunc', @df_BRAS_directivity_ir, ...
'userdata', BRAS_Genelec8020_IR_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'ir', ...
'alphares', 1, ...
'betares', 1, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
%% Impulse response (short, low res, otherwise untouched)
BRAS_Genelec8020_IR_userdata.filter_length = 256;
daffv17_write( 'filename', 'Genelec8020_DAF_2016_5x5_256.v17.ir.daff', ...
'datafunc', @df_BRAS_directivity_ir, ...
'userdata', BRAS_Genelec8020_IR_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'ir', ...
'alphares', 5, ...
'betares', 5, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
%% Generate & export DFT version
daffv17_write( 'filename', 'Genelec8020_DAF_2016_1x1.v17.dft.daff', ...
'datafunc', @df_BRAS_directivity_dft, ...
'userdata', BRAS_Genelec8020_IR_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'dft', ...
'alphares', 1, ...
'betares', 1, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
%% Magnitude & Phase spectrum
daffv17_write( 'filename', 'Genelec8020_DAF_2016_1x1.v17.mps.daff', ...
'datafunc', @df_BRAS_directivity_mps, ...
'userdata', BRAS_Genelec8020_MPS_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'mps', ...
'alphares', 1, ...
'betares', 1, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
daffv17_write( 'filename', 'Genelec8020_DAF_2016_1x1.v17.ms.daff', ...
'datafunc', @df_BRAS_directivity_ms, ...
'userdata', BRAS_Genelec8020_MPS_userdata, ...
'metadata', BRAS_metadata_base, ...
'content', 'ms', ...
'alphares', 1, ...
'betares', 1, ...
'orient', [ 0 -90 0 ], ...
'channels', 1, ...
'quantization', 'float32' );
function [ data, samplerate, is_symetric, metadata ] = df_BRAS_directivity_dft( alpha, beta, BRAS_ir_data )
%df_BRAS_directivity_dft Note: front pole was measured on-axis of
%loudspeaker, so rotation of final DAFF file must be applied (pitch minus 90
%degree)
assert( isfield( BRAS_ir_data, 'IR' ) )
assert( isfield( BRAS_ir_data, 'Phi' ) )
assert( isfield( BRAS_ir_data, 'Theta' ) )
if isfield( BRAS_ir_data, 'samplerate' )
samplerate = BRAS_ir_data.samplerate;
else
samplerate = 44100;
end
phi = round( alpha );
theta = round( beta );
if theta == 0
idx = 1;
elseif theta == 180
idx = size( BRAS_ir_data.IR, 2 );
else
idx = and( BRAS_ir_data.Phi == phi, BRAS_ir_data.Theta == theta );
end
ir = BRAS_ir_data.IR( :, idx );
ir_length = numel( ir );
append_zeros = 0;
if isfield( BRAS_ir_data, 'filter_length' )
if BRAS_ir_data.filter_length > ir_length
append_zeros = BRAS_ir_data.filter_length - ir_length;
filter_length = ir_length;
else
filter_length = BRAS_ir_data.filter_length;
end
else
filter_length = ir_length;
end
% DAFF requires data alignment by multiple of 4
append_zeros = append_zeros + mod( filter_length, 4 );
ir_data_padded = [ ir(1:filter_length)', zeros( append_zeros ) ];
dft_data = fft( ir_data_padded );
N = size( dft_data, 2 );
data = dft_data( 1 : N / 2 + 1 ) / N * sqrt( 2 );
is_symetric = true;
metadata = [];
function [ data, samplerate, metadata ] = df_BRAS_directivity_ir( alpha, beta, BRAS_ir_data )
%df_BRAS_directivity_ir Note: front pole was measured on-axis of
%loudspeaker, so rotation of final DAFF file must be applied (pitch minus 90
%degree)
assert( isfield( BRAS_ir_data, 'IR' ) )
assert( isfield( BRAS_ir_data, 'Phi' ) )
assert( isfield( BRAS_ir_data, 'Theta' ) )
if isfield( BRAS_ir_data, 'samplerate' )
samplerate = BRAS_ir_data.samplerate;
else
samplerate = 44100;
end
phi = round( alpha );
theta = round( beta );
if theta == 0
idx = 1;
elseif theta == 180
idx = size( BRAS_ir_data.IR, 2 );
else
idx = and( BRAS_ir_data.Phi == phi, BRAS_ir_data.Theta == theta );
end
if isfield( BRAS_ir_data, 'Scale' ) && isfield( BRAS_ir_data, 'NormalizeFront' )
assert( not( BRAS_ir_data.Scale && BRAS_ir_data.NormalizeFront ) || xor( BRAS_ir_data. Scale, BRAS_ir_data.NormalizeFront ) )
end
% Prepare data, scale or normalize if requested
if isfield( BRAS_ir_data, 'Scale' ) && BRAS_ir_data.Scale
ir = BRAS_ir_data.IR( :, idx ) ./ BRAS_ir_data.Peak;
elseif isfield( BRAS_ir_data, 'NormalizeFront' ) && BRAS_ir_data.NormalizeFront
front = itaAudio();
front.timeData = BRAS_ir_data.IR( :, idx );
%front_inv = ita_invert_spk_regularization( front );
ir_target = itaAudio();
ir_target.timeData = BRAS_ir_data.IR( :, idx );
ir_normalized = ir_target / front;
ir = ir_normalized.timeData;
else
ir = BRAS_ir_data.IR( :, idx ); % untouched
end
ir_length = numel( ir );
append_zeros = 0;
if isfield( BRAS_ir_data, 'filter_length' )
if BRAS_ir_data.filter_length > ir_length
append_zeros = BRAS_ir_data.filter_length - ir_length;
filter_length = ir_length;
else
filter_length = BRAS_ir_data.filter_length;
end
else
filter_length = ir_length;
end
% DAFF requires data alignment by multiple of 4
append_zeros = append_zeros + mod( filter_length, 4 );
data = [ ir(1:filter_length)', zeros( append_zeros ) ];
metadata = [];
function [ freqs, data_complex, metadata ] = df_BRAS_directivity_mps( alpha, beta, BRAS_mps_data )
%df_BRAS_directivity_ir Note: front pole was measured on-axis of
%loudspeaker, so rotation of final DAFF file must be applied (pitch minus 90
%degree)
assert( isfield( BRAS_mps_data, 'MPS' ) )
assert( isfield( BRAS_mps_data, 'Frequency' ) )
assert( isfield( BRAS_mps_data, 'Phi' ) )
assert( isfield( BRAS_mps_data, 'Theta' ) )
if isfield( BRAS_mps_data, 'samplerate' )
samplerate = BRAS_mps_data.samplerate;
else
samplerate = 44100;
end
phi = round( alpha );
theta = round( beta );
if theta == 0
idx = 1;
elseif theta == 180
idx = size( BRAS_mps_data.MPS, 2 );
else
idx = and( BRAS_mps_data.Phi == phi, BRAS_mps_data.Theta == theta );
end
data_complex = BRAS_mps_data.MPS( :, idx )';
freqs = BRAS_mps_data.Frequency;
metadata = [];
function [ freqs, data, metadata ] = df_BRAS_directivity_ms( alpha, beta, BRAS_mps_data )
[ freqs, data_complex, metadata ] = df_BRAS_directivity_mps( alpha, beta, BRAS_mps_data );
data = abs( data_complex );
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment