>>> MINI VIRTUAL ANALOG SYNTHESIZER


r101: 2015-03-14 8:14 PM
* Enabled enhanced debugging of x87 release builds (/Zo option)

r100: 2015-02-18 3:48 PM
* Support for listening to specific MIDI channels
- Defaults to listening to all channels

r99: 2015-02-18 3:44 PM
* Added four more note keys: 9, O, 0, and P

r98: 2015-02-18 3:42 PM
* Fixed release getting cut off if the decay time was zero
- This was a bug in the ADSR envelope update

r97: 2015-02-18 3:41 PM
* Enabled enhanced debugging of release builds (/Zo option)

r96: 2014-02-27 11:40 PM
* Organize Visual Studio project into folders

r95: 2014-02-27 11:34 PM
* Remove unused FX menu
- It got replaced by the Effect page

r94: 2014-02-27 10:56 PM
* Convert all displays to classes
- Eliminates a bunch of icky global variables :)

r93: 2014-02-27 12:51 AM
* NoteOn resets the filter envelope if the voice is completely off
- Fixes odd behavior by the filter envelope

r92: 2014-02-16 2:19 AM
* Add filter drive parameter
- Multiplies input signal before feedback and saturation
* Show filter resonance as a percentage
- Filter self-oscillates above 100%

r91: 2014-02-16 12:13 AM
* Show cutoff frequency in the filter menu title bar
- Useful when tuning the cutoff to a specific frequency

Fifth Public Release (2014-02-14)

r90: 2014-02-15 12:20 AM
* Tweak screen layout
- Increase spectrum analyzer height to 10 characters
- Position menu pages relative to bottom of spectrum analyzer
- Position menus relative to menu page
* Remember active menu on each page

r89: 2014-02-14 11:09 PM
* Add configuration for x87 release build

r88: 2014-02-14 11:08 PM
* Add function key indicators for main and effects pages

r87: 2014-02-14 10:29 PM
* Add critical section to spectrum analyzer
- Prevents occasional visual glitches

r86: 2014-02-14 9:35 PM
* Fix key envelope indicators sometimes not appearing

r85: 2014-02-14 9:30 PM
* Spectrum analyzer uses a sliding sample buffer
- Fixes smeared-out peaks caused by truncated sample data

r84: 2014-02-11 2:14 AM
* Clean up key volume display

r83: 2014-02-10 9:02 AM
* Add key follow parameter to note oscillator and filter
- Determines how much the note keys affect the frequency
- Key follow range centers on middle C (261.6 Hz)

r82: 2014-02-09 8:59 PM
* Fix some compile warnings

r81: 2014-02-09 1:14 AM
* Update keyboard range
- Add 25th key (I)
- Range centered on Q key (middle C initially)
- Z key is one octave down
- I key is one octave up

r80: 2014-02-09 5:25 PM
* Take advantage of phase being in the range [0,1)
- Integrated from the integer phase code branch
* Add linearly-interpolated noise
- Uses IntegratedPolyBLEP for bandlimiting

r79: 2014-02-08 5:22 PM
* Perform oscillator index wrapping
- This should be done by the wave types that need it...

r78: 2014-02-08 5:19 PM
* Show display immediately before starting run
* Set initial frequency to middle C

r77: 2014-02-08 5:17 PM
* Rename variable to reflect usage

r76: 2014-02-08 5:17 PM
* Fix menu-positioning bug

r75: 2014-02-08 5:16 PM
* Improve accuracy of TPT filter for fc in the range [0.5,1.0]
- Comments document the mathematics

r74: 2014-02-08 4:49 PM
* Revise oscillator waveform display
- Move all static data out of the update function
- Use osc_config state directly instead of copying it
. Significantly reduces code size of the wave plot
- Oversample plot steps to match sample steps with filter enabled
. Shows filter behavior more accurately
. Fixes "ringing" glitch at sharp transitions with TPT filter
- Increase minimum step divider from 2 to 4
. Shows more detail of waveform
. This should probably be a settable "zoom factor" parameter...

r73: 2014-02-05 9:06 PM
* Envelope sets amplitude to zero on zero-duration release

r72: 2014-02-03 8:53 AM
* Add local state data to Oscillator
- Need to find a better way to do that...
* Noise oscillator generates colored noise
- Inspired by Dave Smith Instruments Prophet-12
- Controlled by Width parameter
- 0%: red noise (-6dB/octave)
- 25%: pink noise (-3dB/octave)
- 50%: white noise (0dB/octave)
- 75%: blue noise (+3dB/octave)
- 100%: violet noise (+6dB/octave)

r71: 2014-02-03 8:50 AM
* Update MIDI input
- Set up buffer for receiving system exclusive messages
- Properly handle Sound Off message

r70: 2014-02-03 8:47 AM
* Floating-point stream buffer
- Audio stack in Windows Vista and later uses float internally

r69: 2014-02-03 8:45 AM
* New Menu system
- Class-based
- Supports multiple pages
* Configurable DirectSound effects
- Dedicated page (F11) and menus (F1-F8)
* Apply some optimizations
- Use static for compile-time constants inside functions
- Envelope generator handles zero-time values without conditionals

r68: 2014-02-01 3:00 PM
* Fix sample value wraparound at high output level
- +32768 would wrap to -32768
* Use UpdatePercentageProperty for output level
- Supports modifier keys and range limit

r67: 2014-02-01 1:01 AM
* Commented what PolyBLEP is really trying to approximate

r66: 2014-02-01 12:49 AM
* Enable SSE2 and __vectorcall by default
- Should make a separate configuration for x87...

r65: 2014-02-01 12:48 AM
* WriteStream optimizations
- Skip LFO update and modulation when LFO is off
- Skip oscillator update when oscillator is off

r64: 2014-01-29 12:42 AM
* Add TPT four-pole ladder filter
- Use simple nonlinearity and gain compensation
- Accurate cutoff frequency and resonance
- No oversampling so it's relatively cheap
* Add (compile time) filter controls
- Saturate feedback or saturate input
- Variety of saturation functions

r63: 2014-01-28 8:47 PM
* Filter config stores mix parameters
- Would permit custom mixing
- Set via SetMode method
* Add linear variant of Huovilainen Moog filter
- Use nonlinear feedback from the Improved Moog filter
- Use gain compensation from the Improved Moog filter
- More expensive to set up but slightly faster to apply
* Fix nonlinear variant of Huovilainen Moog filter
- One-and-a-half sample feedback delay was set up wrong
- Use gain compensation from the Improved Moog filter
* All filter variants share mixing code

r62: 2014-01-25 1:43 PM
* Combine key frequency with step
- Reduces the number of multiplies inside oscillators

r61: 2014-01-24 7:22 PM
* Use NUM_OSCILLATORS for oscillator frequency display

r60: 2014-01-23 4:10 AM
* Fix a compile warning in WavePoly

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
