フーリエ変換を逆に使ったサイン波発振器
低周波でサイン波の発振器というと、古い人は真っ先にウィーンブリッジを思い出します(図1)。

図1の回路は ω=1/(RC) のところで 1 端子も 2 端子もは入力電圧の 1/3 で位相は同じになり、そのほかの周波数では 2 の信号は低くなります。 すなわち周波数選択になっているのです。
ですから、2 に出てきた信号を3倍(より少し大きく)して入力に戻してやれば、かなり良いサイン波の発振器になります。
ところが、正確に3倍というのはできない相談ですので、少し大きくするわけですが、そうすると振幅はどんどん大きくなって、増幅器が飽和になったところで発散が止ります。 飽和になるということは、とりもなおさず歪みを持込んでいる、ということなのです。 立上がり時の時間が遅いも気になります。
これを逃れるため、出力の振幅を検出して、発振周波数よりもずっと低いカットオフ周波数を持ったフィルタにかけ、ゲインをコントロールする回路に戻す、ということもやるのですが、それでも完全に問題を回避しているわけではありません。
(昔は、その回路を一挙にやるのに、タングステンランプの抵抗が、温度と正の相関を持ち、かつ熱緩和時間を持っていることを利用したものです)

話は全く違いますが、 Duty 50% のパルスは、フーリエ変換すると基本波の3倍の周波数の成分が 1/3、5倍の成分が 1/5、7倍の成分が 1/7 、、、、というように展開できることはよく知られたことです。
右のスペクトル図はその様子を1目盛 10dB にして見たところです。

ためしに、基本波、3倍波、5倍波、7倍波までを加算してみると右の図のようになります。 だいぶ方形波に近くなっています。
逆転の発想をして、フーリエ展開するのではなく、矩形波から、3倍周波数の矩形波を1/3だけ差引くとどうなるでしょうか。
元のパルスの3倍の成分と、3倍パルスの基本波成分が打消し合って無くなります。 また9倍の成分も無くなります。
次の図を見てください。
ちょっとでこぼこしていますが、矩形波よりはサインカーブに近づいた波が描かれています。
ここまで作ればあとは5倍以上の調波成分をフィルタで除去してやれば、きれいなサイン波になります。 5倍も離れていると分離も簡単です。
こうすれば、ゲイン調整に手こずることもありません。
私が考えたものではありませんが、この逆転の発想には芸術性があると思います。

では具体的にはどうすればいいでしょうか。
まず目的周波数の3倍の周波数を持った 50% Duty のパルスを作ります。
それを XOR 1つと FF 2つを使って3分周します。 このときうまく位相をを合わせておきます。
抵抗のマトリックスで適度に電圧を合成します。
そのあと 12dB/Oct 程度の Low Pass Filter を通せばできあがりです。
ちょっと気を付けなければならないところは、3分周した信号がゲートディレイ分だけやや時間遅れを持っていますので、原信号の方をそれに合わせて遅らせるといいでしょう。
FM ステレオ送信機では 38kHz の副搬送波に正確に位相があった 19kHz パイロット信号がいりますが、それを作ってみました。 (実際の回路では 38kHz をこのような回路で作り、その途中から抜出した信号を元に 19kHz の原信号と 1/3 信号を作っています。)
40xx シリーズの CMOS を使っていますので 15k と 20p というかなり大きな delay を入れています。
フィルタは 18dB/oct の、素子感度の低い(誤差が大きくても良いという意味)バタワースフィルタを設計しました。
電圧加算回路は本来ならオペアンプの反転入力の仮想グラウンドを使うべきですが、別の事情がありました。 あしからず。

[余談] フーリエ変換
計算機で波形をフーリエ変換するととても面白いことがわかります。
バタフライ演算を使って高速にやりますとリアルタイムに表示できますから、刻々変化する入力の周波数分布を目で見ることができるようになります。
正確には、波形ではなく、サンプリングを行って取り入れた一連の値ですから、離散値で、しかも量子化された値を取り扱うわけです。 これを DFT (離散フーリエ変換)といいます。
信号中の周波数成分と、サンプリング周期とが干渉を始めるとエリアシングが起きて余分な成分が出ますからこれを排除するサンプリング周波数を選択しなければなりません。 また、ある瞬間からサンプリングを始めて、ある瞬間で止めますと、その窓自体のフーリエ変換も混じってしまいますから出力がおかしな波形になります。 これを緩和する窓の形も選択する必要が出てきたりします。
高速に行うためには VB や VC++ で書いていてはいけないので、最低限一番内側の演算ループはアセンブラで書く、といった工夫も必要になります。
1 'Fast Fourier Transformation. T Fujiwara 1992 9 ' -------------- Define dimension ------------- 10 N=1024 : DIM XR(N),XI(N),CS(N),SS(N),PTBL(N) 20 OPEN "ram.dat" FOR INPUT AS #1 : OPEN "fft2uni.dat" FOR OUTPUT AS #2 30 FOR I=0 TO N-1 : INPUT #1, XR(I) : NEXT I 34 ' -------------- Hamming Window Weighting ----- 35 'FOR I=0 TO N-1 : XR(I)=XR(I)*(1.08-.92*COS(6.28318*I/(N-1))) : NEXT I 36 ' -------------- Hanning Window Weighting ----- 37 'FOR I=0 TO N-1 : XR(I)=XR(I)*(1-COS(6.28318*I/(N-1))) : NEXT I 49 ' -------------- Initialization --------------- 50 FOR R=1 TO 20 : IF 2^R=N THEN 60 ELSE NEXT R 55 PRINT "Error: Plot count is not equal to 2^R." : END 60 IR=1 : J2=N : DEG=2*3.14159/N 62 FOR I=0 TO N-1 : ARG=DEG*I : CS(I)=COS(ARG) : SS(I)=IR*SIN(ARG) : NEXT I 64 FOR I=0 TO N-1 : BIT=0 : B1=I 65 FOR II=1 TO R : B2=INT(B1/2) : BIT=BIT*2+B1-2*B2 : B1=B2 : NEXT II 66 PTBL(I)=BIT : NEXT I 70 K=0 : L1=R-1 79 ' -------------- FFT Start -------------------- 80 FOR L=1 TO R : L12=2^L1 : J2=J2/2 100 FOR I=1 TO J2 120 BIT=PTBL(INT(K/L12)) 140 C=CS(BIT) : S=SS(BIT) : K1=K+J2 160 A=XR(K1)*C+XI(K1)*S : B=XI(K1)*C-XR(K1)*S 180 XR(K1)=XR(K)-A : XI(K1)=XI(K)-B : XR(K)=XR(K)+A : XI(K)=XI(K)+B : K=K+1 210 NEXT I 220 K=K+J2 230 IF K<N THEN 100 240 K=0 : L1=L1-1 250 NEXT L 260 ' ------------- Final Reordering ------------ 270 FOR KK=0 TO N-1 290 BIT=PTBL(KK) 300 IF BIT>KK THEN SWAP XR(KK),XR(BIT) : SWAP XI(KK),XI(BIT) 320 NEXT KK 324 BEEP '--------- Output ---------------------- 325 X0=SQR(XR(0)*XR(0)+XI(0)*XI(0))/4 330 FOR I=0 TO N/2 : ABV=SQR(XR(I)*XR(I)+XI(I)*XI(I)):DB=8.68589*LOG(ABV/X0) 340 PRINT USING "#####";I;:PRINT USING "#######.##";XR(I),XI(I),ABV,DB 345 PRINT #2, USING "#####";I;:PRINT #2, USING "#######.##";XR(I),XI(I),ABV,DB 350 NEXT I 360 END
