0
$\begingroup$

I have a question about magnitude of a spectrum. My task is to build the spectrum and make IFFT - the result waveform should have unity amplitude.

For example:

  1. Create 2 arrays with Magnitudes and Phases;
  2. Fill the magnitudes array with noise (for example Perlin noise or white uniform noise);
  3. Fill the phases with noise too;
  4. Build the symmetrical-rectangular spectrum based on the above arrays (the first and FFTSize / 2 elements of imaginary arrays are zeroed too);
  5. Perform IFFT;
  6. The output waveform should contains the noise with unity amplitude.

I have troubles because on the output i have single impulse with unity amplitude and silent noise.

The code:

' Main code
 
Private Sub Form_Load()

    . . .

    InitSoundFromFile "C:\temp\test_spin.wav"

    DrawSpectrum picSpectrumOrigin, m_fSpectrum, m_cWavFile.SampleRate

    Randomize 1, 1  ' // Replace data with noise

    IFFT

    DrawSpectrum picSpectrumModified, m_fSpectrum, m_cWavFile.SampleRate
    DrawWaveform picWaveForm, m_fSamples, m_cWavFile.SampleRate

End Sub
 
' Noise/Signal ratio
 
Private Sub Randomize( _
            ByVal fMagnitude As Single, _
            ByVal fPhase As Single)
    Dim lIndex  As Long
    Dim fMag    As Single
    Dim fPh     As Single

    For lIndex = 0 To m_cFFT.FFTSize \ 2

        fMag = Rnd / (m_cFFT.FFTSize / 2)
        fPh = Rnd / (m_cFFT.FFTSize / 2)

        m_fSpectrum(0, lIndex) = fMag * fMagnitude + (1 - fMagnitude) * m_fSpectrum(0, lIndex)
        m_fSpectrum(1, lIndex) = fPh * fPhase + (1 - fPhase) * m_fSpectrum(1, lIndex)

    Next
 
End Sub
 
Private Sub IFFT()
    Dim fRectSpectrum() As Single
    Dim lIndex          As Long
    Dim lFFTSize        As Long

    lFFTSize = UBound(m_fSpectrum, 2) * 2

    ReDim fRectSpectrum(1, lFFTSize - 1)

    For lIndex = 0 To UBound(m_fSpectrum, 2)

        fRectSpectrum(0, lIndex) = Cos(m_fSpectrum(1, lIndex)) * m_fSpectrum(0, lIndex)
        fRectSpectrum(1, lIndex) = Sin(m_fSpectrum(1, lIndex)) * m_fSpectrum(0, lIndex)

    Next

    For lIndex = 1 To lFFTSize - 1
 
        fRectSpectrum(0, lFFTSize - lIndex) = fRectSpectrum(0, lIndex)
        fRectSpectrum(1, lFFTSize - lIndex) = -fRectSpectrum(1, lIndex)

    Next

    fRectSpectrum(1, 0) = 0
    fRectSpectrum(1, lFFTSize \ 2) = 0

    m_cFFT.IFFTR fRectSpectrum(), m_fSamples

    Debug.Print m_fSamples(0)

End Sub

InitSoundFromFile - just creates a waveform from a file (just container) and calculates the spectrum to m_fSpectrum array; Randomize - adds the noise to m_fSpectrum array (with arguments equal to 1 it just replace signal with noise);

The output i have:

enter image description here

ADDED:

I've fixed the single impulse time-domain result by change range of phase-randomization from -PI to PI. I still can't calculate magnitude bins values to get the unity noise amplitude in time domain. What's the value of noise should i add in frequency domain to get unity noise value in time domain?

Now i add the random values from (0..1) / (FFTSize / 2) range to bins but then i get the time domain noise with 1.968998E-02 maximum amplitude after IFFT.

$\endgroup$
2
  • 1
    $\begingroup$ Can you add a plot of your result? $\endgroup$ Jul 14 at 12:23
  • $\begingroup$ I've fixed problem with single pulse (just i've changed random-range for phases from -pi to pi), but i still can't calculate bins values to get unity time domain noise. $\endgroup$
    – John
    Jul 14 at 15:36
1
$\begingroup$

The magnitude of the FFT will likely scale by the number of samples N depending on the specific algorithm you use. So the IFFF will be 1/N. Just multiply your FFT bins by N to normalize it. If you use any windowing this will change the result accordingly

$\endgroup$
3
  • $\begingroup$ Unfortunatelly it doesn't work. For example, i can set anyone bin magnitude to 0.5 (others set to zero) and the result time-domain waveform will contain sine with unity amplitude. If i set 0.25 to 2 any bins i get two sine with 0.5 amplitudes so the result time-domain waveform will contain the unity amplitude of two sines (0.5 + 0.5). How to add a noise? The noise has a random phase and amplitude. How to calculate bins in order to output amplitude has unity value? $\endgroup$
    – John
    Jul 14 at 17:49
  • $\begingroup$ I see - so if it is noise are you looking for the standard deviation to be normalized? Is your noise white? $\endgroup$ Jul 14 at 17:50
  • $\begingroup$ Yes my noise is white, but i plan to add different ones like Perlin noise. I will describe my final task a little: I am writing a synthesizer of sounds in the frequency domain and I need noise as a starting point, which I will then change (smooth, threshold, release etc.) to reproduce final sound. $\endgroup$
    – John
    Jul 14 at 17:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.