Skip to content

Add support for signal analysis#16

Open
amrali wants to merge 41 commits intomasterfrom
feature/signal-analysis-final
Open

Add support for signal analysis#16
amrali wants to merge 41 commits intomasterfrom
feature/signal-analysis-final

Conversation

@amrali
Copy link
Owner

@amrali amrali commented Sep 26, 2025

No description provided.

This commit enhances the library by adding a flexible, `no-std`
compatible signal analysis module. The `analysis::spectrum` function
can now operate on both generative and recorded waveforms by taking
the number of samples to analyze as an argument.

This approach addresses previous design feedback by:
- Consolidating signal representation within the existing `Waveform`
  struct, using a `WaveformSource` enum.
- Keeping the core library `no-std` and agnostic to audio file
  formats.
- Providing a clear, user-friendly analysis function that avoids
  panics for generative waveforms.

Key changes:
- `analysis::spectrum` signature changed to `spectrum(waveform, num_samples)`.
- `Waveform` can be created from a slice of recorded samples.
- An example demonstrates loading a WAV file and analyzing its
  frequency spectrum.
- Tests are updated to cover both generative and recorded waveform
  analysis.
This commit introduces several major features and improvements:
- A `synthesize` function in the `analysis` module to create a
  generative `Waveform` from a recorded one, based on its harmonic
  content.
- A `time_spectrum` function (STFT) to analyze the frequency
  content of a signal over time.
- A unified, library-wide `Error` enum to provide robust,
  panic-free error handling.

The `superpose`, `normalize_amplitudes`, `time_spectrum`, and
`synthesize` functions now return a `Result` instead of
panicking on invalid input. This makes the library's API safer and
more consistent.

An example, `resynthesis.rs`, demonstrates the full workflow of
loading, analyzing, and synthesizing a waveform.
This commit introduces several major features and improvements:
- A `synthesize` function in the `analysis` module to create a
  generative `Waveform` from a recorded one, based on its harmonic
  content.
- A `time_spectrum` function (STFT) to analyze the frequency
  content of a signal over time.
- A unified, library-wide `Error` enum to provide robust,
  panic-free error handling. All functions that previously panicked
  now return a `Result`.
- Module-level documentation for the new `error` and `analysis`
  modules.
- An updated `README.md` with information on the new signal
  analysis features.

An example, `resynthesis.rs`, demonstrates the full workflow of
loading, analyzing, and synthesizing a waveform.
This commit introduces a major architectural change to enable
high-fidelity, dynamic waveform synthesis and modulation, and
improves the ergonomics of the API.

Key changes:
- A new `Modulation` enum replaces static `amplitude` and `phase`
  fields in the `Wave` struct. This allows a wave's properties to
  be modulated by a static value, a pre-calculated envelope, or
  another `Wave` acting as a Low-Frequency Oscillator (LFO).
- `From` traits are implemented for `Modulation` to allow for more
  ergonomic construction of `Wave`s (e.g., `amplitude: 0.5.into()`).
- The `synthesize` function is enhanced to create `Wave`s with
  dynamic amplitude and phase envelopes, capturing the time-varying
  nature of recorded sounds.
- A new `modulation.rs` example demonstrates how to create tremolo
  and vibrato effects using LFOs.
- A previously deleted test, `test_wave_function_formatting`, has
  been restored.
- All tests and documentation have been updated to reflect these
  significant API changes.
@amrali amrali requested a review from Copilot September 26, 2025 05:06
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces comprehensive signal analysis capabilities to the waver library, transforming it from a pure wave generation library into a full-featured signal processing toolkit that can both generate and analyze waveforms.

  • Adds support for recorded waveform sources alongside generative ones
  • Introduces dynamic amplitude and phase modulation using envelopes and Low-Frequency Oscillators (LFOs)
  • Implements frequency analysis (FFT), time-based frequency analysis (STFT), and waveform synthesis from recorded signals

Reviewed Changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/waveform.rs Major restructure to support both generative and recorded waveform sources with enhanced iterator implementation
src/wave.rs Adds dynamic modulation support through Modulation enum for amplitude and phase properties
src/lib.rs Updates public API to expose new analysis module and error types
src/error.rs New error handling module for library-wide error management
src/analysis.rs Complete signal analysis module with FFT, STFT, and synthesis capabilities
examples/*.rs Three new examples demonstrating modulation, analysis, and resynthesis features
README.md Updates documentation to reflect new signal analysis capabilities
Cargo.toml Adds dependencies for FFT processing and audio file handling

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

- Add FFT spectrum analysis with sub-bin frequency accuracy
- Implement STFT (Short-Time Fourier Transform) for spectrograms
- Add advanced waveform synthesis from spectral analysis
- Include comprehensive test suite covering all frequency ranges
- Support extreme frequency analysis (sub-Hz to GHz)
- Implement frequency tracking across time frames
- Add utility functions for peak detection and phase unwrapping
- Restructure analysis module from single file to comprehensive module
- Update waveform module to support new analysis functionality
- Update wave module to integrate with signal analysis features
- Remove old analysis.rs in favor of modular approach
- Add rustfft dependency for Fast Fourier Transform operations
- Add num-complex for complex number arithmetic in FFT
- Update dependencies to support advanced signal processing
- Update analysis.rs example to showcase new spectrum analysis capabilities
- Update resynthesis.rs example to demonstrate waveform synthesis from analysis
- Include practical examples of FFT and STFT usage
- Show integration with the new modular analysis system
@codecov
Copy link

codecov bot commented Sep 27, 2025

Codecov Report

❌ Patch coverage is 74.11765% with 66 lines in your changes missing coverage. Please review.
✅ Project coverage is 76.76%. Comparing base (2e85cfc) to head (75ab1d0).

Files with missing lines Patch % Lines
src/wave.rs 54.90% 23 Missing ⚠️
src/analysis/utils.rs 85.10% 14 Missing ⚠️
src/analysis/synthesis.rs 58.06% 13 Missing ⚠️
src/waveform.rs 71.87% 9 Missing ⚠️
src/analysis/stft.rs 78.12% 7 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff              @@
##            master      #16       +/-   ##
============================================
- Coverage   100.00%   76.76%   -23.24%     
============================================
  Files            2        6        +4     
  Lines           57      284      +227     
============================================
+ Hits            57      218      +161     
- Misses           0       66       +66     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

- Add QuantizationIterator and DequantizationIterator for efficient sample conversion
- Implement QuantizeIterator and DequantizeIterator traits for ergonomic API
- Provide quantize_samples() and dequantize_samples() convenience functions
- Support all standard integer types (i8, i16, i32, u8, u16, u32) and floats
- Use NumCast for safe type conversions without unnecessary intermediate types
- Design for no-std compatibility using f32 precision to avoid i128 on embedded platforms
- Remove redundant generic parameter F from spectrum() function, keeping only BitDepth
- Update spectrum() to work with any FftNum + Float type instead of forcing f32 conversion
- Optimize STFT with native BitDepth precision throughout analysis pipeline
- Enhance spectral peak detection with improved parabolic interpolation
- Add comprehensive frequency tracking with adaptive tolerance based on frequency ranges
- Improve synthesis parameter validation and error handling
- Update all analysis utilities to maintain precision without unnecessary type casting
- Add better phase unwrapping and smoothing for synthesis quality
- Make Wave and Waveform generic over Float types instead of just integer types
- Add quantize() method to Wave for direct sample quantization
- Export quantization functions and traits in public API
- Update Waveform to work natively with floating-point samples
- Remove unnecessary BitDepth constraints and phantom data
- Add InvalidParameters error type for better analysis error reporting
- Improve iterator implementations for better numerical stability
- Update all type conversions to use proper float-to-float casting
- Convert all examples to use f32 waveforms with quantization for output
- Update README.md example to demonstrate new quantization workflow
- Show proper usage of dequantize_samples() for analysis of integer data
- Use QuantizeIterator trait for ergonomic sample conversion in examples
- Update synthesis parameters for better quality and performance
- Fix RFC URL in documentation to point to current Rust issue
- Add 'diagnostics' feature flag for verbose and expensive analysis tests
- Allows users to run comprehensive tests with: cargo test --features diagnostics
- Keeps regular test suite fast while providing option for thorough validation
- Remove QuantizedWaveIterator struct that duplicated quantization logic
- Update Wave::quantize() to use the quantization module's QuantizeIterator trait
- Remove inconsistent AsPrimitive<f32> usage in favor of NumCast from quantization module
- Clean up imports by removing unused num_traits imports
- Maintain same public API: wave.quantize() still works but now uses the proper trait
- Fix lifetime bounds in return type to work with quantization iterator infrastructure

This eliminates code duplication and ensures consistent quantization behavior
across the entire library using a single source of truth in the quantization module."
amrali added 12 commits October 1, 2025 23:41
- Remove Wave::quantize() method that violated single responsibility principle
- Update tests to use trait-based quantization: wave.iter().quantize()
- Follow Rust idioms where functionality is extended via traits, not direct methods
- Maintain separation of concerns: Wave generates samples, quantization converts them
- More consistent with iterator ecosystem (collect, map, filter, etc.)
- Users now use: wave.iter().quantize().take(100).collect()

This follows The Rust Way™ of extension traits over convenience methods,
keeping the Wave struct focused on its core responsibility of sample generation."
- Split quantization.rs into modular structure:
  - core.rs: quantize_samples and dequantize_samples functions
  - iterators.rs: QuantizationIterator and DequantizationIterator
  - traits.rs: QuantizeIterator and DequantizeIterator extension traits
  - mod.rs: module entry point with re-exports
- Move tests into tests/ subdirectory with dedicated test files
- Improves code organization and maintainability
- All 8 quantization tests passing
- Split wave.rs into modular structure:
  - types.rs: WaveFunc, Modulation, and Wave types with Display impls
  - iterator.rs: WaveIterator implementation
  - mod.rs: module entry point with re-exports
- Extract tests into tests/ subdirectory:
  - basic.rs: core functionality tests (4 tests)
  - modulation.rs: LFO and envelope tests (4 tests)
  - edge_cases.rs: boundary condition tests (8 tests)
  - quantization.rs: integration test (1 test)
- Improves separation of concerns and code discoverability
- All 17 wave tests passing
- Split waveform.rs into modular structure:
  - types.rs: WaveformSource and Waveform types
  - iterator.rs: WaveformIterator and WaveformIteratorSource
  - mod.rs: module entry point with re-exports
- Extract tests into tests/ subdirectory:
  - basic.rs: basic functionality and normalization (4 tests)
  - recorded.rs: recorded waveform tests (2 tests)
  - edge_cases.rs: edge case tests (1 test)
- Add internal constructor for WaveformIterator to avoid circular deps
- Improves code organization and maintainability
- All 7 waveform tests passing
- Change `mod wave` to `pub mod wave`
- Change `mod waveform` to `pub mod waveform`
- Improves public API discoverability
- Allows users to access submodules for advanced use cases
- Maintains backward compatibility via re-exports
Update README to reflect all major changes in feature/signal-analysis-final branch:

New Features:
- Signal analysis module (FFT, STFT, dynamic synthesis)
- LFO modulation and envelope support
- Float-based precision API (f32, f64)
- Quantization utilities module
- Support for sub-Hz to GHz frequency ranges

Documentation improvements:
- Comprehensive feature sections with subsections
- Module organization guide (wave, waveform, quantization, analysis, error)
- Expanded examples covering all major use cases:
  * Basic waveform generation
  * Wave superposition
  * LFO modulation (tremolo/vibrato)
  * Signal analysis and resynthesis
  * Quantization methods
- Updated version from 0.1 to 0.2
- Updated installation section
- Added TODO for inverse FFT support

The README now accurately represents the current state of the library with
comprehensive documentation for users to understand and utilize all features.
…diences

Broaden README appeal from audio-centric to universal signal processing:

Key changes:
- Updated opening description to emphasize "entire electromagnetic spectrum"
  from sub-Hz geological signals to GHz radio frequencies
- Reframed "Waveform Generation" as "Signal Generation"
- Reframed "Signal Analysis" as "Spectral Analysis" with scientific terminology
- Added "Quantization & Data Conversion" section emphasizing precision conversion
- Renamed "No-std Compatible" to "Embedded & Bare-Metal" with clearer benefits
- Updated module organization to use "signal processing" terminology

New "Use Cases" section highlights diverse applications:
- Audio Processing (20Hz - 20kHz)
- RF Communications (MHz - GHz)
- Sensor Signal Processing (sub-Hz - kHz)
- Scientific Instrumentation
- Seismology & Geophysics
- Telecommunications

Added scientific/engineering examples:
- High-frequency RF carrier generation (100 MHz FM radio)
- Low-frequency sensor data analysis (tidal measurements, sub-Hz)
- Enhanced STFT example showing time-frequency evolution analysis

Terminology changes:
- "waveform" → "signal" where appropriate
- "audio synthesis" → "waveform synthesis"
- "online generation" → "streaming generation"
- Emphasized "precision" and "spectral" terminology

This positions Waver as a universal signal processing library suitable for
physicists, RF engineers, sensor researchers, and anyone working with signals
beyond just audio applications.
Fixed two failing doc tests by providing valid sample data:

1. "Analyze Low-Frequency Sensor Data" example:
   - Increased sample count from 1000 to 2048 (minimum for 1024-point FFT)
   - Fixed variable naming (_phase instead of phase to avoid unused warning)

2. "Signal Analysis and Resynthesis" example:
   - Wrapped code in fn main() {} to avoid top-level let statements
   - Generated actual 440 Hz sine wave test signal instead of empty vec
   - Added proper imports (std::f32::consts::PI)
   - Limited STFT iteration to first 5 frames to reduce test time
   - Fixed unused variable warning (_new_samples)

3. Fixed markdown formatting:
   - Added missing blank line between code block and heading

All 18 doc tests now pass successfully.
@amrali amrali requested a review from Copilot October 2, 2025 06:30
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Copilot reviewed 47 out of 49 changed files in this pull request and generated 7 comments.


Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

amrali and others added 2 commits October 2, 2025 09:44
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants