sfstoolbox / sfs-matlab

SFS Toolbox for Matlab/Octave
https://sfs-matlab.readthedocs.io
MIT License
97 stars 39 forks source link

Is it possible to delay a source? #144

Closed nettings closed 5 years ago

nettings commented 7 years ago

Hi *!

I've been playing around with SFS a lot lately, using it to design subwoofer arrays. In that usecase, it is customary to arc a line of subs in order to spread the beam. Doing this physically can be simulated easily with SFS. In actual practice however, the arc is created by progressively delaying the outer speakers, to avoid a strong hotspot in the inside of a physical arc and to get perfectly symmetrical radiation. complex_driving_function I'm working around this by using complex driving gains like so: arcArray(45,1,createArray(10,14))(:,7) # create a 45 degree delayed arc ans =

-0.21299 - 0.97705i 0.48620 - 0.87385i 0.85965 - 0.51089i 0.98170 - 0.19044i 0.99978 - 0.02121i 0.99978 - 0.02121i 0.98170 - 0.19044i 0.85965 - 0.51089i 0.48620 - 0.87385i -0.21299 - 0.97705i

The big big disadvantage is of course that the complex gains are frequency dependent, forcing me to set a global frequency variable and recalculating the gains for every new frequency, as follows: f=70; sound_field_mono(ax,ay,0,arcArray(45,1,createArray(10,14)),'ps',createTaper(10,-10), f,conf);

I would love to be able to assign a fixed delay to every source instead. Is there any way to make this possible?

fietew commented 7 years ago

Yes, you have to use the time domain functionalities namely sound_field_imp. As an input, you have to provide the driving signals for each loudspeaker as the matrix d, where the first dimension is the time and the second dimension corresponds to each loudspeaker.

% configuration
conf = SFS_config;
conf.plot.usedb = true;  % just for better visibility
conf.secondary_sources.geometry = 'linear';  % linear array
conf.secondary_sources.size = 15;  % length of array
conf.secondary_sources.number = 10;  % number of loudspeakers N0

% shortcuts
N0 = conf.secondary_sources.number;  % number of loudspeakers
c = conf.c;  % speed of sound

% create driving signals
sig = [dirac_imp(); zeros(2047,1)];  % this could be any signal [Nx1]
w = ones(1,N0);  % individual weight for each loudspeaker (e.g. tapering, REAL VALUED) [1xN0]
tau = (1:N0)/c*0.4;  % individual delay for each loudspeaker in seconds [1xN0]
d = delayline(sig,tau,w,conf);  % delays the signal for each loudspeaker [NxN0]

% compute and plot the sound field
x0 = secondary_source_positions(conf);
X = [-10,10];
Y = [-10,10];
t = 5.0/c;  % time for time-shapshot
sound_field_imp(X,Y,0,x0,'ps',d,t,conf);

You can use any other signal for sig, e.g. a simple sine-wave. The delay line, which delays the signal, uses integer delays (rounding towards integer samples) by default. In order to change this behaviour, have a look at the delayline part in SFS_config.m.

Note, that in your code x0(:,7) is actually not meant to be complex valued. This should be provided to sound_field_mono via the driving signal D.

hagenw commented 7 years ago

Just a short note on sound_field_imp. The time is only set in seconds in the latest version of the master, in the last official release (2.3.0) the time is still provided in samples.

hagenw commented 7 years ago

@nettings: is your question answered? If you do mono-frequent sound field simulations you have to do one simulation per frequency anyway and you can then add an offset by changing the phase. If you would like to have fix time offsets I would also recommend to use the time domain functions. Or what would be your desired output?

nettings commented 6 years ago

Sorry for the late reply. Thanks @fietew and @hagenw for your hints, I'm playing with the time domain functions now. But I guess the kind of output I'm looking for is more easily accomplished with the sound_field_mono function. I'll make sure to add the phase mangling to the driving function rather than the speaker weight. In any case: exiting new features, great to play around with! Thanks so much for your development effort!