Background: I am working on a Unity Project (C#) and implementing a Room Impulse Response synthesis. I do ray tracing to create energy histogram for different bands. With these histograms it is possible to synthesize a room impulse response.
My guide is following theoretical Reference: Physically based real-time auralization of interactive virtual environments (Schröder) 5.3.4 Construction of the Room Impulse Response (RT) https://publications.rwth-aachen.de/record/50580/files/3875.pdf
I also found a helpful Matlab Implementation which refers to the work above: https://de.mathworks.com/help/audio/ug/room-impulse-response-simulation-with-stochastic-ray-tracing.html#RoomImpulseWithRayTracingExample-8
I worked through the process step by step and so far it managed to implement this to my C# class. Now I am stuck at the point where I have to use the STFT and the ISTFT. For that reason I am using the NWaves (C#) package to work with (I)STFT: https://github.com/ar1st0crat/NWaves/wiki/Transforms#short-time-fourier-transform
To be more precise, I have (poisson distributed) dirac pulses in a 44100 Array (1sek IR 44100 samplerate). This time signal has to be transformed to frequency domain via STFT to filter it with a Raised Cosine Filter and transform it back to time domain.
In the matlab code its at the part Filter the Poisson sequence through the six bandpass filters. Without going into further details, the problem is that the Matlab Function sfft(signalVector) is returning a different result than NWaves. Right now I am using the Matlab Example Online Editor to evaluate its output (via Try this example on the website).
I don't understand how to (1. )interpret the results or (2.) replicate the calculation process of Matlab. It seems like Matlab is doing so much under the hood. With no experience in Matlab this is very hard to comprehend.
1.) I have isolated the problem to grasp it but Matlab and NWaves are returning different results despite the same input and I don't understand why. I am using the same STFT configuration for Matlab and NWaves.
Reduced Matlab Code
NFFT = 8192;
win = hann(882,"symmetric");
sfft = dsp.STFT(Window = win,OverlapLength=441,FFTLength=NFFT,FrequencyRange="onesided");
isfft = dsp.ISTFT(Window=win,OverlapLength=441,FrequencyRange="onesided");
x = linspace(1, 1, 441).'
X = sfft(x);
Matlab returns a 4097 Array with a real and imaginary part. I expected a length of 4097 due to the FFT Length (FFT Size / 2 + 1) As far I know the imaginary values are strictly mandatory to reconstruct the frequency domain signal back to time domain.
The reduced C# Code:
float[] testValues = new float[441];
for (int i = 0; i < 441; i++)
{
testValues[i] = 1.0f;
}
int nFFT = 8192; // FFT Size defines the frequency resolution of the spectrogram.
int hannWindowLength = 882; // The window length defines the time resolution of the spectrogram.
int hopSize = hannWindowLength / 2; // The Hopsize defines the overlap between two consecutive windows. The hopsize is usually chosen to be 50% of the window length.
Stft stft = new Stft(hannWindowLength, hopSize, NWaves.Windows.WindowType.Hann, nFFT);
List < (float[], float[]) > stftFrameResult = stft.Direct(testValues);
float[] realSpectrum1 = stftFrameResult[0].Item1; // Length: 8192
float[] imagSpectrum1 = stftFrameResult[0].Item2; // Length: 8192
for (int j = 0; j < realSpectrum1.Length; j++)
{
Debug.Log(realSpectrum1[j] + " " + imagSpectrum1[j]);
}
NWaves returns a complete different result. The spectrum has the length of the FFT (8192) and all values except the first one are different.
In NWaves I can not set the frequency range. Therefore I interprete its results that I have to use only the first half of the Array to 4097. But the results would be still different and I don't understand why.
When I change the FrequencyRange in Matlab to twosided I receive a result of length 8192. But the values still differs from NWaves.
2.) Even if the results would be the same. How is Matlab doing his sfft magic? In the linked example (Filter the Poisson sequence through the six bandpass filters)
X = sfft(x);
X = X.*RCF.';
y((index-1)*frameLength+1:index*frameLength,:) = isfft(X);
Where RCF is a 6 x 4097 Matrix with only real values. X will become a 4097x6 Matrix with real and imaginary parts due to filtering with the RCF. Are these imaginary parts somehow included in the calculation of X.*RCF? Or are they only attached to the matrix but not touched?
I would appreciate any share of knowledge or hints. Thanks!