|
TR123e - EMCT Computing Final Project Version 1.0
Research Project Translation from gen~ to embedded Moog synth
|
High-precision frequency interpolation engine for musical portamento. More...
#include <PortamentoPlayer.h>
Public Member Functions | |
| PortamentoPlayer (float sampleRate, float defaultPortamentoTimeMs=100.0f) | |
| Construct PortamentoPlayer with audio system parameters. | |
| void | setPortamentoTime (float timeMs) |
| Update portamento timing parameter in real-time. | |
| void | noteOn (int midiNote, bool portamentoOn) |
| Trigger new note with optional portamento control. | |
| void | noteOff () |
| Signal note release for envelope coordination. | |
| int | getCurrentNote () |
| Query current MIDI note number. | |
| float | getCurrentFreq () |
| Query current instantaneous frequency. | |
| float | process () |
| Generate next frequency sample with interpolation processing. | |
Private Member Functions | |
| float | midiToFreq (int midiNote) |
| Convert MIDI note number to frequency using equal temperament. | |
| float | interpolateFrequency () |
| Perform linear frequency interpolation for smooth transitions. | |
Private Attributes | |
| int | currentNote |
| Current MIDI note number being processed. | |
| float | sampleRate |
| Audio system sample rate in Hz. | |
| float | currentFreq |
| Current instantaneous frequency in Hz. | |
| float | targetFreq |
| Target frequency for interpolation in Hz. | |
| float | incrementPerSample |
| Frequency increment per audio sample. | |
| float | portamentoTimeMs |
| Portamento duration in milliseconds. | |
| bool | noteIsOn |
| Note activity state flag. | |
High-precision frequency interpolation engine for musical portamento.
The PortamentoPlayer class provides professional-grade pitch sliding capabilities with sample-accurate timing and configurable interpolation parameters. It handles MIDI note-to-frequency conversion, interpolation timing calculations, and real-time frequency generation suitable for direct oscillator control.
@design_principles
@interpolation_characteristics
@musical_applications
@usage_example
| PortamentoPlayer::PortamentoPlayer | ( | float | sampleRate, |
| float | defaultPortamentoTimeMs = 100.0f ) |
Construct PortamentoPlayer with audio system parameters.
Initialize PortamentoPlayer with audio system parameters.
| sampleRate | Audio processing sample rate in Hz Used for timing calculations and interpolation precision Typical values: 44100, 48000, 96000 Hz |
| defaultPortamentoTimeMs | Default portamento duration in milliseconds Configurable timing for pitch transitions Default: 100ms (musically appropriate for most contexts) Range: [1.0-10000.0]ms practical limits |
@complexity O(1) - Constant time initialization @memory ~32 bytes object size (platform dependent) @thread_safety Safe for concurrent construction
@implementation_notes Constructor initializes all frequency state to 0.0f, ensuring clean startup behavior without frequency artifacts on first note event.
| sampleRate | Audio processing rate for timing calculations |
| defaultPortamentoTimeMs | Initial portamento duration setting |
Initializes all frequency state to zero for clean startup behavior. No frequency output occurs until first noteOn() call establishes valid frequency values.
| float PortamentoPlayer::getCurrentFreq | ( | ) |
Query current instantaneous frequency.
@complexity O(1) - Direct member variable access @precision Full floating-point precision @range [0.0, ~13289.75]Hz (MIDI note 0-127 frequency range)
@applications
Direct frequency accessor for monitoring and secondary processing applications. Provides real-time frequency value without affecting interpolation state.
| int PortamentoPlayer::getCurrentNote | ( | ) |
Query current MIDI note number.
@complexity O(1) - Direct member variable access @thread_safety Safe for concurrent read access
@use_cases
Simple accessor method for external state queries and keyboard tracking applications. Returns stored value regardless of current interpolation state.
|
private |
Perform linear frequency interpolation for smooth transitions.
Execute linear frequency interpolation with completion detection.
Core interpolation algorithm implementing sample-accurate linear frequency transitions. Handles completion detection and state cleanup when target frequency is reached within numerical precision limits.
Core interpolation algorithm implementing sample-accurate linear frequency transitions with automatic completion detection and numerical stability.
@algorithm_analysis The method implements a three-stage decision process:
@numerical_stability Uses absolute value comparison with increment tolerance to prevent oscillation around target frequency due to floating-point precision limits. This ensures clean completion detection regardless of interpolation direction.
@convergence_analysis Convergence condition: |targetFreq - currentFreq| ≤ |incrementPerSample|
This guarantees completion within one additional sample period, preventing infinite interpolation due to numerical precision limitations.
Early return for static frequency (no interpolation active) Optimizes common case where frequency has reached target
Completion detection with numerical tolerance
Checks if remaining frequency difference is smaller than the interpolation increment, indicating completion within one sample period. Uses absolute values to handle both positive and negative frequency transitions correctly.
Interpolation complete: snap to exact target frequency and disable further interpolation processing
Continue linear interpolation: apply calculated increment for smooth frequency progression toward target
|
private |
Convert MIDI note number to frequency using equal temperament.
Convert MIDI note to frequency using equal temperament.
| midiNote | MIDI note number [0-127] |
Implements standard equal temperament conversion formula with 440 Hz reference for A4 (MIDI note 69). Provides standard musical tuning compatible with conventional instruments and software.
| midiNote | MIDI note number input |
@mathematical_implementation Uses standard equal temperament formula: f = 440 * 2^((n-69)/12)
Reference: A4 (MIDI note 69) = 440.0 Hz Semitone ratio: 2^(1/12) ≈ 1.059463 (12th root of 2)
@precision_analysis
@performance_characteristics
| void PortamentoPlayer::noteOff | ( | ) |
Signal note release for envelope coordination.
Signal note release while maintaining frequency output.
Marks note as released while maintaining current frequency for envelope release phase. Frequency continues processing to support amplitude envelope decay without pitch artifacts.
@complexity O(1) - Simple state flag update @realtime_safety Real-time safe (no blocking operations)
@behavioral_notes
Simple state update allowing continued frequency generation during amplitude envelope release phase. Frequency interpolation continues if active, providing smooth pitch behavior during note decay.
| void PortamentoPlayer::noteOn | ( | int | midiNote, |
| bool | portamentoOn ) |
Trigger new note with optional portamento control.
Process note-on event with portamento control.
Initiates frequency transition to new MIDI note with configurable portamento behavior. Calculates target frequency and interpolation parameters for smooth real-time processing.
| midiNote | Target MIDI note number [0-127] Converted to frequency using equal temperament formula Note 69 (A4) = 440.0 Hz reference |
| portamentoOn | Enable/disable portamento for this transition true: Smooth interpolation from current frequency false: Immediate frequency jump (staccato) |
@complexity O(1) - Constant time note processing @precision IEEE 754 floating-point arithmetic accuracy @realtime_safety Real-time safe (deterministic execution time)
@algorithm_behavior
@state_updates Updates internal state variables:
| midiNote | Target MIDI note number |
| portamentoOn | Enable smooth frequency transition |
@algorithm_implementation The method implements conditional behavior based on portamento settings and current frequency state:
@mathematical_precision Interpolation timing: samples = (timeMs / 1000.0) * sampleRate Step size: increment = (targetFreq - currentFreq) / samples
This provides linear frequency interpolation with exact timing control independent of audio buffer sizes or system scheduling variations.
Calculate target frequency using equal temperament conversion Always performed to ensure proper frequency reference regardless of portamento settings
Determine interpolation behavior based on portamento settings and current frequency state
Immediate frequency jump for:
Calculate smooth interpolation parameters for legato transition
Convert portamento time to sample count for precise timing: portamentoSamples = (timeMs / 1000.0) * sampleRate
Calculate linear interpolation increment: incrementPerSample = frequency_difference / time_in_samples
Update state variables for processing and external queries
| float PortamentoPlayer::process | ( | ) |
Generate next frequency sample with interpolation processing.
Main processing method for real-time frequency generation.
Core processing method called once per audio sample to generate current frequency value with smooth interpolation. Handles all interpolation logic, completion detection, and state management.
@complexity O(1) - Constant time per sample processing @determinism Bounded execution time regardless of interpolation state @realtime_safety Real-time safe (no allocation or blocking)
@processing_logic
@state_management
@call_pattern Must be called exactly once per audio sample for proper timing:
@processing_strategy Implements conditional processing based on note state and interpolation status:
This approach ensures continuous frequency output during amplitude envelope release phases while allowing interpolation to complete naturally.
@real_time_considerations
@musical_behavior The processing continues frequency generation after note-off to support natural amplitude envelope decay without pitch artifacts. This matches the behavior of acoustic instruments and traditional analog synthesizers.
Determine if active frequency processing is required
Conditions for active processing:
This logic ensures frequency continues updating during:
Sustain current frequency for envelope release
When note is off and target frequency reached, maintain current frequency to support amplitude envelope decay without pitch drift or artifacts
| void PortamentoPlayer::setPortamentoTime | ( | float | timeMs | ) |
Update portamento timing parameter in real-time.
Update portamento timing parameter.
| timeMs | New portamento duration in milliseconds Controls the time required for complete pitch transitions Affects only future note events (current glides unchanged) |
@range [0.1-10000.0]ms practical limits for musical applications @precision Full floating-point precision maintained @realtime_safety Real-time safe (no allocation or blocking)
@musical_considerations
| timeMs | New portamento duration in milliseconds |
Simple parameter update affecting future note transitions. No validation performed for maximum real-time performance.
|
private |
Current instantaneous frequency in Hz.
Real-time frequency value updated each sample during interpolation. Represents the exact frequency being output for oscillator control.
|
private |
Current MIDI note number being processed.
Stores the most recent MIDI note number passed to noteOn() for external state queries and keyboard tracking applications.
|
private |
Frequency increment per audio sample.
Calculated interpolation step size for linear frequency progression. Value determined by (targetFreq - currentFreq) / portamentoSamples providing precise timing control over frequency transitions.
|
private |
Note activity state flag.
Boolean indicator of current note status for processing control. Used to determine when frequency generation should continue during envelope release phases after note-off events.
|
private |
Portamento duration in milliseconds.
User-configurable timing parameter controlling the duration of frequency transitions. Converted to sample count for precise interpolation timing calculations.
|
private |
Audio system sample rate in Hz.
Cached sample rate used for timing calculations and interpolation precision. Enables sample-accurate portamento timing independent of audio system configuration.
|
private |
Target frequency for interpolation in Hz.
Destination frequency calculated from MIDI note number using equal temperament conversion. Interpolation progresses toward this value over the configured portamento duration.