Skip to content

Commit 3b8cd60

Browse files
Fiete Winterhagenw
Fiete Winter
authored andcommitted
extend signal_from_spectrum to nd matrices
1 parent b57196b commit 3b8cd60

File tree

2 files changed

+70
-27
lines changed

2 files changed

+70
-27
lines changed

SFS_general/signal_from_spectrum.m

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
function outsig = signal_from_spectrum(amplitude,phase,f,conf)
1+
function outsig = signal_from_spectrum(amplitude,phase,f,dim,conf)
22
%SIGNAL_FROM_SPECTRUM time signal from single-sided spectrum
33
%
44
% Usage: outsig = signal_from_spectrum(amplitude,phase,f,conf)
@@ -7,6 +7,7 @@
77
% amplitude - the single-sided amplitude spectrum
88
% phase - the single-sided phase spectrum / rad
99
% f - the corresponding frequency vector
10+
% dim - dimension along which the fft is performed
1011
% conf - configuration struct (see SFS_config)
1112
%
1213
% Output parameters:
@@ -50,10 +51,24 @@
5051

5152
%% ===== Checking input arguments ========================================
5253
nargmin = 4;
53-
nargmax = 4;
54+
nargmax = 5;
5455
narginchk(nargmin,nargmax);
55-
[amplitude,phase] = column_vector(amplitude,phase);
56+
if nargin == nargmin
57+
conf = dim;
58+
dim = find(size(amplitude)~=1, 1); % find first non-singleton dimension
59+
else
60+
isargpositivescalar(dim);
61+
end
62+
isargstruct(conf);
5663

64+
Ndims = ndims(amplitude);
65+
dim = min(dim,Ndims);
66+
amplitude = permute(amplitude, [dim:Ndims, 1:dim-1]); % move dim to first dimension
67+
phase = permute(phase, [dim:Ndims, 1:dim-1]); % move dim to first dimension
68+
s = size(amplitude);
69+
Nx = s(1);
70+
amplitude = reshape(amplitude, Nx, []); % squeeze all other dimensions
71+
phase = reshape(phase, Nx, []); % squeeze all other dimensions
5772

5873
%% ===== Configuration ===================================================
5974
fs = conf.fs;
@@ -67,25 +82,31 @@
6782
% Length of the signal to generate
6883
samples = 2 * (bins-1);
6984
% Rescaling (see spectrum_from_signal())
70-
amplitude = [amplitude(1); amplitude(2:end-1)/2; amplitude(end)] * samples;
85+
amplitude = [amplitude(1,:); amplitude(2:end-1,:)/2; amplitude(end,:)] ...
86+
* samples;
7187
% Mirror the amplitude spectrum ( 2*pi periodic [0, fs[ )
72-
amplitude = [amplitude; amplitude(end-1:-1:2)];
88+
amplitude = [amplitude; amplitude(end-1:-1:2,:)];
7389
% Mirror the phase spectrum and build the inverse (complex conjugate)
74-
phase = [phase; -1 * phase(end-1:-1:2)];
90+
phase = [phase; -1 * phase(end-1:-1:2,:)];
7591

7692
else % -> odd time signal length
7793
% Length of the signal to generate
7894
samples = 2*bins - 1;
7995
% Rescaling (see signal_from_spectrum)
80-
amplitude = [amplitude(1); amplitude(2:end)/2] * samples;
96+
amplitude = [amplitude(1,:); amplitude(2:end,:)/2] * samples;
8197
% Mirror the amplitude spectrum ( 2*pi periodic [0, fs-bin] )
82-
amplitude = [amplitude; amplitude(end:-1:2)];
98+
amplitude = [amplitude; amplitude(end:-1:2,:)];
8399
% Mirror the phase spectrum and build the inverse (complex conjugate)
84-
phase = [phase; -1*phase(end:-1:2)];
100+
phase = [phase; -1*phase(end:-1:2,:)];
85101
end
86102

87103
% Convert to complex spectrum
88104
compspec = amplitude .* exp(1i*phase);
89105

90106
% Build the inverse fft and assume spectrum is conjugate symmetric
91107
outsig = real(ifft(compspec));
108+
109+
%% ===== Output ==========================================================
110+
% undo reshape and permute
111+
outsig = reshape(outsig, [samples, s(2:end)]);
112+
outsig = permute(outsig, [Ndims-dim+2:Ndims, 1:Ndims-dim+1]);

SFS_general/spectrum_from_signal.m

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
function varargout = spectrum_from_signal(signal,conf)
1+
function varargout = spectrum_from_signal(signal,dim,conf)
22
%SPECTRUM_FROM_SIGNAL single-sided amplitude and phase spectra of signal
33
%
4-
% Usage: [amplitude,phase,f] = spectrum_from_signal(sig,conf)
4+
% Usage: [amplitude,phase,f] = spectrum_from_signal(sig,[dim],conf)
55
%
66
% Input parameters:
77
% signal - one channel audio (time) signal
8+
% dim - dimension along which the fft is performed
89
% conf - configuration struct (see SFS_config)
910
%
1011
% Output parameters:
@@ -52,11 +53,22 @@
5253

5354
%% ===== Check input arguments ===========================================
5455
nargmin = 2;
55-
nargmax = 2;
56+
nargmax = 3;
5657
narginchk(nargmin,nargmax);
57-
signal = column_vector(signal);
58+
if nargin == nargmin
59+
conf = dim;
60+
dim = find(size(signal)~=1, 1); % find first non-singleton dimension
61+
else
62+
isargpositivescalar(dim);
63+
end
5864
isargstruct(conf);
5965

66+
Ndims = ndims(signal);
67+
dim = min(dim,Ndims);
68+
signal = permute(signal, [dim:Ndims, 1:dim-1]); % move dim to first dimension
69+
s = size(signal);
70+
Nx = s(1);
71+
signal = reshape(signal, Nx, []); % squeeze all other dimensions
6072

6173
%% ===== Configuration ===================================================
6274
fs = conf.fs;
@@ -65,7 +77,7 @@
6577

6678
%% ===== Calcualate spectrum =============================================
6779
% Generate fast fourier transformation (=> complex output)
68-
compspec = fft(signal);
80+
compspec = fft(signal,[],1);
6981

7082
% Length of the signal => number of points of fft
7183
bins = length(signal);
@@ -75,37 +87,47 @@
7587
f = fs/bins * (0:(bins-1)/2)';
7688
% Get amplitude and phase spectra and use only the first half of the
7789
%>spectrum [0, fs/2[
78-
amplitude = abs(compspec(1:length(f)));
79-
phase = angle(compspec(1:length(f)));
90+
amplitude = abs(compspec(1:length(f),:));
91+
phase = angle(compspec(1:length(f),:));
8092
% Scale the amplitude (factor two for mirrored frequencies
8193
%>divide by number of bins)
82-
amplitude = [amplitude(1); 2*amplitude(2:end)] / bins;
94+
amplitude = [amplitude(1,:); 2*amplitude(2:end,:)] / bins;
8395

8496
else % For even signal length
8597
% Calculate corresponding frequency axis
8698
f = fs/bins * (0:bins / 2)';
8799
% Get amplitude and phase spectra and use only the first half of the
88100
%>spectrum [0, fs/2]
89-
amplitude = abs(compspec(1:length(f)));
90-
phase = angle(compspec(1:length(f)));
101+
amplitude = abs(compspec(1:length(f),:));
102+
phase = angle(compspec(1:length(f),:));
91103
% Scale the amplitude (factor two for mirrored frequencies
92104
%>divide by number of bins)
93-
amplitude = [amplitude(1); 2*amplitude(2:end-1); amplitude(end)] / bins;
105+
amplitude = [amplitude(1,:); 2*amplitude(2:end-1,:); amplitude(end,:)] / bins;
94106
end
95107

96-
% Return values
97-
if nargout>0, varargout{1}=amplitude; end
98-
if nargout>1, varargout{2}=phase; end
99-
if nargout>2, varargout{3}=f; end
100-
101-
102108
%% ===== Plotting ========================================================
103109
if nargout==0 || useplot
104110
figure; title('Spectrum');
105111
subplot(2,1,1)
106112
semilogx(f,20 * log10(abs(amplitude))); xlim([1, fs/2]);
107113
grid on; xlabel('frequency / Hz'); ylabel('amplitude / dB')
108114
subplot(2,1,2)
109-
semilogx(f,unwrap(phase)); xlim([1, fs/2]);
115+
semilogx(f,unwrap(phase,[],1)); xlim([1, fs/2]);
110116
grid on; xlabel('frequency / Hz'); ylabel('phase / rad')
111117
end
118+
119+
%% ===== Output ==========================================================
120+
% Return values
121+
if nargout>0
122+
% undo reshape and permute
123+
amplitude = reshape(amplitude, [length(f), s(2:end)]);
124+
amplitude = permute(amplitude, [Ndims-dim+2:Ndims, 1:Ndims-dim+1]);
125+
varargout{1}=amplitude;
126+
end
127+
if nargout>1
128+
% undo reshape and permute
129+
phase = reshape(phase, [length(f), s(2:end)]);
130+
phase = permute(phase, [Ndims-dim+2:Ndims, 1:Ndims-dim+1]);
131+
varargout{2}=phase;
132+
end
133+
if nargout>2, varargout{3}=f; end

0 commit comments

Comments
 (0)