I have long avoided FM (Frequency Modulation) synthesis in my own musical practice as I never felt connected with the results I was able to get myself. However, I recently had the great pleasure to attend a talk about the 50th anniversary of FM synthesis, given by its creator, John Chowning, and I was very inspired to explore FM once again. In so doing, I came across the Yamaha reface DX synthesizer and became fascinated with reproducing its feedback system to morph an operator’s output from a Sine to either Saw or Square waveform.
Now, I do not own a reface DX, so most of my research into it was through looking at manuals and watching video demonstrations on YouTube to try to get an idea of how it might be done. I knew from going through literature on FM and PM (Phase Modulation) that using PM with feedback could get an operator’s signal to move from a Sine to Sawtooth wave, depending upon the amount of feedback. I was quickly able to setup a PM instrument in Csound and test this out and it sounded much like what I had heard for the reface DX.
;; feedback PM - feedback moves towards saw instr PMFBSaw ifreq = p4 iamp = p5 kfb = linseg(0, p3 * .5, 0.3, p3 * .5, 0) aphs = phasor(ifreq) ; init for feedback acar init 0 acar = tablei(aphs+(acar*kfb), 1, 1, 0, 1) acar *= linen:a(1, 0.1, p3, 0.1) * iamp outc(acar, acar) endin
In the code above, one can see that the acar
output from tablei
is also used as input into the opcode. The code above runs in a single-sample context (in Csound parlance, with ksmps=1
).
Now, the part I could not find anywhere in literature or discussion online was how to use operator feedback to morph from Sine to Square. (This is done by using 0 to -127 range for feedback on the reface DX.) After a couple days of research and exploration, I stumbled upon a calculation that sounded to my ears very much like what I had heard on the reface DX videos.
The code below shows the entire instrument:
;; feedback PM - feedback moves towards square instr PMFBSquare ifreq = p4 iamp = p5 kfb = linseg(0, p3 * .5, 0.3, p3 * .5, 0) aphs = phasor(ifreq) ; init for feedback acar init 0 acar = tablei(aphs+(acar*acar*kfb), 1, 1, 0, 1) acar *= linen:a(1, 0.1, p3, 0.1) * iamp outc(acar, acar) endin
This instrument is virtually the same as the first instrument with the exception of one additional calculation: the multiplication of the acar
feedback by itself. (This is seen in the acar*acar
calculation.) Adding this one additional multiplication made the signal move from Sine to Square.
I posted this to the Csound User list and Iain McCurdy gave great feedback that the waveform could be morphed between Saw and Square by interpolating between acar and 1. This made a lot of sense as when one of the acar
‘s becomes 1, it reduces back down to the normal feedback addition to produce a Saw sound. After some further emails, I did some experiments to use a cosine-based mapping for the interpolation that resulted in a nice transition.
;; feedback PM - feedback moves from square to saw ;; Based on Iain McCurdy's comments on Csound User List instr PMFBSquareSaw ifreq = p4 iamp = p5 kfb = 0.25 ;;kfb = linseg(0, p3 * .5, 0.5, p3 * .5, 0) kwaveshape = linseg(0, p3 * .5, 1, p3 * .5, 0) ;; range 0-1 for saw->square kwaveshape *= kwaveshape ;; adjust curve kwaveshape = $M_PI * (kwaveshape + 1) ;; adjust from PI->2PI kwaveshape = (cos(kwaveshape) * 0.5) + 0.5 ;; adjust to 0-1 aphs = phasor(ifreq) ; init for feedback acar init 0 acar = tablei(aphs+(ntrpol(acar, a(1), kwaveshape)*acar*kfb), 1, 1, 0, 1) acar *= linen:a(1, 0.1, p3, 0.1) * iamp outc(acar, acar) endin
I do not know if these calculations are what are used in the reface DX, but regardless, the sine->square sounded good to my ear and I felt it was usable for the kind of sound work I was interested in doing. For now, I have posted the Csound CSD project file here. The audio example at the top of this post is an MP3 version of the output rendered from this project.
Cheers!
Steven
Looking at some YouTube videos (https://youtu.be/r3EQQ-XF3jA?t=650), Reface seem to use absolute value for negative feedback, not squaring. With a trivial experiment, the ‘shark fins’ come out a lot more triangular with the abs function than with squaring, which preserves a bit of the curvature in the shark fins.
In fact, a bit more searching on the net finds that they’ve even patented this relative triviality, as a circuit. See fig 1 and 3(c) in
Takeuchi https://patents.google.com/patent/US6410838
One thing that they seem to have missed is that if you use actual negative feedback, i.e. negative beta in the patent’s notation, (not the virtualized kind they offers as a knob on the Reface), you get trapezoids (https://imgur.com/U6gfNun), not triangular shark fins, with the absolute value function. Which sound more like actual squares to me. (With the ‘normal’ PM un-phaseshaped feedback, negative feedback/beta just reverses the phase, but with absolute value, or any odd function thrown in as a phaseshaper, you get different shapes for negative beta than for positive; the odd function ‘selects’ a different part of the wave when the beta sign is changed.)
One thing I’ve not figured out is what smoothing filter the Reface uses. It’s a lot more aggressive than the simple averaging used on the DX7 (Tomisawa patent US4249447A, fig 7 & 8). You can see in the above YouTube video that one push the feedback hard on the Reface and not get noise, which you still get with enough oscillation through the simple averaging filter. The Tomisawa patent was somewhat mistaken/misleading that that’s just ‘numerical instability’. With big enough feedback, there’s eventually large frequency oscillations due to the IIR nature of the feedback process that will overcome any filter. I’ve tried a weighted averaging filter (biquad acar, 3, 2, 1, 6, 0, 0) which is a bit of an improvement over the DX7 style one, but not quite Reface level.
Excellent information, thanks for sharing! It’s been a while since I thought about all this but your comments are inspiring me to investigate further. Appreciate it!