手習ひデジタル信号処理(102) Scilab、シンボル(疑似乱数系列)生成用関数のおさらい

Joseph Halfmoon

Scilabのcomm_tbx(コミュニケーション・ツール・ボックス)にはいつもお世話になっておりますが、諸般の問題もあり「代替自前関数」を作ることを含めて何をどこまで使えるのか、勉強をかねておさらいしておる最中でございます。今回はテスト用にシーケンス(疑似乱数)を生成する関数についてです。急がば回れ、ホントか?

※「手習ひデジタル信号処理」投稿順 Indexはこちら

※Windows11上で、Scilab6.1.1およびScilab上のツールボックス Scilab Communication Toolbox 0.3.1(以下comm_tbx)を使用させていただいとります。

PN符号の代表選手といえば「M系列」だが

PN(Pseudo Noise Sequence)符号は、テスト・シーケンスに用いられることも多いですが、モダンな通信では通信の根幹を担うお役目を果たすことも多いみたいです。知らんけど。

PN符合の代表選手といえばM系列(Maximum-Length Linear Feedback Shift Register Sequence)です。そしてM系列といえば、そのお名前に含まれておるとおりLFSR(Linear Feedback Shift Register)、ハードでもソフトでも構わんけど、を使って生成するのが定番かと。

さてcomm_tbxにおいても、LFSRを用いて擬人乱数系列を生成することは以下の2つの関数を使って可能です。

    • lfsr_init
    • lfsr_process

なお、comm_tbxにおいては Linear Feedback 「State」 Registerと唱えています。わたしゃこの歳になるまでShiftと覚えてきましたが。何かStateに意味が込められているのか?わからんぞなもし。

ともかく以下のようにしてLFSRを定義可能です。

lfsr = lfsr_init(deg)

degには0から15までの数を与えて多項式の次数を決定できるようです。なお、

The LFSR register size will be 1 + degree

ということなので、degに最大の15を与えたとき、多項式の次数は16ということになる筈。

ただし、いろいろ調べたのだけれど腑に落ちない部分があり。通常、LFSRの場合、どのビットからフィードバックを取り出すのかチョイスがありえる(ダメな場所から取り出すと「最長の」M系列にならなかったりするケド)ので、「タップ位置」指定がありそうなもんなのですが、見当たりませぬ。良きように計らってくれているみたい。。。ホントか、何も書いてないんだが。

実際に「5次」のLFSRで疑似乱数列を生成してみたのが以下に。

lfsr4 = lfsr_init(4);
[x4, lfsr4] = lfsr_process(lfsr4, n);
plot_binary(x4);

上記で生成したx4の一部をplot_binaryでプロットしてみました。plot_binary_x4

上をみると、周期31の系列になっているみたい。5次の「最長」になっているみたいね。

prbs()関数とts01()関数

上記のように、イマイチよくわからんLFSR関係関数にくらべて、以下の関数は明快です。comm_tbxを使ってテストシーケンスを生成するのであれば、以下を使う方が明快?

    • prbs 疑似乱数系列の生成
    • ts01 周期的シーケンス0101…の生成

なお、prbs関数は、LFSRは使っておらず、Scilab本体が常備しているgrand関数(各種の分布に基づく乱数を生成できる)を呼び出しているみたいです。grand関数の設定によっては乱数の素性を変更することも可能なんでないかと。やってないケド。

prbs()関数での疑似乱数系列の生成例が以下に。nはバイナリシーケンスのビット長です。

n=1000;
x0=prbs(n);
plot_binary(x0);

上記で生成した1000ビット長のバイナリシーケンスの一部をプロットしてみたものが以下に。plot_binary_x0

念のため、0101とお決まりのパターンを繰り返す ts01()関数も使ってみます。

x1=ts01(n);
plot_binary(x1);

プロット結果が以下に。plot_binary_x1

 

生成した疑似乱数の「数列」を「信号」っぽくするまで

上記で01のバイナリ数列は生成できましたが、まだまだ数列(列ベクトル)で信号っぽくありません。以下のcomm_tbx内の3つの関数を使うと「それらしい」信号にすることが可能です。

    • nrz、NRZ信号へパルスシェーピング
    • ma、移動平均
    • awgn、Additive White Gaussian Noise

まずは、nrz関数で、0とか1とか1点の数値だったものを、シンボル長(当然その裏にはサンプリングレートあり)の長さの「長い」数列にします。しかしこのままでは0と1が一瞬で入れ替わるので、実信号らしく0から1へ1から0へゆるゆると遷移させるためにma関数で加工。最後にホワイトノイズを添加するととても実信号っぽくなると。

まずはNRZ化っす。

nSYM=100;
x0nrz=nrz(x0, nSYM);
plot_binary(x0nrz);

結果のプロットが以下に。1つの値がnSYM分の長さの「信号」になっとります。plot_binary_x0nrz

続いて ma かけます。maかけるウインドウの幅によって立ち上がり、立下りの勾配は変化します。ウインドウの最大幅がシンボル長を超えてしまうと前後のシンボルが「混ざって」しまうので注意。

nMA=51;
x0ma=ma(x0nrz, nMA);
plot_binary(x0ma);

plot_binary()はバイナリといいつつも、上記のx0maの中間値が含まれるデータもプロットしてくれます。こんな感じ。ただこれ以上〇が重なると五月蠅いデス。バイナリでないデータに適用するのは計画的に?plot_binary_x0ma

さて、最後に雑音載せてみます。

xN01 = awgn(x0ma, 0.1);
plot(xN01);

今度のプロットは普通にplot()

plot_xN01

なんだかそれらしくなったんでないかい。

手習ひデジタル信号処理(101) Scilab、plot_eyeの代替自前関数、五月蠅い へ戻る

手習ひデジタル信号処理(103) Scilab、comm_tbx、NRZはあるNRZIはない へ進む