[linux-audio-dev] Subharmonic synthesizer, is there one?
Paul Winkler
pw_lists at slinkp.com
Wed Jun 18 13:10:01 UTC 2003
On Wed, Jun 18, 2003 at 06:52:05PM +0300, Kimmo Sundqvist wrote:
> Hello
>
> I'd like to know if there is a subharmonic synthesizer for linux. That is a
> plugin which adds low frequency content to sound not by boosting, but by
> synthesizing frequency components that are below what the signal otherwise
> contains. I'm thinking about something like Delaydots Phat Pro.
>
> If there is no such thing, is anyone thinking about developing one?
I have an old csound instrument i wrote that does this, in a similar way
to the old analog "octave" pedals.
there are more sophisicated techniques, i guess involving analysis of the signal
and generating sine waves based on the analysis... but mine can be
quite useful. I would love it if somebody made a LADSPA plugin out
of this algorithm.
my basic technique was this:
steep lowpass filter (reduces the number of zero crossings)
count upward-going zero crossings in the sine wave.
if count % N == 1, set the output to 1.
if count % N == 0, set the output to -1.
N determines the frequency of the subharmonic. If N == 2,
you get an octave down. If N == 4, you get two octaves down.
You now have a square wave with no dynamics, whose fundamental frequency
is a subharmonic of the input signal. It has no dynamics, meaning it's
likely to produce horrible noise if the input is low with a non-zero noise
floor :) We'll fix that later.
Note that, like its analog counterparts, this algorithm gives somewhat
odd results when the input signal is complex, e.g. a dissonant chord.
Next, apply a steep lowpass filter on the output unless you like the
square wave :)
Now apply gain balancing so that the output volume tracks the input volume.
I don't know how you'd do that efficiently in C, i just used a csound
opcode that's provided for this purpose.
The csound instrument is attached, if that's useful...
--
Paul Winkler
http://www.slinkp.com
Look! Up in the sky! It's OCTO BARON-MAN!
(random hero from isometric.spaceninja.com)
-------------- next part --------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;copyright 1998 Paul M. Winkler, zarmzarm at hotmail.com
;****++++
;**** Last modified: Mon May 1 04:23:19 2000
;****----
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
sr = 44100
kr = 44100
ksmps = 1
nchnls = 2
instr 1
; subharmonic synthesis
; version one -- downsampling
; Low ksmps (1 or 2) gives best-sounding results.
istraightgain = ampdb(p4) ; used as gains,
idown1gain = ampdb(p5) ; not amplitudes.
idown2gain = ampdb(p6) ; e.g. if arg is
; 6, the gain is 2.
; If arg. is -6,
; gain is 0.5.
; first generate some sound
kcount init 0
ktest init 0
; kamp expseg .001, 0.5, 1, p3 -1, 1, 0.5, .0001
kamp expseg .7, p3 -0.2 , 5, 0.2, 0.0005
kpitch init p7
a1, a2 diskin "FX/temp/bore-roar-mix-lopass.aiff", kpitch
; a1, a2 diskin "FX/temp/bore-mix.aiff", kpitch
; afilt1 tonex a1, 400, 4 ; heavy pre-filtering.
amix = (a1 + a2) * .5
afilt1 resonx amix, 150, 200, 2, 1 ; this could use some tweaking
k1 downsamp afilt1
; Now process the mix.
; This works by counting upward zero crossings in the
; waveform.
; The count is used to set the output to either 1 or -1
; so we get square waves at half (and a quarter) of
; the input frequency.
; adown1 is down an octave, adown2 is down 2 octaves.
kdetect trigger k1, 0, 0 ; notice only upward zero-crossings
if kdetect == 0 goto next1
kcount = kcount + 1
ktest = kcount % 4
next1:
if ktest != 1 goto next2
adown1 = 1
adown2 = 1
goto output
next2:
if ktest != 2 goto next3
adown1 = -1
adown2 = 1
goto output
next3:
if ktest !=3 goto next4
adown1 = 1
adown2 = -1
goto output
next4:
adown1 = -1
adown2 = -1
output:
; Choose your filter...
; adown1 tone adown1, kfreq * .04 ; takes out some high end, but
; still synth-sounding... looks like a triangle wave.
; adown1 rezzy adown1, 40, 30 ; pretty smooth but asymmetrical.
; adown1 tonex adown1, 40, 7 ; distorts with some inputs.
adown1 resonx adown1, 35, 60, 4 ; Very nice, near-sine output.
adown2 resonx adown2, 30, 50, 4
; adown1 butterbp adown1, 30, 10 ; output looks like a triangle wave!
adown1 dcblock adown1
adown2 dcblock adown2
adown1 balance adown1, afilt1 ; Restore dynamics.
adown2 balance adown2, afilt1 ; It's important to use filtered signal!
; adjust output levels
asubs = adown1*idown1gain + adown2*idown2gain
; remove excessive subs.
asubs atonex asubs, 22, 5
a1 = (a1*istraightgain + asubs) * kamp
a2 = (a2*istraightgain + asubs) * kamp
outs a1 + asubs, a2 +asubs
endin
instr 2 ; IGNORE THIS ONE.
; subharmonic synthesis
; version something-or-other... instr1 now is better.
; first generate some sound
k2 init 0
kx_count init 0
; test with sine wave input
; kfreq expseg 70, p3 / 2, 300, p3/2, 70
; kamp expseg 1, 1, 16000, p3 - 2, 16000, 1, 1
; a1 oscil kamp, kfreq, 1
kamp expseg .001, 0.5, 1, p3 -1, 1, 0.5, .0001
kpitch expseg 2, p3, 0.5
a1 diskin "beats+loops/longroove.aiff", kpitch
; a1filt tone a1, 80 ; doesn't seem to help much... maybe with complex pitches
; Also, low ksmps (1 or 2) gives best-sounding results.
k1 downsamp a1
kdetect trigger k1, 0, 0 ; notices only upward zero-crossings
if kdetect == 0 kgoto skip
kx_count = kx_count + 1 ; kdetect must be 1
skip:
; I'll keep this next line just as a nice example of using || or && ...
; if ((kx_count % 4) == 1) || ((kx_count % 4) == 2) kgoto positive
if ((kx_count % 2) == 1) kgoto positive
a2 = -1 ; if we're here, count is odd, so make output negative
kgoto output
positive:
a2 = 1
output:
;a2 upsamp k2 ; 'interp' doesn't seem to help much here.
; a2 = a2 * 16000
; a2 tone a2, kfreq * .04 ; take out some high end, but
; still synth-sounding... looks like a triangle wave.
; a2 rezzy a2, 40, 30 ; pretty smooth but asymmetrical.
; a2 tonex a2, 40, 7 ; distorts with some inputs.
a2 resonx a2, 35, 100 ; VERY nice, near-sine output.
; a2 butterbp a2, 30, 10 ; output looks like a triangle wave!
a2 balance a2, a1, 2 ; balance a2 to a1 to restore dynamics.
outs a1, a2
endin
;;; I N S T R U M E N T 3
;;; Dynamic Range Expander???
;;; Keywords: expansion
instr 3
;; Description of Arguments:
kpitch expseg 2, p3, 0.5
a1 diskin "beats+loops/longroove.aiff", kpitch
iscale = 1 / 32768
a1 = a1 * iscale ; normalize
a2 pow a1, 4 ; raise to power
a2 tone a2, 5000 ; does this help?
a1 balance a1, a2 ; do the dynamics
outs a1 * 32768, a2 * 32768 ; re-normalize
endin
-------------- next part --------------
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;copyright 1998 Paul M. Winkler, zarmzarm at hotmail.com
;****++++
;**** Last modified: Mon May 1 04:20:16 2000
;****----
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
f1 0 32768 10 1 ; sine
; gains:
;1 at dur straight down1 down2 pitch
; i1 0 16.88 -2 -6 -60
i1 0.1 4.4 0 4 10 0.6
; i1 0 . 3 7 13 1
i1 0 . 0 4 9 1.05
f0 6
More information about the Linux-audio-dev
mailing list