>>> MINI VIRTUAL ANALOG SYNTHESIZER

Fourth Public Release (2014-01-06)

r59: 2014-01-23 4:08 AM
* Amplifier config defaults to using key velocity

r57: 2014-01-13 3:55 AM
* Fix visual glitches in the Oscillator Waveform display

r56: 2014-01-23 3:41 AM
* Math
- Lerp linear interpolation function
- SSE versions of RoundInt, FloorInt, CeilInt, and TruncateInt

r55: 2014-01-13 3:39 AM
* Rename LFO_UPDATE_SAMPLES to BLOCK_UPDATE_SAMPLES
- ...because it's for all per-block updates, not just LFO
* Set FPU to flush denormals in StreamWrite
- They're much slower than normal floating-point values

r54: 2014-01-21 2:42 AM
* EnvelopeState Gate skips states with zero times
- Attack time zero: skip to Decay
- Decay time zero: skip to Sustain
- Release time zero: skip to Off

r53: 2014-01-20 10:06 PM
* OscillatorConfig includes wave properties
- Wave evaluate function, cycle length, frequency adjust

r52: 2014-01-19 11:23 PM
* Improve IntegratedPolyBLEP
- Closer approximation of cosine shape
- Can use a smaller width scale factor

r51: 2014-01-19 11:20 PM
* Restore previous Sawtooth and Pulse antialiasing
- Limiting maximum PolyBLEP width to 0.5 solves the original problem
- Should reduce CPU cost a bit

r50: 2014-01-19 11:03 PM
* Filter Modes
- 2x magnitude on Band-Pass 1 (+ Low-/High-Pass 1/2)
- 4x magnitude on Band-Pass 2
- Notch 1 + High-Pass 1/2
- Notch 2: two Notch 1 in series
- Phase-Shift 1-4: 1-/2-/3-/4-pole All-Pass phase shifter
* Filter documentation
- Combining filters (parallel, scale, series)
- Frequency-based phase shifts
- Explain filter mix coefficients

r49: 2014-01-19 3:18 AM
* Update control parameters every 16 samples
- Low-frequency oscillator
- Oscillator LFO modulation (which uses powf)
- Filter LFO and envelope modulation (which uses expf)
- Significantly reduces CPU cost

r48: 2014-01-18 6:21 PM
* New PolyBLEP and IntegratedPolyBLEP variants
- General versions taking a step size
- Specialized versions with hard-coded step sizes
- Optimize code: fewer branches
* Add "Noise Hold" wave type
- Hold random value for wave period
- Currently implemented as a wave table
- TO DO: replace with a true sample-and-hold mechanism
* Fix Sawtooth and Pulse antialiasing for step > 1/3
- Need to include previous and next edges
* Rename OscillatorFunc to WaveEvaluate
- That's what it does :)

r46: 2014-01-18 1:03 AM
* Replace voice "volume" with "amplifier"
- Rename menu, enumerations, variables, etc.
- New AmplifierConfig class for amplifier parameters
* Move envelope config/state objects 
- Filter envelope in Filter.cpp/.h
- Amplifier envelope in Amplifier.cpp/.h
* Support note velocities
- Treat 64 as 100%
- Keyboard keys produce a velocity of 64
- Filter: velocity modulation of cutoff envelope
- Amplifier: velocity modulation of level envelope
- Velocity has zero influence by default

r45: 2014-01-17 8:35 PM
* Add pitch wheel control
- Pitch +/- 2 semitones per General MIDI
* Increase voice count from 12 to 16

r43: 2014-01-17 2:24 AM
* MIDI frequency table
- 11 octaves of frequency table entries
* "Voices" independent of keys
- Notes allocate voices as needed
* Functional MIDI input
- Note On, Note Off, All Notes Off

r42: 2014-01-16 10:50 PM
* Preliminary support for MIDI input
- Opens device ID 0 if available
- Currently just prints debug messages

r41: 
* Fix down edge of pulse waveform

r40: 2014-01-15 12:13 AM
* New Poly variants
- Period-93: short-period noise based on NES 2A03 APU
- Poly9: 9-bit LFSR based on Atari TIA and POKEY

r39: 2014-01-14 8:23 PM
* Add Menu::SetActive function

r38: 2014-01-14 2:35 AM
* Enclose menu-related functions and data in namespaces
* Split out "menu" functionality into separate files
* Split out "effect" functionality into separate files

r37: 2014-01-14 2:31 AM
* Simplify key volume envelope display

r36: 2014-01-14 2:26 AM
* Remove a redundant "const" from declaration of filter names

r35: 2014-01-14 2:25 AM
* Waveform display uses a shared UpdateWaveformStep function

r34: 2014-01-11 5:25 PM
* Split out "display" functionality into separate files
- DisplayKeyVolumeEnvelope: per-key volume envelope
- DisplayLowFrequencyOscillator: low-frequency oscillator "metronome"
- DisplayOscillatorFrequency: per-oscillator frequency
- DisplayOscillatorWaveform: combined oscillator/filter/volume waveform
- DisplaySpectrumAnalyzer: log-log frequency/power spectrum
* Move key-related values into a shared file

r33: 2014-01-11 4:06 PM
* Split out "simulation" functionality into separate files
- Envelope: envelope generators
- Filter: resonant filter
- Oscillator: base oscillator
- OscillatorLFO: low-frequency oscillator
- OscillatorNote: per-voice oscillators
- PolyBLEP: polynomial bandlimited step
- SubOscillator: sub-oscillator
- Wave: shared wave data
- WaveNoise: white noise
- WavePoly: poly noise
- WavePulse: pulse wave
- WaveSawtooth: sawtooth wave
- WaveSine: sine wave
- WaveTriangle: triangle wave

r32: 2014-01-11 2:24 PM
* Split out more functionality into separate files
- Menu: shared menu functionality
* Waveform display takes modulated frequency into account

r31: 2014-01-09 11:12 PM
* Split out some functionality into separate files
- Console: console display utilities
- Debug: debug print
- Math: math utility functions
- Random: xor-shift random number generator
- StdAfx: precompiled header

r30: 2014-01-09 1:34 AM
* Sub-Oscillator
- Uses oscillator state index to generate lower-frequency tones
- Square wave one octave down
- Square wave two octaves down
- Pulse wave two octaves down

r29: 2014-01-09 12:09 AM
* New OscillatorState methods to reduce duplicate code
- Compute: get the oscillator's current value
- Advance: advance the oscillator's phase (and index)
- Update uses these internally

r28: 2014-01-08 9:41 AM
* Move some duplicated functionality into functions
- EnvelopeState::Gate for contolling envelope state
- NoteOscillatorConfig::Modulate for applying LFO modulation
* Fix signs of filter mixing parameters
- Values were negated, inverting the output
* Try to keep filter state stable in the waveform display

Third Public Release (2014-01-06)

r27: 2014-01-06 12:52 AM
* Enable and disable individual components
- The component's menu bar is a selectable item
- Right arrow enables, left arrow disables
- Bypass the component when disabled
* Remove Filter mode "None"
* Show component state visually
- Blue/cyan title bar with green ON when enabled
- Red/yellow title bar with red OFF when disabled
* New PrintConsoleWithAttribute function
- Print text onto the console with the specified attribute set
* Show envelope values in seconds
- Attack takes 1x the shown time to arrive
- Decay and Release take 3x the shown value to arrive
- Large step: 1s
- Normal step: 0.1s
- Small step: 0.01s
- Tiny step: 0.001s
* Show yellow markers next to the selected item
- Improves readability

r26: 2014-01-05 3:46 PM
* Bandlimited hard-sync
- Set oscillator sync phase based on OSC1
- Sine, pulse, sawtooth, and triangle fully support it
- Apply PolyBLEP/IntegratedPolyBLEP at discontinuity
- May not synchronize perfectly if OSC1 changes frequency quickly
* Fast float to integer routines
- Independent of FPU rounding mode
- Range restricted to [-2**30, 2**30-1]
- FloorInt: round down
- CeilInt: round up
- RoundInt: round to nearest integer

r25: 2014-01-05 9:18 AM
* Add winmm.lib to linker dependencies
- Time step calculation needs it

r24: 2014-01-04 2:01 PM
* Waveform display handles filter state better
- Apply cutoff frequency properly
- Run oscillators and filter by a frame time step
- Filter dynamics update at realtime (for the most part)

r23: 2014-01-04 11:49 AM
* Use arrays of filter stage mix coefficients
- Eliminates the giant switch statement
- FilterState::Apply does the mixing itself
- Nonlinear Moog filter does the mixing too
* Slightly-modified nonlinear Moog filter

r22: 2014-01-04 4:14 AM
* Support multiple oscillators
- Currently two (set by NUM_OSCILLATORS)
* Rearrange menus to fit second oscillator
* Convert all structs to classes
- Add constructors
- Made members all public (for now)
* Combo waveform display
- Plots OSC1 + OSC2 with filter effect and volume envelope
- Assumes OSC1 is the "master" oscillator
- Tracks the most-recently-pressed note key
* Oscillator menus show current frequency in Hz
* Filter modes
- Mix values from low-pass filter stages
- Based on Oberheim Xpander and Matrix-12 multi-mode filter
- Document where the mix coefficients came from
- High-pass 1, 2, 3, 4
- Band-pass 1, 2
- Band-pass 1 + low-pass 1, 2
- Band-pass 1 + high-pass 1, 2
- Notch
- Notch + low-pass 1, 2

r21: 2014-01-03 12:30 AM
* New POKEY waveforms
- Pulse/Poly5: pulse clocked by Poly5 (what POKEY actually does)
- Poly4/Poly5: Poly4 clocked by Poly5
- Poly17/Poly5: Poly17 clocked by Poly5
- Restored original poly4, poly5, and poly17 tables
* Add OscillatorState::Reset member function
* Simplify OscillatorPoly
- Check for edges over a range of wavetable entries
* Restore original waveform display height

r20: 2014-01-01 11:03 PM
* General cleanup
- Added copyright
- Remove some unused code
- Add some comments
* Waveform display uses defines instead of literals

r19: 2014-01-01 10:09 PM
* Amplitude uses linear modulation
- Not sure if this is correct...
* Revised waveform display 
- Postive values show blue fill down to the midline
- Negative values show red fill up to the midline

r18: 2014-01-01 9:31 PM
* Change poly LFSR tables into precomputed wavetables
- POKEY togles output when the LFSR generates a high bit
- Wavetable version already includes this toggling
- No need for oscillator loop callback functions
- I may regret this if I add Poly4+Poly5 and Poly17+Poly5 modes...
* Poly oscillator antialiasing can step +/- 8 phases
- Corrects aliasing at very high frequencies

r17: 2014-01-01 8:20 PM
* Fix waveform glitch in pulse oscillator
- Handle pulse width outside (0, 1) interval
- Add extra PolyBLEP for down-step at phase 1 + width

Second Public Release (2014-01-01)

r16: 2014-01-01 4:07:34 PM
* Tweak PolyBlep and IntegratedPolyBLEP interval to (-w, w)
* Add LFOOscillatorConfig struct
- Contains frequency_base for use by the menu
- Menu computes actual frequency from it
* Show Antialias setting
* Menus use helper functions to change setting values
- Eliminates a bunch of code
- Ensures consistent behavior
- Hold Shift for large step
- Unmodified for normal step
- Hold Ctrl for small step
- Hold Alt for tiny step
- UpdateFrequencyProperty: 1 octave, 1 semitone, 0.1 semitone, 0.01 semitone
- UpdatePercentageProperty: 1/4 step, 1/16 step, 1/64 step, 1/256 step
* Clean up menu presentation

r15: 2014-01-01 1:21:09 AM
Happy New Year!
* Simplify PolyBLEP and IntegratedPolyBLEP
- Covers interval [-w, +w] instead of [0, w] and [1-w, 1]
- Makes it more straightforward to use
- Properly handles non-periodic events
* Add oscillator loop callback functions
- Poly evaluators use it as a "clock event"
* Bandlimited poly4, poly5, and poly17 waveforms
- Apply PolyBLEP correction at value transitions
- Shared implementation in OscillatorPoly and OscillatorPolyLoop
* Adjust frequency of poly4, poly5, and poly17
- One octive up instead of two
- Matches behavior of the Atari POKEY
* Merge LFO and OSC implementations
- OscillatorConfig settings common to both
- OscillatorState state common to both
- NoteOscillatorConfig adds modulation parameters
- Pass OscillatorConfig and OscillatorState to evaluator functions
* Clean up oscillator waveform display
- Better variable names
- More and better comments
- Uses a local copy of the oscillator configuration
* Add low-frequency oscillator display
- "Metronome" beneath LFO menu
* Restore "no active oscilators" code path

r14: 2013-12-31 7:54 PM
* Code reorganization
- Move spectrum analyzer logic to UpdateSpectrumAnalyzer
- Move key volume display logic to UpdateKeyVolumeEnvelopeDisplay
- Move waveform display logic to UpdateOscillatorWaveformDisplay

r13: 2013-12-31 7:37 PM
* Bandlimited sawtooth, pulse, and triangle waveforms
- Experimental wavetable implementation of sawtooth (#ifdeffed out)
- PolyBLEP: polynomial correction for C0 discontinuity
- IntegratedPolyBLEP: polynomial correction for C1 disctontinuity
- Pass phase step instead of amplitude to evaluators
- Evaluators check phase step against limit
- F12 key toggles antialiasing
* Replace hyperbolic tangents with a fast rational polynomial approximation
* Spectrum analyzer shows 20 kHz limit
* Waveform display
- Plot waveform generated by the lowest note key
- Reflects oscillator settings and realtime LFO values

r12: 2013-12-30 9:06 PM
* Spectrum analyzer shows Nyquist limit
- Frequency columns above the limit are red
* Simplify sawtooth and triangle oscillators
* Oscillators return 0 if delta phase is 0.5 or more
- That means the frequency is above the Nyquist limit
* Handle negative phase delta
- In anticipation of frequency modulation...

First Public Release (2013-12-30)

r11: 2013-12-30 2:26 PM
* Fix compiler warnings
* Add comments
* Temporarily disable "no oscillators running" code path
* Update spectrum analyzer
- Use 8192-sample FFT
- Generate spectrum from complex FFT data
- Document code better

r10: 2013-12-30 12:46 AM
* Update Spectrum Analyzer
- Move properties to globals
- Increase width to 80 semitones
- Increase height to 8
- Start one octave lower
- Update at ~60 FPS
* Remove buffer size settings
* Change volume keys to - and +
* Reposition effects menu

r9: 2013-12-29 11:11 PM
* Spectrum Analyzer
- 1 semitone frequency per column
- 6 dB power attenuation per row
- 60x6 rectangle at the top of the window
- Update at ~20 FPS
* Reposition note keys beneath analyzer

r8: 2013-12-29 5:56 PM
* New title text
* Change ENV menu to VOL
- Reflects its purpose
* Separate ADSR envelopes for filter and volume
* Move filter config data to a struct
* Move LFO state update to a member function
* Move note key frequencies to a separate array
- Remove frequency member from OscillatorState
* Clean up FLT and VOL menu logic
- Combine decrease and increase cases
* Reposition effect menu
* Increase window size to 80x50
* Generate note key positions procedurallly
- Arrange in a horizontal line

r7: 2013-12-29 2:13 AM
* Reduce to two filter variations
- Improved Moog: linear IIR with nonlinear feedback
- Nonlinear Moog: full nonlinear IIR
- Both have accurate cutoff frequency tuning
* Expand octave range to [0..8]

r6: 2013-12-29 1:09 AM
* Antti Huovilainen nonlinear digital filter
- http://dafx04.na.infn.it/WebProc/Proc/P_061.pdf
- https://raw.github.com/ddiakopoulos/MoogLadders/master/Source/Huovilainen.cpp
* General IIR digital filter
- Single implementation for all IIR "variation" filters
- Document the origins of each variation's parameters
- Variation 0: http://www.musicdsp.org/showArchiveComment.php?ArchiveID=24
- Variation 1: http://www.musicdsp.org/showArchiveComment.php?ArchiveID=25
- Variation 2: http://www.musicdsp.org/showArchiveComment.php?ArchiveID=26
- Variation 3: http://courses.cs.washington.edu/courses/cse490s/11au/Readings/Digital_Sound_Generation_2.pdf
- Variation 4: http://www.music.mcgill.ca/~ich/research/misc/papers/cr1071.pdf

r5: 2013-11-28 5:40 PM
- Move config data and state data into structs
- LFO: LFOConfig, LFOState
- OSC: OscillatorConfig, OscillatorState
- ENV: EnvelopeConfig, EnvelopeState
* Move simulation logic into struct member functions
- This means the structs should be classes...
- LFO: LFOState::Update()
- OSC: OscillatorState::Update()
- ENV: EnvelopeState::Update()
* Filter supports multiple modes
- None (disabled)
- All-pass (input + feedback term)
- 4 High-pass (output from stage 1, 2, 3, and 4)
- 4 Low-pass
- Band-pass
- Notch
* Another filter code variant
- Custom IIR filter with settings based on a published paper
- Combine input and output state array
- Comments explain how the optimization works
- Changed other variants to use the same state array
* Restore keyboard-controlled octave shift
- [ to decrease, ] to increase
* Add oscillator base amplitude setting
* Clean up menu logic
- Combine decrease and increase cases
- Half the to wrangle :)
* Colorize non-menu key controls
- Buffer size, output scale, key octave

r4: 2013-12-27 9:30 AM
First Virtual Analog Synthesizer features
* Resonant low-pass filter (FLT)
- Key-tracking cutoff frequency
- Configurable resonance
- Several different code variations...
* White noise oscillator
- XOR-shift random number generator from VideoVenture
* Keyboard-controllable output volume
- F10 to decrease, F11 to increase
* Soft-saturate output
- Hyperbolic tangent instead of clamp
* Enable floating-point exceptions with debugger attached

r3: * Add ADSR volume envelope (ENV)
- Replaces the fixed volume decay envelope
- Note key acts as the gate signal
* Add low frequency oscillator (LFO)
- Same waveform evaluator functions as main oscillator
- Separate oscillator state
- Shared between voices
* Rewrote oscillator logic (OSC)
- Evaluate active oscillators per sample
- Use frequency in Hz
- Apply modulation from LFO
* Add on-screen menu system
- Edit LFO, OSC, and ENV settings
- Replaces old octave, wave type, and effect displays

r2: Initial C++ revision
Major changes relative to the original BASS Simple Synth:
* Reformatted and reorganized code
* Two full octaves of note keys
* Square, Sawtooth, Triangle Poly4, Poly5, and Poly17 waveforms
* Display text using Windows console API
* Highlight active note keys
