Both sides previous revision
Previous revision
Next revision
|
Previous revision
|
sarah [2017/09/05 22:10] shane [About SARAH's oscillators] |
sarah [2017/09/30 15:38] (current) shane |
====== SARAH: FFT-based synthesizer plugin ====== | ====== SARAH: FFT-based synthesizer plugin ====== |
**SARAH** is an improved and expanded version of [[VanillaJuce]] which uses the new DSP classes provided in JUCE 5.1 to address the problem of oscillator aliasing. It works by using //juce::dsp::FFT// to transform mathematically-perfect oscillator waveforms, zeroing out unwanted high-frequency harmonics, and reverse-transforming to produce perfectly band-limited wave tables. Just for fun (and because I wanted to know if it was even possible without killing the CPU), it also implements simulated low-pass filtering in the frequency domain. | **SARAH** is an improved and expanded version of [[VanillaJuce]] which uses the new DSP classes provided in JUCE 5.1 to address the problem of oscillator aliasing. It works by using //juce::dsp::FFT// to transform mathematically-perfect oscillator waveforms, zeroing out unwanted high-frequency harmonics, and reverse-transforming to produce perfectly band-limited wave tables. Just for fun (and because I wanted to know if it was even possible without killing the CPU), it also implements simulated low-pass filtering (which I call //Harmonic Shaping//) in the frequency domain. |
| |
Because of the use of the Harmonic Analysis, via the Fast Fourier Transform, and because Fourier himself was French, and because the really great name [[http://www.image-line.com/plugins/Synths/Harmor/|Harmor]] was already taken, and because there's a fabulous singer-songwriter in my hometown whose name is [[https://en.wikipedia.org/wiki/Sarah_Harmer|Sarah Harmer]], I decided to use the name **SARAH**, and let it stand for //synthèse à rapide analyse harmonique//, or "synthesis by fast harmonic analysis". | Because of the use of the Harmonic Analysis, via the Fast Fourier Transform, and because Fourier himself was French, and because the really great name [[http://www.image-line.com/plugins/Synths/Harmor/|Harmor]] was already taken, and because there's a fabulous singer-songwriter in my hometown whose name is [[https://en.wikipedia.org/wiki/Sarah_Harmer|Sarah Harmer]], I decided to use the name **SARAH**, and let it stand for //synthèse à rapide analyse harmonique//, or "synthesis by fast harmonic analysis". |
| |
===== About SARAH's oscillators ===== | ===== About SARAH's oscillators ===== |
The oscillators are the only interesting aspect of SARAH's design. All of the other elements shown in the signal-flow diagram above (Envelope Generators, LFOs, summing and scaling) are entirely conventional. | The oscillators are the only interesting aspect of SARAH's design. All of the other elements shown in the signal-flow diagram above (Envelope Generators, LFOs, summing and scaling) are entirely conventional. The following is a quick summary; for details see [[SARAH oscillator details]]. |
| |
SARAH's oscillators are wave-table based. They play out samples from a 1024-element digitized representation of one cycle of the selected waveform---sine, triangle, square, or sawtooth. What is interesting and new is how the 1024-element wave tables are populated. | SARAH's oscillators are wave-table based. They play out samples from a 1024-element digitized representation of one cycle of the selected waveform---sine, triangle, square, or sawtooth. What is interesting and new is how the 1024-element wave tables are populated. |
- 1024 samples of each waveform (one cycle) are generated once, using exactly the same mathematical expressions used in the LFOs, resulting in mathematically "exact" waveforms having 512 harmonics. | - 1024 samples of each waveform (one cycle) are generated once, using exactly the same mathematical expressions used in the LFOs, resulting in mathematically "exact" waveforms having 512 harmonics. |
- Each mathematically-exact waveform is transformed using //juce::dsp::FFT// to produce a frequency-domain representation, which is a new 1024-element array, where each element ("coefficient") represents the relative amplitude and phase of all 512 harmonics. These three "frequency-domain" tables (one each for triangle, square, and sawtooth wave shapes) are kept in memory. | - Each mathematically-exact waveform is transformed using //juce::dsp::FFT// to produce a frequency-domain representation, which is a new 1024-element array, where each element ("coefficient") represents the relative amplitude and phase of all 512 harmonics. These three "frequency-domain" tables (one each for triangle, square, and sawtooth wave shapes) are kept in memory. |
- Each oscillator instance has its own 1024-element array. In preparation to sound a note, it copies the coefficient data out from the appropriate common frequency-domain table to its own array, then performs an //in-place **inverse** FFT// to re-create the appropriate time-domain wave table. To prevent aliasing, only the coefficients for harmonics below the //Nyquist frequency// (one-half the sampling rate) are copied; higher-order coefficients are set to zero. | - Each oscillator instance has its own 1024-element array. In preparation to sound a note, it copies the coefficient data out from the appropriate common frequency-domain table to its own array, then performs an //in-place **inverse FFT**// to reconstruct the appropriate time-domain wave table. To prevent aliasing, only the coefficients for harmonics below the //Nyquist frequency// (one-half the sampling rate) are copied; higher-order coefficients are set to zero. |
- To sound a note, the oscillator resamples its own 1024-element array (wave table). | |
| |
See [[SARAH oscillator details]]. | ===== Harmonic Shaping ===== |
| Zeroing (or changing in any way) the coefficients of a frequency-domain signal and then performing an inverse FFT is basically a kind of filtering. After I had implemented the dynamic wavetable reconstruction algorithm described above, it occurred to me that I could easily apply some kind of frequency-response curve to the non-zero harmonic components, to obtain a similar effect as running the oscillator output through a conventional filter. This requires many more inverse FFT operations (because it must be done dynamically, to simulate a time-varying filter cutoff), but I found that on modern PC and Mac hardware, this is not impractical. |
| |
| Because SARAH is using coefficient adjustments and the inverse FFT to //simulate// filtering, I decided to call this //Harmonic Shaping// rather than "filtering". I'm not at all convinced this is a sensible alternative to conventional (time-domain) digital filtering, but it is certainly interesting, and allowed me to implement simple time-varying timbres (using both an envelope generator and an LFO) with just a few simple changes to the existing anti-aliased oscillator code. |
| |
| ===== The details ===== |
| See [[sarah_oscillator_details|this page]] for the gritty details of SARAH's oscillator implementation. |
| |
| ===== Skinning ===== |
| As of 29 September, 2017, SARAH uses a single-view GUI instead of the multi-tabbed approach inherited from [[https://github.com/getdunne/VanillaJuce|VanillaJuce]]. See [[sarah_skinning|this page]] for some thoughts on the two approaches. |
| |
(More to come...) | |
| |
| |