Background Theory
FOF (formant wave function) synthesis is a synthesis technique that involves modelling sounds based on the characteristics of their frequency spectrums. One starts by identifying characteristics of the spectrum such as the center frequencies of peaks in the spectrum, the amplitudes of those peaks and the bandwidths of the peaks at some measurable point (such as 6 dB down from the actual peak). Using these measurements, one can then synthesize a sound based on them by either using a filterbank based approach or working with a timedomain function representation.
In the paper TimeDomain FormantWaveFunction Synthesis by Xavier Rodet, one particular timedomain representative function is proposed:
$$s(k)=\begin{cases}
\frac{1}{2}(1\cos(\beta k))e^{\alpha k}\sin(\omega_c k+\phi)\qquad\text{for }0\leq k\leq k_1\\
e^{\alpha k}\sin(\omega_c k+\phi)\,\,\qquad\qquad\qquad\qquad\text{for }k\geq k_1.
\end{cases}$$
where \(\beta\) controls the attack time of the function which in turn controls the skirt width of the related formant peak in the frequency domain, \(\alpha=\pi BW\) controls the bandwidth of the formant and \(\omega_c\) is the center frequency of the formant.
This equation, however, only creates one formant peak in the frequency domain. Thus, in order to generate a rich frequency spectrum, it is necessary to calculate more than one of these formant waves in parallel and sum the output to generate a rich formant spectrum. Finally, the rate at which these formant wave functions are repeated determines the fundamental frequency of the harmonic tone that posesses the frequency spectrum generated by the formant waves (as pictured below).
Project Description
I decided to implement the timedomain version of formant wave function synthesis in the Faust (Functional AUdio STream) programming language which provides a good environment for DSP process coding. In Faust, every programming object is represented as a signal, thus numbers are represented by constant signals and logical statements must be implemented in terms of signals as well. This can make certain aspects of programming in Faust somewhat challenging to think about. While it was not very difficult to implement \(e^{\alpha k}\sin(\omega_c k+\phi)\), it was challenging to implement the logic of the case statement controlling the attack of the function. It was necessary to use a counter and a gate to allow one of the two parts of the above equation to pass through to the output depending on where the counter was at.
Another difficult aspect of the project was figuring out how to overlap and add the repeating formant wave functions. Since the length of the waves is dependent on the bandwidth of the particular formant and not on the rate of repetition which is controlled by the period of the fundamental frequency, it is nearly always the case that the formant waves will overlap each other. In order to accomplish that in Faust, I developed a system using a counter where I start calculating the values of one cycle of the formant wave as one signal which becomes zeros after a certain point (in particular when the \(t_{60}\) decay time has been reached). I then feed that signal through a recursive delay and add element that delays the stream by the number of samples in the fundamental period. Thus, the formant wave function values are created once and then cycle continuously through a delay line after that point.
The last part of the implmentation involved creating the gui controls, a play button and then specifying the formant values for different vowel sounds. I chose to use a bass singer's formant vowel values as in the future I hope to synthesize eastern chant music such as Tibetan chant and Mongolian throat singing. Also, this is the vocal range that is typically most difficult to synthesize. Finally, with Faust it is necessary to compile your Faust code in one of a variety of different export formats such as a VST, or a standalone Jack app in order to play the app. I was not sucessful in creating a ChucK ChuGin with the faust2ck export command but I was able to create a web audio html page using the faust2webaudioasm export command (see below link).
Project contents
The Faust code for my formant wave function synthesizer is located here.
The web audio implementation of the synthesizer is located here.
References
