今まで、自作のSSB変復調プログラムはIF=12kHzで固定でした。これは、サンプリング周波数のちょうど1/4になっていて、ベースバンドとの周波数変換のときの局発を実現するのに真面目に正弦波をつくる必要がなく、実質乗算も行なわなくて良いので実装上も処理速度上もメリットがあったからです(ソフトウェアで行なうメリゴ方式みたいになります)。
しかしFT-747は最小ステップが25Hzのため、局発が動かせないと、正確には相手にゼロイン出来ないですし、そもそも12kHz以外のIFに対応できた方が組み合わせるハードウェアの自由度もあがります。そこで、IF周波数をある程度自由に選べてかつ運用時にも微調整可能なようにプログラムを作り換えています。そのためには、ちゃんとした正弦波をIQのペアで出力するような関数が必要になります。週末の深夜にオリンピックの中継を見ながら、やはり昔つくったプログラムをちょこちょこ直して組み込んで、朝方にはなんとか動いて気分良く寝たのですが、夕方3.5MHzをワッチしていると最初はいいのですが、数十分くらいするとだんだん出力が大きくなってきて、しまいにはサチってしまうことに気づきました。変更したのは局発のところだけなので、きっと正弦波の振幅が誤差の蓄積で大きくなっているのだろうなと思って調べてみたら、やはりそのようです。試しに関数内部で使っている変数の精度をfloatからdoubleにしたところ、1時間くらい動かしていても問題はなさそうになりました。本質的には、誤差がある程度出てきたら振幅をリセットするとかしないといけない気がするのですが...
ちなみにそこの部分は以下のようなコードになっています。世の中、どんなやりかたで処理しているのでしょうかね。
/*
* complex sine wave generator
*/
#ifndef SINGEN_H
#define SINGEN_H
#include <math.h>
class SinGen {
private:
int sr;
float f;
double a, b, c, d;
double angle, wd;
public:
SinGen(float freq, int sample_rate) {
sr = sample_rate;
f = freq;
a = 1.0;
b = 0.0;
angle = 0.0;
wd = 2 * PI * f / sr;
c = cos(wd);
d = sin(wd);
}
void set_freq(float freq) {
f = freq;
wd = 2 * PI * f / sr;
c = cos(wd);
d = sin(wd);
}
void get_sample_n(float *i, float *q, int n) {
double a_next, b_next;
for (int j = 0; j < n; j++) {
a_next = a * c - b * d;
b_next = a * d + b * c;
i[j] = a_next;
q[j] = b_next;
a = a_next;
b = b_next;
//angle += wd;
}
}
};
#endif