Repository navigation
FFT Manager and Signal Generators
Relevant source files
The following files were used as context for generating this wiki page:
- docs/assets/widgets/export_dialog.png
- docs/assets/widgets/settings.png
- docs/assets/widgets/welcome.png
- scripts/capture_widget_screenshots.py
- src/core/fft_manager.py
- src/core/ring_buffer.py
- src/gui/widgets/signal_generator.py
- tests/logic_verification/core/test_ring_buffer_mismatch.py
- tests/logic_verification/gui/widgets/test_signal_generator.py
This section details the centralized FFT management system, the advanced signal generation capabilities, and the underlying thread-safe circular buffering used for high-performance audio data handling in MeasureLab.
The FFTManager class serves as a centralized controller for Fast Fourier Transform operations. It is designed to optimize performance by leveraging pyfftw (Pythonic wrapper for FFTW) with persistent wisdom management and thread-safe plan caching.
-
PyFFTW Wisdom: The manager stores FFTW "wisdom" (pre-calculated plans for specific sizes) in an XDG-compliant user data directory
src/core/fft_manager.py:54-60. This allows the system to skip expensive hardware-specific optimization on subsequent runs. -
Security: Wisdom is serialized using JSON and Base64 instead of
pickleto prevent arbitrary code execution vulnerabilitiessrc/core/fft_manager.py:49-50. -
Threading: The manager limits FFT computation to a maximum of 8 threads to minimize synchronization overhead on high-core-count processors during small 1D transforms
src/core/fft_manager.py:40-45. -
Plan Caching: Plans are cached in a dictionary keyed by size, dtype, and direction
src/core/fft_manager.py:122-128. The manager supports "upgrading" a plan fromFFTW_ESTIMATEtoFFTW_MEASUREif higher precision is requested latersrc/core/fft_manager.py:143-146.
The following diagram illustrates how modules request and receive optimized FFT plans.
FFT Plan Lifecycle
sequenceDiagram
participant M as MeasurementModule
participant FM as FFTManager
participant PW as pyfftw
participant FS as FileSystem (Wisdom)
Note over FM: Initialization
FM->>FS: load_wisdom()
FS-->>FM: JSON/Base64 Wisdom
M->>FM: get_plan(size, dtype, flags)
FM->>FM: Check _plans cache
alt Plan Not Cached
FM->>PW: empty_aligned (Input/Output)
FM->>PW: FFTW Plan Creation
FM->>FM: Store in _plans
else Plan Upgrade Needed
FM->>PW: Create higher precision plan
end
FM-->>M: Return Plan Object
Sources: src/core/fft_manager.py:31-152
The SignalGenerator module src/gui/widgets/signal_generator.py:150 provides high-precision excitation signals. It supports independent control for Left and Right channels, including complex modulations and filtered noise.
The generator distinguishes between two primary types of signals:
-
Periodic Waveforms: Calculated in real-time per block (Sine, Square, Triangle, Sawtooth, Pulse)
src/gui/widgets/signal_generator.py:152. -
Buffered Waveforms: Pre-generated for performance (Noise, Multitone, MLS, Golay, Burst, PRBS)
src/gui/widgets/signal_generator.py:151.
-
Phase Continuity: For periodic signals, the generator maintains a
_phasestate across audio blocks, ensuring no "clicks" occur when changing frequenciestests/logic_verification/gui/widgets/test_signal_generator.py:86-125. -
Colored Noise: Supports White, Pink (-3dB/oct), Brown (-6dB/oct), Blue (+3dB/oct), and Violet (+6dB/oct) noise via FFT-based frequency domain filtering
src/gui/widgets/signal_generator.py:192-230. -
Frequency Snapping: Can "snap" the output frequency to the exact center of an FFT bin to prevent spectral leakage in analysis modules
src/gui/widgets/signal_generator.py:114-116. -
Calibration Integration: Applies frequency calibration factors (PPM adjustments) retrieved from the
AudioEnginecalibration managersrc/gui/widgets/signal_generator.py:178-190.
Signal Generator Architecture
graph TD
subgraph "SignalGenerator (MeasurementModule)"
ParamsL["SignalParameters (Left)"]
ParamsR["SignalParameters (Right)"]
GenLogic["_generate_audio_block()"]
end
subgraph "Processing Pipeline"
Mod["Modulators (AM/FM/PM)"]
Wave["Waveform Helpers"]
Filt["IIR Filters (LPF/HPF/Notch)"]
end
ParamsL --> GenLogic
ParamsR --> GenLogic
GenLogic --> Mod
Mod --> Wave
Wave --> Filt
Filt --> Out["AudioEngine Callback"]
Sources: src/gui/widgets/signal_generator.py:43-148, src/gui/widgets/signal_generator.py:150-166
The RingBuffer is a thread-safe, circular buffer implementation used to bridge the high-priority audio callback thread and the lower-priority UI/Analysis threads src/core/ring_buffer.py:6-12.
-
Thread Safety: Uses a
threading.Lockto synchronizereadandwriteindicessrc/core/ring_buffer.py:27. -
Broadcasting: Supports writing mono data to a stereo buffer via NumPy broadcasting
src/core/ring_buffer.py:89-91. -
Overflow Handling: If the writer "laps" the reader, the buffer automatically jumps the read index to the start of the latest valid window to prevent reading corrupted data
src/core/ring_buffer.py:119-122. -
Channel Mismatch: Automatically handles input with fewer channels by zero-padding
src/core/ring_buffer.py:70-76or ignoring extra channelssrc/core/ring_buffer.py:68-69.
| Function | Role | Thread Context |
|---|---|---|
write(data) |
Appends new audio frames to the buffer. | Audio Callback |
read(num) |
Retrieves requested number of frames. Returns copy to avoid race conditions. | UI / Analysis |
reset() |
Clears all data and resets indices. | Control Thread |
available() |
Returns the count of readable samples. | UI / Analysis |
Sources: src/core/ring_buffer.py:41-153, tests/logic_verification/core/test_ring_buffer_mismatch.py:13-32