Both sides previous revision
Previous revision
Next revision
|
Previous revision
|
sarah_oscillator_details [2017/09/05 23:35] shane |
sarah_oscillator_details [2017/09/05 23:42] (current) shane [The resulting code] |
====== SARAH Oscillator Details ====== | ====== SARAH Oscillator Details ====== |
| |
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 [[sarah|signal-flow diagram]] (Envelope Generators, LFOs, summing and scaling) are entirely conventional. |
| |
SARAH uses two oscillator instances per voice. The oscillators themselves are identically structured, but their settings are independent, i.e., they can be set to produce different waveforms, detuned, and mixed so as to provide at least a basic set of options to create composite timbres, and each oscillator's inherent "harmonic shaping" can also be set up differently, to provide further control. The following explanation (which is just an overview) applies equally to OSC1 and OSC2. | SARAH uses two oscillator instances per voice. The oscillators themselves are identically structured, but their settings are independent, i.e., they can be set to produce different waveforms, detuned, and mixed so as to provide at least a basic set of options to create composite timbres, and each oscillator's inherent "harmonic shaping" can also be set up differently, to provide further control. The following explanation (which is just an overview) applies equally to OSC1 and OSC2. |
* Element 1023 represents the 1st harmonic (fundamental) | * Element 1023 represents the 1st harmonic (fundamental) |
| |
//Why are the 1st through 511th harmonics represented twice?// This is because the Fourier Transform works in terms of both //positive// and //negative frequencies//, where a negative frequency is interpreted as the Nyquist frequency minus the absolute frequency value. (This is related to the phenomenon of aliasing. When a positive frequency is beyond the Nyqyist frequency, it is "aliased" to the corresponding negative frequency. The human ear hears this negative frequency just the same as the corresponding positive one.) The 0th harmonic, whose frequency is zero Hz, is its own negative. So is the 512th harmonic, owing to the arcane mathematics of the FFT. | //Why are the 1st through 511th harmonics represented twice?// This is because the Fourier Transform works in terms of both //positive// and //negative frequencies//, where a negative frequency is interpreted as the Nyquist frequency minus the absolute frequency value. (This is related to the phenomenon of aliasing. When a positive frequency is beyond the Nyqyist frequency, it is "aliased" to the corresponding negative frequency. The human ear hears this negative frequency just the same as the corresponding positive one.) The 0th harmonic, whose frequency is zero Hz, is its own negative. Owing to the arcane mathematics of the FFT, so is the 512th harmonic. |
| |
===== The resulting code ===== | ===== The resulting code ===== |
* The ''for'' loop runs through the harmonic indices 1 through ''maxHarmonicToRetain'', copies both the positive and negative-frequency coefficients out of the master table (a pointer to which is returned by //SynthOscillatorBase::getFourierTable(waveform)//, and then scales the resulting copies by a factor ''fv'' computed by an expression which models the response curve of a simple low-pass filter with a given cutoff frequency (expressed in cycles per sample) and slope (expressed in dB per octave). | * The ''for'' loop runs through the harmonic indices 1 through ''maxHarmonicToRetain'', copies both the positive and negative-frequency coefficients out of the master table (a pointer to which is returned by //SynthOscillatorBase::getFourierTable(waveform)//, and then scales the resulting copies by a factor ''fv'' computed by an expression which models the response curve of a simple low-pass filter with a given cutoff frequency (expressed in cycles per sample) and slope (expressed in dB per octave). |
* Finally, we request an inverse FFT on the ''waveTable[]'' array. | * Finally, we request an inverse FFT on the ''waveTable[]'' array. |
| |
| The astute reader will have noted that the ''for'' loop skips the 0th harmonic. The 0th harmonic of an digitized AC signal represents the //DC component// (net offset from zero) which is neither audible nor desirable in a digital signal processing system. Ensuring that the 0th-harmonic coefficient is always zero results in output waveforms which are guaranteed to be symmetric about zero---yet another free gift from the FFT. |
| |
===== "Real-Only" FFT ===== | ===== "Real-Only" FFT ===== |