Teoría de la Síntesis de Sonido/Osciladores y Tablas de Ondas
Osciladores y Tablas de Ondas
editarOsciladores
editarUn oscilador es una forma de onda repetitiva con una frecuencia fundamental y amplitud máxima y constituye la base de las técnicas de síntesis más populares en la actualidad. Además de la frecuencia o el tono del oscilador y su amplitud, una de las características más importantes es la forma de su forma de onda. Las formas de onda de dominio de tiempo en Fig. 5.1 muestra las cuatro formas de onda del oscilador usadas más comúnmente. Aunque es posible utilizar todo tipo de formas únicas, estas cuatro sirven para un rango de funciones que se adaptan a una gama de diferentes técnicas de síntesis; que van desde el sonido suave y llano de una onda sinusoidal hasta el zumbido armónicamente rico de una onda de diente de sierra.
Los osciladores generalmente están controlados por un sintetizador de teclado o dispositivo de protocolo MIDI. Una pulsación de tecla dará como resultado un valor de nota MIDI que se convertirá a un valor de frecuencia (Hz) que el oscilador aceptará como su entrada, y el período de forma de onda se repetirá de acuerdo con la frecuencia especificada. Desde aquí, el sonido puede procesarse o manipularse de diversas formas en el sintetizador o programa para enriquecer o modificar el sonido.
Generando las formas de onda del oscilador
editarOnda sinusoidal
editarComo se mencionó anteriormente, la onda sinusoidal puede considerarse el bloque de sonido más fundamental. La mejor forma de generar un oscilador que produzca esta forma de onda es hacer uso de una biblioteca o función incorporada en el sistema en cuestión. Muchos lenguajes de programación tienen bibliotecas de matemáticas estándar con muchas de las funciones trigonométricas representadas. Un ciclo de una onda sinusoidal es radianes de largo y tiene una amplitud máxima de , como se muestra en Fig. 5.2. En un sistema digital, las ondas generadas serán una serie de valores igualmente espaciados a la velocidad de muestreo.
Con una velocidad de muestreo de 44100 ciclos por segundo y una duración de ciclo requerida de 1 segundo, se necesitarán 44100 muestras para pasar de 0 a . En otras palabras, podemos determinar los pasos por ciclo desde la duración del ciclo :
Donde es la frecuencia de muestreo. Por lo tanto, cada paso tomará la siguiente cantidad en radianes:
Donde , en el segundo resultado, se obtiene el mismo resultado en términos de frecuencia. La importancia de esto es que es posible expandirlo en un algoritmo que sea adecuado para generar una onda sinusoidal de una frecuencia y amplitud especificadas por el usuario, ¡efectivamente el sintetizador más simple posible! Una onda sinusoidal puede generarse incrementando repetidamente un valor de fase en una cantidad requerida para alcanzar un número deseado de ciclos de longitud por segundo, a la velocidad de muestreo. Este valor se puede pasar a una función sinusoidal para crear el valor de salida, entre la amplitud máxima especificada por el usuario.
Entrada: amplitud máxima (A), frecuencia (f) Salida: valor de amplitud (y) y = A * sen(fase) fase = fase + ((2 * pi * f) / frecuencia de muestreo) si fase> (2 * pi) luego fase = fase - (2 * pi)
Lo más importante a tener en cuenta acerca de este algoritmo es que cuando el valor de la fase ha excedido se restará por un período completo. Esto es para asegurar que la función "se enrolla" en la posición correcta en lugar de volver directamente a 0; si una fase se incrementa sobrepasando y se restablece a 0, ocurrirán discontinuidades indeseables, causando distorsión armónica en el sonido oscilatorio.
Square wave
editarThe square wave cannot be generated from a mathematical function library so easily but once again the algorithm is particularly straightforward since it is constructed from straight line segments. Unlike the sine wave, square waves have many harmonics above their fundamental frequency, and have a much brighter, sharper timbre. After examining a number of different waveforms it will start to become apparent that waveforms with steep edges and/or abrupt changes and discontinuities are usually harmonically rich.
(Note that the following square, sawtooth, and triangle functions are "naive"; they are equivalent to sampling the ideal mathematical functions without first bandlimiting them. In other words, all of the harmonics above the Nyquist frequency will be aliased back into the audible range. This is most obvious when sweeping one of these waveforms into the high frequencies. The aliased harmonics will move up and down the frequency spectrum, making "radio tuning" sounds in the background. A better method to produce waveforms for audio would be additive synthesis, or something like MinBLEPs. A properly-bandlimited waveform will have "jaggies" as you approach the discontinuities instead of piecewise straight lines.)
The square wave is constructed in a very similar fashion to the sine wave, and we use the same approach by cycling through a pattern with a phase variable, and resetting once we exceed radians.
Input: Peak amplitude (A), Frequency (f) Output: Amplitude value (y) if phase < pi then y = A else y = -A phase = phase + ((2 * pi * f) / samplerate) if phase > (2 * pi) then phase = phase - (2 * pi)
As is evident there is no reliance on an external function, the square wave can be defined by simple arithmetic, since it essentially switches between two values per cycle. One can expand on this by introducing a new variable which controls the point in the cycle the initial value switches to its signed value; this waveform is known as a pulse wave. Pulse waves are similar in character to square waves but the ability to modulate the switching point offers greater sonic potential.
Sawtooth wave
editarThe sawtooth wave is more similar in sound to a square wave although it has harmonic decay and an appropriately "buzzy" timbre. It is constructed out of diagonal, sloping line segments and as such requires a line gradient equation in the algorithm. The mathematical form:
Where represents amplitude and is the phase. This can be incorporated into the algorithmic form as follows:
Input: Peak amplitude (A), Frequency (f) Output: Amplitude value (y) y = A - (A / pi * phase) phase = phase + ((2 * pi * f) / samplerate) if phase > (2 * pi) then phase = phase - (2 * pi)
Triangle wave
editarThe triangle wave shares many geometric similarities with the sawtooth wave, except it has two sloping line segments. The algebra is slightly more complex and programmers may wish to consider consolidating the line generation into a new function for ease of reading. Triangle waves contain only odd-integer harmonics of the fundamental, and have a far softer timbre than square or saw waves, which is nearer to that of a sine wave. The mathematical form of the two lines segments are:
For to radians:
For to radians:
The algorithm then, is similar to the previous examples but with the gradient equations incorporated into it. In the example algorithms presented here it is evident that a range of different waveshapes can be designed, but there is the realisation that the shapes can only be described as mathematical functions. Complex shapes may become very demanding due to the increased processing power for more complicated mathematical statements.
Input: Peak amplitude (A), Frequency (f) Output: Amplitude value (y) if phase < pi then y = -A + (2 * A / pi) * phase else y = 3A - (2 * A / pi) * phase phase = phase + ((2 * pi * f) / samplerate) if phase > (2 * pi) then phase = phase - (2 * pi)
Wavetables
editarThere may be a situation or a desire to escape the limitations or complexity of defining an oscillatory waveform using mathematical formulae or line segments. As mentioned before, this could be a concern for processing power, or simply the fact that it would be easier to specify the shape through an intuitive graphical interface. In cases like these, musicians and engineers may use wavetables to be their source oscillator. Wavetables are popular in digital synthesis applications because accessing a block of memory is computationally faster than calculating values using mathematical operations.
The wavetable is in essence an array of N values, with values 1 through to N representing one whole cycle of the oscillator. Each value represents an amplitude at a certain point in the cycle. Wavetables are often displayed graphically with the option for the user to draw in the waveshape he or she requires, and as such it represents a very powerful tool. There is also the possibility of loading a pre-recorded waveshape as well; but note that a wavetable oscillator is only a reference table for one cycle of a waveform; it is not the same as a sampler. The wavetable has associated with it a read pointer which cycles through the table at the required speed and outputs each amplitude value in sequence so as to recreate the waveform as a stream of digital values. When the pointer reaches the last value in the table array, it will reset to point one and begin a new cycle.
Using wavetables
editarThe size of the wavetable and the sampling rate of the system determine what the fundamental frequency of the wavetable oscillator will be. If we have a wavetable with 1024 individual values and a sampling rate of 44.1 kHz, it will take:
seconds to complete one cycle. As previously shown, frequency can be determined from , giving us a fundamental frequency of:
It therefore becomes apparent that, in order to change the frequency of our oscillator we must change either the size of the wavetable or the sampling rate of the system. There are some real problems with both approaches:
- Changing the wavetable size means switching to a different sized wavetable with the same, updated waveform. This would require dozens, hundreds, or even thousands of individual wavetables, one for each pitch, which is obviously totally inefficient and memory-consuming.
- Digital systems, especially mixers that combine several synthesized or recorded signals, are designed to work at a fixed sampling rate and to make sudden changes to it is once again inefficient and extremely hard to program.
- The sample rate required to play high frequencies with an acceptable level of precision becomes very high and puts high demand on the system.
One of the most practical and widely-used approaches to playing a wavetable oscillator at different frequencies is to change the size of the "steps" that the read pointer makes through the table. As with our previous example, our 1024-value wavetable had a fundamental frequency of 43.5 Hz when every point in the table was outputted. Now, if we stepped through the table every 5 values, we would have:
It follows from this a general formulae for calculating the required step size, S for a given frequency, f:
Where N is the size of the wavetable and is the sample rate. It is important to note that because the step size is being altered, the read pointer may not land exactly on the final table value N, and so it must "wrap around" in the same fashion as the functionally generated waveforms in the earlier section. This can be done by subtracting the size of the table from the current pointer value if it exceeds N; the algorithmic form of which can easily be gleaned from the examples above.
Frequency precision and interpolation
editarWe must consider that some frequency values may generate a step size that has a fractional part; that is, it is not an integer but a rational number. In this case we find that the read pointer will be trying to step to locations in the wavetable array that do not exist, since each member of the array has an integer-valued index. There may be a value at position 50, but what about position 50.5? If we desire to play a frequency that uses a fractional step size, we must consider ways to accommodate it:
- Truncation and rounding. By removing the fraction after the decimal point we reduce the step size to an integer—this is truncation. For instance, 1.3 becomes 1, and 4.98 becomes 4. Rounding is similar, but chooses the closest integer—3.49 becomes 3, and 8.67 becomes 9. For simple rounding, if the value after the decimal point is less than 5, we round down (truncate), otherwise we round up to the next integer. Rounding may be supported in the processor at no cost, or can be done by adding 0.5 to the original value and then truncating to an integer. For wavetable synthesis, the only difference between truncation and rounding is a constant 0.5 sample phase shift in the output. Since that is not detectable—and neither an improvement nor a detriment—a decision between truncation and rounding comes down to whichever is more convenient or quicker.
- Linear interpolation. This is the method of drawing a straight line between the two integer values around the step location and using the values at both points to generate an amplitude value that interpolates between them. This is a more computationally demanding process but introduces greater precision.
- Higher order interpolation. With linear interpolation considered first order interpolation (and truncation and rounding considered zero order interpolation) there are many higher-order forms that are commonly used—cubic Hermite, Lagrangian, and others. Just as linear interpolation requires two points for the calculation, higher orders require even more wavetable points to be used in the calculation, but produce a more accurate, lower distortion result. Sinc interpolation can be made arbitrarily close to perfect, at the expense of computation time.
By increasing the wavetable size, the precision of the above processes becomes greater and will result in a closer fit to the idealised, intended curve. Naturally, large wavetable sizes result in greater memory requirements. Some wavetable synthesizer hardware designs prefer table sizes that are powers of two (128, 256, 512, 1024, 2048, etc.), due to shortcuts that exploit the way in which digital memory is constructed (binary).