SDR

ワンセグの仕様

日本のワンセグ放送の仕様。自分用のメモ。

  • セグメント帯域幅(Bws) = 6000/14 = 428.571..kHz
  • キャリア周波数間の間隔(Cs) = Bws/432 = 0.992…kHz
  • キャリア数 = 432 (Data 384, SP 36, TMCC 4, AC1 8の合計)
  • キャリアの変調方式: QPSK
  • 1フレームのシンボル数: 204
  • 実効シンボル長: 1008us
  • ガードインターバル: 126us (1/8)
  • シンボル長: 1134us (1/8)
  • フレーム長: 231.336ms (1/8) = 1134us * 204
  • Inner code: Convolutional code 2/3
  • Outer code: RS(204,188)

ワンセグのデータレート QPSK, Convolutional Code 2/3, Mode 3, フレーム内のTSP 64, ガードインターバル 1/8, 416.08kbps (= 64(# of TSPs) * 188 (bytes/TSP) * 8 (bits/byte) * 1/frame length)

FPGA FM受信機設計資料をGitHubに上げました

2年ほど前に実験していた、FPGAを使用したFM受信機の設計資料をGitHubに上げました。 SDR受信機とはどのように設計されるものなのか。実際のアナログ/デジタル回路含めて全体を理解したい、 という好奇心を満たすために始めたプロジェクトで、当初の目的はそれなりに達成できたと思います。

あまり詳しくドキュメントを書いていないので、実際に使用するのは難しいかと思いますが、 FM用のバンドパスフィルタ基板、ADC基板の回路図、ガーバー、BOMも含まれています。

ワンセグ生データをOFDM復調(4)

前回、パイロット信号が正しく取り出せないのはキャリア周波数オフセット(Carrier Frequency Offset, CFO)が原因ではないかと書きました。それ以後、 OFDM Baseband Receiver Design for Wireless Communicationsを参考に、 CFO, SCO(Sampling Clock Offset)を除去するためのPLLを実装してみたりもしましたが、どうにも思うとおりにはなりませんでした。

考え直してさらに調査した結果、DFTのデータを取り出すウィンドウが間違っていたということが判明しました。

これまでは、相関値が最大になる場所をDFTウィンドウの先頭としていましたが、 それだとCyclie Prefix(ガードインターバル)の先頭からOFDMシンボルを切り出してしまうことになります。 この領域は、信号に遅延波があるときに、他のシンボルからの干渉を避けるためのものなので、 本来DFTに使用するのは望ましくありません。

遅延波が全く無かったとしても、上記の文献の式(5.11)の通り、周波数領域の信号Zkは、送信信号Xk、チャンネル応答Hkに対して次のようになります。

“Symbol Timing Offset”

ここに、TdはDFTウィンドウがCyclic Prefixに入り込んでいる時間です。

これまでのTs=1, Td=128, N=1024で計算してみると、e^{-j2pi128k/1024}= e^{-jpi*k/4}となります。つまり、隣り合ったサブキャリアの間で-pi/4だけ位相が本来の信号からずれていくことになります。

これまでの結果を振り返ってみると、サブキャリア12本ごとにpi位相がずれている様子でした。 計算すると、-pi/4*12=-3pi=pi (modulo 2pi)ですので、ちょうどこの結果と一致します。

それで、CPの開始からDFTウィンドウを設定するのではなく、CPの終わりの少し前からDFTウィンドウを設定することで、ほぼ所望の結果が得られるようになりました。

“Symbols Before Channel Estimation”

上はチャンネル補正をする前の、生のDFT後のデータです。 これだけバラけていると、QPSKであることも疑わしい感じですね。

“SP”

SP自体は上のように、まだキャリアごとに、わずかに回転しています。このSPによって、残りのチャンネルは線形補間で推定します。推定結果でデータを補正すると、次になりました。

“Symbols After Channel Estimation”

このように、CFO, SCOのためのPLLは一切使用せずに、相関値を算出したときのガンマの値による回転と、整数倍のチャンネル周波数補正、SPによるチャンネル補正のみで、QPSKの信号がほぼ復元できました。

流石に、この程度のコンステレーションでは64QAMは無理ですが、4象限しか区別しないQPSK程度であれば、これでも十分に思われます。また、TMCC, ACに相当するI軸上の点も見つけられます。

ここまで来れば、TMCCのデコードをはじめ、ワンセグのデコード処理も規格書に則って進めれば完成まで持っていけそうな気がしてきました。

ワンセグ生データをOFDM復調(3)

前回までで、ワンセグの生データからのOFDMシンボル切り出し、パイロット信号を見つけるところまで実装しました。ところが、パイロット信号からチャンネル補正ができそうにない、というところで止まってしまいました。もう少し調査したところ、原因が分かってきました。 自分の理解の範囲でのまとめです。

OFDM Baseband Receiver Design for Wireless CommunicationsのChanter 5. Synchronizationの式(5.6)は次のようになっています。

“Z”

これは、キャリア周波数のオフセットが、FFTした結果に及ぼす影響を記述した式です。 左辺Z_{i, k}は、(時系列に並んだ)i番目のシンボルの、k番目のサブキャリアの(周波数領域の)値を示しています。また、ε_I, ε_fがそれぞれキャリア周波数オフセットの整数部、小数部です。 Hはそれぞれのサブキャリアに対応するチャンネルの周波数応答です。

ごちゃごちゃしていますが、とにかく、ε_I, ε_fが0でなければ、Z = X Hとは記述できず、他のキャリア周波数の影響を受けてしまうことを示しています。

右辺の第一項を見てみると、大きく4つの掛け算になっていますが、最後の2つのe^{…}の部分は純粋な回転です。 これまでの実装で、小数部のキャリア周波数補正はできていると思われます。 そのため、ε_fはほとんど0と考えます。

したがって、振幅だけを見るならば、受信したk番目のサブキャリアのFFT結果は、送信側のk-ε_I番目のサブキャリアの値に、チャンネル応答を掛けたものになっています(sinの項はε_f->0で1になるため)。 ですから、パイロット信号も含めてXの振幅は既知なので、振幅について積算することで、 ε_Iを求めることができたのでした。

問題は3番目のeの項による回転です。 この式を見るとε_Iが0でなければ、時間と共に盛大に回転します。 (2019/2/20追記:これ自体は正しいですが、kには依存していませんので、 Scattered Pilotがキャリアによって回転量が異なることの説明にはなりません。 それより(5.6)右辺第2項が寄与しているのかも知れません)

これの逆数を求めて回転を補正することもできるかも知れませんが、 上記の式では右辺には第2項以降も存在します。 そのため、基本的にはε_I, ε_fを0に収束させるような制御をしたほうが良さそうです。

上記の本の5.2.3節にも、周波数領域の推定アルゴリズムには限度があるので、同期エラーはその限界内に来ていることを確かめないといけない、といった記述があります。そのためには、時間領域で補正することができる、と書かれています。

時間領域での補正方法は下記の図のようになります(Figure 5.13より)。

“CFO compensation PLL”

求められたε_I, ε_fをloop filterを通してNCOに与え、その周波数でサンプリングしたデータを回転させる、というものです。 これまでの実装ではε_fのみしか考慮していませんでしたが、ε_Iも考慮する必要がある、ということです。

以上を参考にして、PLLでキャリア周波数オフセットを0に制御できるか試してみたいと思います。

ワンセグ生データをOFDM復調(2)

前回までで、ワンセグの生データからのOFDMシンボル切り出しあたりまで実装しました。今回はそれ以降の処理についてです。

前提知識

ワンセグも含めて、地上波デジタル放送は、ARIBにて規格書が配布されています。

標準規格(放送分野)一覧表のSTD-B31「地上デジタルテレビジョン放送の伝送方式」から入手可能です。私は会員でもないので、英語版を入手しています。

FFT以降の処理

前回の部分も少し修正して[11]については、次のようにしました。

“FFT”

重要なのはfftshiftを実施していることです。データ取得時のサンプリング周波数は、放送帯域の中心に設定しているので、(キャリア周波数オフセットが0であれば)fftshift後の配列中央の値が、放送帯域の中心キャリアになるはずです。

また、後でキャリア周波数の整数倍の補正をするために、周波数シフトをする必要があります。そのためのシフト量を保持するために、F_leftという変数を定義しています。シフト量が0であった場合に、FFT結果Fのうちキャリア番号0に対応する値を、初期値として設定しています。

“PRBSとTMCCの定義”

パイロット信号を検出するためにPRBSが必要になるので、その定義と、TMCC、ACという特別なパイロット信号のキャリア番号を定義しています。PRBSの最初の値がキャリア0に、次の値がキャリア1に、…というように、432本のキャリアにそれぞれ0, 1のいずれかが対応します。SP(Scattered Pilot)信号は、このキャリア周波数毎の0, 1の値がBPSKにより、IQ空間上のそれぞれ(+4/3, 0), (-4/3, 0)にマップされます。これを上記では配列Wiで定義しています。

“TMCCとAC推定”

上記は、TMCCとACの場所を推定するための関数です。G2では、引数mで指定された分だけ、キャリア周波数を移動した場所をTMCC, ACとみなして、絶対値の積算をしています。

Gs = [G2(i, Wi) for i in range(-20, 20)]

にて、キャリア周波数を-20から20まで整数倍シフトして、G2の積算値が最大になる場所を求めます。最大値が得られるインデックスでF_leftを調整しています。これでキャリア番号0から431までの場所が求まったことになるはずです。上記のプロット結果は省略します。

“SP推定”

次はSPの推定です。SP信号は12キャリアに1本あります。OFDMシンボル毎に場所が3キャリアずつ移動します。つまり、OFDMシンボル毎に、SPの場所はi12, i12+3, i12+6, i12+9, i*12,…のように巡回します。上記find_spでは、現OFDMシンボルでSPが何処に含まれているかを求めています。SPは、それ以外のデータキャリアに比べて4/3倍の絶対値を持っているので、上記のように積算した最大値を求めるという方法が使えます。

ここからがまだうまく行っていないと思われるのですが、上記では次のような出力が得られます(行が長くなりすぎるので、小数点以下は一部省略しています)。

[35.74547, 36.26827, 49.57394, 37.08745]
2
SPs:
6 1.0953 (-0.9832743533464458+0.482584084887267j) 1.3333
18 1.1773 (0.9411424714348882-0.7073685094875273j) 1.3333
30 1.2927 (0.9226357042956151-0.905485176200131j) -1.3333
42 1.3544 (-0.9451630023246448+0.9701050133998432j) -1.3333
54 1.3868 (-1.041607866189769+0.9155528236391836j) 1.3333
66 1.2944 (0.6906246945088386-1.0947704458085812j) 1.3333
78 1.0671 (0.6685409527954194-0.8316726977365281j) -1.3333
90 1.3859 (0.7967161344290873-1.1339926757265295j) 1.3333
102 1.1538 (-0.34105207413393135+1.102293053251151j) 1.3333
114 1.2401 (0.4762959068094629-1.144985106068488j) 1.3333
126 1.5607 (0.725557306133454-1.381834432391039j) -1.3333
138 1.2347 (-0.6547734652174335+1.0467712733713745j) -1.3333
150 1.3194 (-0.3329626554307+1.2767023965626096j) 1.3333
162 1.5988 (0.5091991640004263-1.5155690510396185j) 1.3333
174 1.3907 (-0.6562514301534865+1.2261640531390314j) 1.3333
186 1.6392 (-0.5092859972519473+1.5580715920605588j) -1.3333
198 1.5107 (0.26879055172568034-1.4866408415508643j) -1.3333
210 1.6382 (0.7524038499463859-1.4552230916819244j) 1.3333
222 1.3896 (0.44737449638796445-1.3156195604230028j) -1.3333
234 1.3833 (0.5356609612670982-1.2753992069341795j) 1.3333
246 1.559 (0.3497743406085074-1.5192501362727482j) -1.3333
258 1.1333 (-0.42997707286624176+1.048549775299747j) -1.3333
270 1.3702 (-0.2787479092644133+1.3415065163031206j) 1.3333
282 1.6204 (-0.5708941597565+1.5164865623719384j) -1.3333
294 1.4883 (0.6930350159378798-1.317100025661765j) -1.3333
306 1.5654 (-0.7261325631313592+1.3867477986830758j) -1.3333
318 1.5449 (0.4601928773417365-1.4747525850693373j) -1.3333
330 1.4912 (0.5746828035844906-1.3760673756943445j) 1.3333
342 1.4701 (0.825690594740095-1.2162618274644958j) -1.3333
354 1.4209 (0.24893414863314506-1.398884931842842j) 1.3333
366 1.3512 (-0.6292706725628592+1.1957269229318115j) 1.3333
378 1.4125 (-0.5413499265712505+1.3046784927444803j) -1.3333
390 1.4662 (0.7501030028129436-1.2598034492601253j) -1.3333
402 1.1753 (-0.7940964094918974+0.8664208985515854j) -1.3333
414 1.3589 (-0.7997872953740967+1.098570575241878j) 1.3333
426 1.0329 (-0.3727620060886928+0.96334271774669j) -1.3333

最初の行と次の行は、SPの場所と絶対値の積算値を表示しています。49は残りの3つの値36付近に比べると、ほぼ4/3倍となっているので、結果は正しそうに思われます。

ワンセグ生データをOFDM復調(1)

前回、GNU RadioとADALM PLUTOを使って、 ワンセグの生データを取得してファイルに保存しました。

いきなり余談(Jupyterを使うまで)

現在、Pythonにて上記のデータをデコードできるかを実験しています。 最初はCでプログラムを作成し始めました。でも、実装していると、 途中途中までで、思い通りに処理ができているかを確認したくなります。 そのために、グラフを作成する必要が出てきました。CImgなど、 C++で比較的に簡単に使えるライブラリも試しました。これは画像生成は簡単ですが、 グラフ生成は面倒に感じました。

それで、結局Jupyter Notebookを使ったほうが簡単だということで、Pythonに移行しました。アルゴリズムが固まったら、データを一気に処理するためにC,C++に戻る予定ですが。

ここから本題

キャプチャした生データをソフトウェアで処理して、MPEG TSを得るところまで持っていきたいと考えています。そのためには、まずなによりも、OFDMの復調処理が必要です。 ここがクリアできれば、残りはそれほど難しくないと予想しています。

以下、Notebookの画像を貼り付けていきます。

“相関値算出まで”

上記In [1]は、各種ライブラリを使用することを宣言しています。[2]でcapture.rawという、GNU Radioで保存したファイルを開いて、dataという変数に読み込みます。 ファイルの一番先頭は少し飛ばしています。

[3]はガードインターバルとシンボル長の定義です。 ADALM PLUTOでは、64/63MHzでサンプリングしています。1シンボルは1008[us]なので、 計算してみると、ちょうど1024というキリの良い個数になります(そうなるようにサンプリング周波数を設定している)。

(少なくとも日本の)ワンセグのガードインターバルはシンボル長の1/8なので、128になります。

[4]は、シンボルの境界を検出するための相関値を求める関数correlateの定義です。 この方法については、 “An Open and Free ISDB-T Full_Seg Receiver Implemented in GNU Radio” Federico Larroca et al.で最初に知りましたが、 “ML Estimation of Time and Frequency Offset in OFDM Systems” Van De Beek et al.がオリジナルのようです。

最初の論文の(1)式の計算になります。ざっくり説明すると、シンボル長だけ離れた、ガードインターバル長サンプルの相関(積和, 上記gamma)を計算しています。また、RHOは本来であればSNR/(1+SNR)で定義されるのですが、今回は定数としています。十分SNRが大きければ1に近づく値なので、 ひとまずこのように置いても問題なさそうです。

“極大計算”

[5]では、実際に先頭をずらしながら相関値を計算していき、配列corに入れます。 correlateが返すのはタプルなので、[6]で分解してそれぞれの配列を得ます。 配列corrsの値が極大になっているところが、OFDMシンボルの区切りです。

[7]はグラフを見やすくするためのサイズ調整です(横幅を伸ばしている)。

[8]で相関値とガンマの値を時系列のグラフにしています。結果が次です。

“correlation”

上記Van De Beekの論文のFigure 4と同じような結果です。横軸はサンプルの番号です。赤い線が左の縦軸に対応しており、相関値を表します。青い線が右の縦軸に対応しており、ガンマの偏角を表します。

ワンセグ生データを保存してオフライン処理できるようにした

ダイアグラムを2つに分離して、ファイルを経由するように変更

これまでで、ADALM-PLUTOとGNU Radioを使って、 ワンセグ受信ができることは確認できました。 今回は、受信したデータを一旦ファイルに保存して、GNU Radioを使ってオフライン処理できるようにしました。 目的は、ADCのデータからMPEG TSのデコードまでを、GNU Radioを使用せず自作のプログラムで行うためです。

“file_sink”

上記のようなダイアグラムを作成して実行すると、capture.rawというファイルが作成されました。 受信したデータのサンプリング周波数を調整して、LPFを通しただけのデータとなります。

次に、Pluto SDR Sourceの代わりにFile Sourceを置いて、OFDM Synchronization 1segの入力に繋ぎます。

“file_source”

上記を作成しました。こちらも実行すると、capture.rawに保存されたデータがオフライン処理され、 test_out.tsという名前でMPEG TSファイルが作成されました。

今後の目標としては、このcapture.rawを処理して、test_out.tsと同等の出力を得るプログラムを作成したいと考えています。

ちょっと苦労した点

これだけだと簡単に動作したように思われてしまうかも知れませんが、1時間くらい上手く動きませんでした。 ダイアグラム上はPluto SDR Sourceのコネクションを削除しているはずなのに、 なぜかリアルタイムで受信したものがOFDM処理されてしまい、画面上では接続されているFile Sourceからのデータが処理されませんでした。

どうやら、“Generate the flow graph"ボタンで失敗していたのが原因だったようです。これが失敗する場合でも、なぜか"Execute the flow graph"は押せることがあるようです。でも、実際にExecuteしても、Generateする前のダイアグラムが実行されるようで、画面ではPluto SDR Sourceは外しているのに、繋がっている状態の(古い)ダイアグラムが実行されていたようです。

思わぬ所でハマってしまいましたが、ひとまず生データの取得はできました。44秒位ですが、約360MB程度のファイルサイズです。1.0*10^6(サンプリング周波数)64/638(複素1サンプルバイト数)*44(秒)=352MBで、おおよそ計算どおりです。

また、家のアンテナ端子だと受信感度がイマイチだったので、DX アンテナ US10WBと、AliExpressにて、SMAオス<-> Fメスの変換アダプタを購入しました。無線機器を繋ごうとすると、こういったアダプタが(種類として)沢山必要になりますね。

データ型について

File Sinkで生成されるファイルは、GNU RadioではComplexとなっています。 Pythonのgr-utilsのgr_plot_iqのコードを見てみると、 numpy.complex64となっているようです。numpyのData Typesのページから、結局、実部、虚部の順に32-bit floatとしてバイナリデータとなっているようです。

GNU Radio + ADALM-PLUTOであっけなくワンセグ受信ができた

先日購入したADALM-PLUTOをGNU Radioで使って、ワンセグの受信ができました。

上記で@edy555さんが紹介されている、下記のコードを使用しました。

https://github.com/git-artes/gr-isdbt

基本的には上記GitHubにある通りにmake & installします。そして、examplesディレクトリに入っているrx_1seg_demo.grcを開いて、次の画面のように変更しました。

“1seg rx”

PlutoSDR Sourceを追加し、テレビ周波数チャンネルを参考に、NHK東京総合の557.142857MHzをLO Frequencyに入力しました。Sample rateは1M, RF bandwidthは500k、後はデフォルトです。また、Low Pass Filterの周波数は1*64/63MHzなので、LPFの前にRational Resamplerを追加して、Interpolation 64, Decimation 63にしました。 また、OFDM Synchronization 1segのGuard Intervalは1/8にします。

上記のサンプルレート変換は、GitHubからリンクされている論文PDFに記載されているFigure 3を参考にしました。

いざ実行しようとしたら、

AttributeError: 'module' object has no attribute 'viterbi_decoder'

といったエラーが表示されました。GitHubにもFAQで書いてありましたが、自分の場合はswigをインストールしていませんでした。それで

$ sudo apt-get install swig

でインストールして、再度gr-isdbtをmake & installしたところ、動作するようになりました。

現在F端子をSMAに変換するアダプタが到着していないので、アンテナとして、秋月で買った、下記のものを使いました。

“Antenna”

正直あまり感度は良くありません。アンテナの向きがシビアです。実行時には、次のような画面が表示されますが、 なんとかアンテナの向きを色々変えることで、コンスタレーションが集まるようにすると、コンソールにTMCC OKといった表示がされ、ちゃんとデコードできるようです。

“Constellation”

上のダイアグラムの場合だと、test_out.tsというファイルにMPEG TSストリームが保存されるので、ffplayコマンドで保存されたtest_out.tsを開くと、NHKの映像が再生されました。

ADALM PLUTOを購入してGNU Radioまで繋いだ

Analog DevicesのADALM PLUTOMouserから購入しました。まだ99USDで買えたようです。


ここはちょっと余談

これに入っているAD9363というデバイスは、 LNA, 直交ミキサ, PLL, フィルタ, ADC, DAC, FIRフィルタなど、RFフロントエンドにおおよそ必要な機能が、 たった一つのICに入っています。本来なら、これらのコンポーネントをそれぞれ基板に配置して設計したほうが楽しそうですが、 かなり骨の折れる作業です。このデバイスなら、たった1つ置くだけで良いわけです。 ただし、高機能な分、お値段も素晴らしいです。Digikeyでは1個14,640円でした(11/5調べ)。

これだけの機能があれば、それほど高くは無いとも言えるのかも知れませんが。 もっとも、実際自分でレジスタを適切に設定するのは結構大変だと予想されます。 それで、メーカはデバイスドライバで簡単に使えるようにしてくれているようです。

ちなみに、これにはXilinxのZynqも入っています。これで私物で買ったZynqは3つ目です…

個々の部品代を考えると、これがたった1万円ちょっとで購入できるわけですので、 遊びで使う分にはかなりお買い得かと思います。

余談終わり


“ADALM-PLUTO”

本体に加えて、アンテナ2本とSMAケーブル、USBケーブル(Type-A <-> Micro-Bタイプ)が付属しています。USBケーブルでPCに接続すると、LED1とReadyが光ります。

WikiにあるLinux Driversの内容に従って、libiio-utilsをインストールして

$ iio_info -n 192.168.2.1

すると、次のようなメッセージが表示されました。

Library version: 0.10 (git tag: v0.10)
Compiled with backends: local xml ip usb serial
IIO context created with network backend.
Backend version: 0.14 (git tag: v0.14  )
Backend description string: 192.168.2.1 Linux (none) 4.9.0-10315-gb07f3c6 #234 SMP PREEMPT Tue Apr 24 13:47:24 CEST 20
18 armv7l
IIO context has 8 attributes:
        hw_model: Analog Devices PlutoSDR Rev.B (Z7010-AD9363)
        hw_model_variant: 0
        hw_serial: 104473ce69910015ecff2b0017e78933a0
        fw_version: v0.28
        ad9361-phy,xo_correction: 40000140
        ad9361-phy,model: ad9363a
        local,kernel: 4.9.0-10315-gb07f3c6
        ip,ip-addr: 192.168.2.1
IIO context has 5 devices:
        iio:device3: cf-ad9361-dds-core-lpc (buffer capable)
                6 channels found:
                        voltage0:  (output, index: 0, format: le:S16/16>>0)
                        4 channel-specific attributes found:
                                attr  0: calibscale value: 1.000000
                                attr  1: calibphase value: 0.000000
                                attr  2: sampling_frequency_available value: 30719999 3839999 
                                attr  3: sampling_frequency value: 30719999
                        voltage1:  (output, index: 1, format: le:S16/16>>0)
                        4 channel-specific attributes found:
                                attr  0: calibphase value: 0.000000
                                attr  1: calibscale value: 1.000000
                                attr  2: sampling_frequency_available value: 30719999 3839999 
                                attr  3: sampling_frequency value: 30719999
                        altvoltage3: TX1_Q_F2 (output)
                        5 channel-specific attributes found:
                                attr  0: raw value: 1
                                attr  1: phase value: 0
                                attr  2: frequency value: 9279985
                                attr  3: scale value: 0.000000
                                attr  4: sampling_frequency value: 30719999
                        altvoltage1: TX1_I_F2 (output)
                        5 channel-specific attributes found:
                                attr  0: phase value: 90000
                                attr  1: scale value: 0.000000
                                attr  2: raw value: 1
                                attr  3: frequency value: 9279985
                                attr  4: sampling_frequency value: 30719999
                        altvoltage0: TX1_I_F1 (output)
                        5 channel-specific attributes found:
                                attr  0: phase value: 90000
                                attr  1: scale value: 0.000000
                                attr  2: frequency value: 9279985
                                attr  3: raw value: 1
                                attr  4: sampling_frequency value: 30719999
                        altvoltage2: TX1_Q_F1 (output)
                        5 channel-specific attributes found:
                                attr  0: raw value: 1
                                attr  1: phase value: 0
                                attr  2: frequency value: 9279985
                                attr  3: scale value: 0.000000
                                attr  4: sampling_frequency value: 30719999
                1 debug attributes found:
                                debug attr  0: direct_reg_access value: 0x90062
        iio:device1: ad9361-phy
                9 channels found:
                        altvoltage1: TX_LO (output)
                        8 channel-specific attributes found:
                                attr  0: external value: 0
                                attr  1: frequency value: 2450000000
                                attr  2: fastlock_store value: 0
                                attr  3: fastlock_recall ERROR: Invalid argument (-22)
                                attr  4: powerdown value: 0
                                attr  5: fastlock_save value: 0 238,206,235,207,206,253,207,233,206,206,123,253,206,206,206,206
                                attr  6: frequency_available value: [325000000 1 3800000000]
                                attr  7: fastlock_load value: 0
                        voltage0:  (input)
                        15 channel-specific attributes found:
                                attr  0: hardwaregain_available value: [-3 1 71]
                                attr  1: hardwaregain value: 71.000000 dB
                                attr  2: rssi value: 115.75 dB
                                attr  3: rf_port_select value: A_BALANCED
                                attr  4: gain_control_mode value: slow_attack
                                attr  5: rf_port_select_available value: A_BALANCED B_BALANCED C_BALANCED A_N A_P B_N B_P C_N C_P TX_MONITOR1 TX_MONITOR2 TX_MONITOR1_2
                                attr  6: rf_bandwidth value: 18000000
                                attr  7: rf_dc_offset_tracking_en value: 1
                                attr  8: sampling_frequency_available value: [2083333 1 61440000]
                                attr  9: quadrature_tracking_en value: 1
                                attr 10: sampling_frequency value: 30719999
                                attr 11: gain_control_mode_available value: manual fast_attack slow_attack hybrid
                                attr 12: filter_fir_en value: 0
                                attr 13: rf_bandwidth_available value: [200000 1 56000000]
                                attr 14: bb_dc_offset_tracking_en value: 1
                        voltage3:  (output)
                        8 channel-specific attributes found:
                                attr  0: scale value: 1.000000
                                attr  1: raw value: 306
                                attr  2: sampling_frequency_available value: [2083333 1 61440000]
                                attr  3: rf_port_select_available value: A B
                                attr  4: filter_fir_en value: 0
                                attr  5: sampling_frequency value: 30719999
                                attr  6: rf_bandwidth_available value: [200000 1 40000000]
                                attr  7: rf_bandwidth value: 18000000
                        altvoltage0: RX_LO (output)
                        8 channel-specific attributes found:
                                attr  0: frequency_available value: [325000000 1 3800000000]
                                attr  1: fastlock_save value: 0 244,244,244,244,244,244,244,228,244,244,244,244,244,244,244,252
                                attr  2: powerdown value: 0
                                attr  3: fastlock_load value: 0
                                attr  4: fastlock_store value: 0
                                attr  5: frequency value: 2400000000
                                attr  6: external value: 0
                                attr  7: fastlock_recall ERROR: Invalid argument (-22)
                        voltage2:  (output)
                        8 channel-specific attributes found:
                                attr  0: raw value: 306
                                attr  1: scale value: 1.000000
                                attr  2: sampling_frequency_available value: [2083333 1 61440000]
                                attr  3: rf_port_select_available value: A B
                                attr  4: filter_fir_en value: 0
                                attr  5: sampling_frequency value: 30719999
                                attr  6: rf_bandwidth_available value: [200000 1 40000000]
                                attr  7: rf_bandwidth value: 18000000
                        temp0:  (input)
                        1 channel-specific attributes found:
                                attr  0: input value: 36842
                        voltage0:  (output)
                        10 channel-specific attributes found:
                                attr  0: rf_port_select value: A
                                attr  1: hardwaregain value: -10.000000 dB
                                attr  2: rssi value: 0.00 dB
                                attr  3: hardwaregain_available value: [0 250 89750]
                                attr  4: sampling_frequency_available value: [2083333 1 61440000]
                                attr  5: rf_port_select_available value: A B
                                attr  6: filter_fir_en value: 0
                                attr  7: sampling_frequency value: 30719999
                                attr  8: rf_bandwidth_available value: [200000 1 40000000]
                                attr  9: rf_bandwidth value: 18000000
                        voltage2:  (input)
                        13 channel-specific attributes found:
                                attr  0: offset value: 57
                                attr  1: scale value: 0.305250
                                attr  2: raw value: 892
                                attr  3: rf_port_select_available value: A_BALANCED B_BALANCED C_BALANCED A_N A_P B_N B_P C_N C_P TX_MONITOR1 TX_MONITOR2 TX_MONITOR1_2
                                attr  4: rf_bandwidth value: 18000000
                                attr  5: rf_dc_offset_tracking_en value: 1
                                attr  6: sampling_frequency_available value: [2083333 1 61440000]
                                attr  7: quadrature_tracking_en value: 1
                                attr  8: sampling_frequency value: 30719999
                                attr  9: gain_control_mode_available value: manual fast_attack slow_attack hybrid
                                attr 10: filter_fir_en value: 0
                                attr 11: rf_bandwidth_available value: [200000 1 56000000]
                                attr 12: bb_dc_offset_tracking_en value: 1
                        out:  (input)
                        1 channel-specific attributes found:
                                attr  0: voltage_filter_fir_en value: 0
                18 device-specific attributes found:
                                attr  0: dcxo_tune_coarse ERROR: No such device (-19)
                                attr  1: rx_path_rates value: BBPLL:983039994 ADC:245759998 R2:122879999 R1:61439999 RF:30719999 RXSAMP:30719999
                                attr  2: trx_rate_governor value: nominal
                                attr  3: calib_mode_available value: auto manual manual_tx_quad tx_quad rf_dc_offs rssi_gain_step
                                attr  4: xo_correction_available value: [39992140 1 40008140]
                                attr  5: gain_table_config ERROR: Input/output error (-5)
                                attr  6: dcxo_tune_fine ERROR: No such device (-19)
                                attr  7: dcxo_tune_fine_available value: [0 0 0]
                                attr  8: ensm_mode_available value: sleep wait alert fdd pinctrl pinctrl_fdd_indep
                                attr  9: multichip_sync ERROR: Permission denied (-13)
                                attr 10: rssi_gain_step_error value: lna_error: 0 0 0 0
mixer_error: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
gain_step_calib_reg_val: 0 0 0 0 0
                                attr 11: dcxo_tune_coarse_available value: [0 0 0]
                                attr 12: tx_path_rates value: BBPLL:983039994 DAC:122879999 T2:122879999 T1:61439999 TF:30719999 TXSAMP:30719999
                                attr 13: trx_rate_governor_available value: nominal highest_osr
                                attr 14: xo_correction value: 40000140
                                attr 15: ensm_mode value: fdd
                                attr 16: filter_fir_config value: FIR Rx: 0,0 Tx: 0,0
                                attr 17: calib_mode value: auto
                175 debug attributes found:
                                debug attr  0: digital_tune value: 0
                                debug attr  1: calibration_switch_control value: 0
                                debug attr  2: multichip_sync value: 0
                                debug attr  3: gaininfo_rx2 ERROR: Resource temporarily unavailable (-11)
                                debug attr  4: gaininfo_rx1 value: 71 76 0 0 0 0 0 0
                                debug attr  5: bist_timing_analysis value: 0
                                debug attr  6: bist_tone value: 0
                                debug attr  7: bist_prbs value: 0
                                debug attr  8: loopback value: 0
                                debug attr  9: initialize value: 0
                                debug attr 10: adi,txmon-2-lo-cm value: 48
                                debug attr 11: adi,txmon-1-lo-cm value: 48
                                debug attr 12: adi,txmon-2-front-end-gain value: 2
                                debug attr 13: adi,txmon-1-front-end-gain value: 2
                                debug attr 14: adi,txmon-duration value: 8192
                                debug attr 15: adi,txmon-delay value: 511
                                debug attr 16: adi,txmon-one-shot-mode-enable value: 0
                                debug attr 17: adi,txmon-dc-tracking-enable value: 0
                                debug attr 18: adi,txmon-high-gain value: 24
                                debug attr 19: adi,txmon-low-gain value: 0
                                debug attr 20: adi,txmon-low-high-thresh value: 37000
                                debug attr 21: adi,gpo3-tx-delay-us value: 0
                                debug attr 22: adi,gpo3-rx-delay-us value: 0
                                debug attr 23: adi,gpo2-tx-delay-us value: 0
                                debug attr 24: adi,gpo2-rx-delay-us value: 0
                                debug attr 25: adi,gpo1-tx-delay-us value: 0
                                debug attr 26: adi,gpo1-rx-delay-us value: 0
                                debug attr 27: adi,gpo0-tx-delay-us value: 0
                                debug attr 28: adi,gpo0-rx-delay-us value: 0
                                debug attr 29: adi,gpo3-slave-tx-enable value: 0
                                debug attr 30: adi,gpo3-slave-rx-enable value: 0
                                debug attr 31: adi,gpo2-slave-tx-enable value: 0
                                debug attr 32: adi,gpo2-slave-rx-enable value: 0
                                debug attr 33: adi,gpo1-slave-tx-enable value: 0
                                debug attr 34: adi,gpo1-slave-rx-enable value: 0
                                debug attr 35: adi,gpo0-slave-tx-enable value: 0
                                debug attr 36: adi,gpo0-slave-rx-enable value: 0
                                debug attr 37: adi,gpo3-inactive-state-high-enable value: 0
                                debug attr 38: adi,gpo2-inactive-state-high-enable value: 0
                                debug attr 39: adi,gpo1-inactive-state-high-enable value: 0
                                debug attr 40: adi,gpo0-inactive-state-high-enable value: 0
                                debug attr 41: adi,gpo-manual-mode-enable-mask value: 0
                                debug attr 42: adi,gpo-manual-mode-enable value: 0
                                debug attr 43: adi,aux-dac2-tx-delay-us value: 0
                                debug attr 44: adi,aux-dac2-rx-delay-us value: 0
                                debug attr 45: adi,aux-dac2-active-in-alert-enable value: 0
                                debug attr 46: adi,aux-dac2-active-in-tx-enable value: 0
                                debug attr 47: adi,aux-dac2-active-in-rx-enable value: 0
                                debug attr 48: adi,aux-dac2-default-value-mV value: 0
                                debug attr 49: adi,aux-dac1-tx-delay-us value: 0
                                debug attr 50: adi,aux-dac1-rx-delay-us value: 0
                                debug attr 51: adi,aux-dac1-active-in-alert-enable value: 0
                                debug attr 52: adi,aux-dac1-active-in-tx-enable value: 0
                                debug attr 53: adi,aux-dac1-active-in-rx-enable value: 0
                                debug attr 54: adi,aux-dac1-default-value-mV value: 0
                                debug attr 55: adi,aux-dac-manual-mode-enable value: 1
                                debug attr 56: adi,aux-adc-decimation value: 256
                                debug attr 57: adi,aux-adc-rate value: 40000000
                                debug attr 58: adi,temp-sense-decimation value: 256
                                debug attr 59: adi,temp-sense-periodic-measurement-enable value: 1
                                debug attr 60: adi,temp-sense-offset-signed value: 206
                                debug attr 61: adi,temp-sense-measurement-interval-ms value: 1000
                                debug attr 62: adi,elna-gaintable-all-index-enable value: 0
                                debug attr 63: adi,elna-rx2-gpo1-control-enable value: 0
                                debug attr 64: adi,elna-rx1-gpo0-control-enable value: 0
                                debug attr 65: adi,elna-bypass-loss-mdB value: 0
                                debug attr 66: adi,elna-gain-mdB value: 0
                                debug attr 67: adi,elna-settling-delay-ns value: 0
                                debug attr 68: adi,ctrl-outs-enable-mask value: 255
                                debug attr 69: adi,ctrl-outs-index value: 0
                                debug attr 70: adi,rssi-duration value: 1000
                                debug attr 71: adi,rssi-wait value: 1
                                debug attr 72: adi,rssi-delay value: 1
                                debug attr 73: adi,rssi-unit-is-rx-samples-enable value: 0
                                debug attr 74: adi,rssi-restart-mode value: 3
                                debug attr 75: adi,fagc-adc-large-overload-inc-steps value: 2
                                debug attr 76: adi,fagc-power-measurement-duration-in-state5 value: 64
                                debug attr 77: adi,fagc-rst-gla-if-en-agc-pulled-high-mode value: 0
                                debug attr 78: adi,fagc-rst-gla-en-agc-pulled-high-enable value: 0
                                debug attr 79: adi,fagc-rst-gla-large-lmt-overload-enable value: 1
                                debug attr 80: adi,fagc-rst-gla-large-adc-overload-enable value: 1
                                debug attr 81: adi,fagc-energy-lost-stronger-sig-gain-lock-exit-cnt value: 8
                                debug attr 82: adi,fagc-rst-gla-engergy-lost-sig-thresh-below-ll value: 10
                                debug attr 83: adi,fagc-rst-gla-engergy-lost-goto-optim-gain-enable value: 1
                                debug attr 84: adi,fagc-rst-gla-engergy-lost-sig-thresh-exceeded-enable value: 1
                                debug attr 85: adi,fagc-rst-gla-stronger-sig-thresh-above-ll value: 10
                                debug attr 86: adi,fagc-optimized-gain-offset value: 5
                                debug attr 87: adi,fagc-rst-gla-stronger-sig-thresh-exceeded-enable value: 1
                                debug attr 88: adi,fagc-use-last-lock-level-for-set-gain-enable value: 1
                                debug attr 89: adi,fagc-gain-index-type-after-exit-rx-mode value: 0
                                debug attr 90: adi,fagc-gain-increase-after-gain-lock-enable value: 0
                                debug attr 91: adi,fagc-final-overrange-count value: 3
                                debug attr 92: adi,fagc-lmt-final-settling-steps value: 1
                                debug attr 93: adi,fagc-lpf-final-settling-steps value: 1
                                debug attr 94: adi,fagc-lock-level-gain-increase-upper-limit value: 5
                                debug attr 95: adi,fagc-lock-level-lmt-gain-increase-enable value: 1
                                debug attr 96: adi,fagc-lp-thresh-increment-steps value: 1
                                debug attr 97: adi,fagc-lp-thresh-increment-time value: 5
                                debug attr 98: adi,fagc-allow-agc-gain-increase-enable value: 0
                                debug attr 99: adi,fagc-state-wait-time-ns value: 260
                                debug attr 100: adi,fagc-dec-pow-measurement-duration value: 64
                                debug attr 101: adi,agc-immed-gain-change-if-large-lmt-overload-enable value: 0
                                debug attr 102: adi,agc-immed-gain-change-if-large-adc-overload-enable value: 0
                                debug attr 103: adi,agc-gain-update-interval-us value: 1000
                                debug attr 104: adi,agc-sync-for-gain-counter-enable value: 0
                                debug attr 105: adi,agc-dig-gain-step-size value: 4
                                debug attr 106: adi,agc-dig-saturation-exceed-counter value: 3
                                debug attr 107: adi,agc-lmt-overload-large-inc-steps value: 2
                                debug attr 108: adi,agc-lmt-overload-small-exceed-counter value: 10
                                debug attr 109: adi,agc-lmt-overload-large-exceed-counter value: 10
                                debug attr 110: adi,agc-adc-lmt-small-overload-prevent-gain-inc-enable value: 0
                                debug attr 111: adi,agc-adc-large-overload-inc-steps value: 2
                                debug attr 112: adi,agc-adc-large-overload-exceed-counter value: 10
                                debug attr 113: adi,agc-adc-small-overload-exceed-counter value: 10
                                debug attr 114: adi,agc-outer-thresh-low-inc-steps value: 2
                                debug attr 115: adi,agc-outer-thresh-low value: 18
                                debug attr 116: adi,agc-inner-thresh-low-inc-steps value: 1
                                debug attr 117: adi,agc-inner-thresh-low value: 12
                                debug attr 118: adi,agc-inner-thresh-high-dec-steps value: 1
                                debug attr 119: adi,agc-inner-thresh-high value: 10
                                debug attr 120: adi,agc-outer-thresh-high-dec-steps value: 2
                                debug attr 121: adi,agc-outer-thresh-high value: 5
                                debug attr 122: adi,agc-attack-delay-extra-margin-us value: 1
                                debug attr 123: adi,mgc-split-table-ctrl-inp-gain-mode value: 0
                                debug attr 124: adi,mgc-dec-gain-step value: 2
                                debug attr 125: adi,mgc-inc-gain-step value: 2
                                debug attr 126: adi,mgc-rx2-ctrl-inp-enable value: 0
                                debug attr 127: adi,mgc-rx1-ctrl-inp-enable value: 0
                                debug attr 128: adi,gc-use-rx-fir-out-for-dec-pwr-meas-enable value: 0
                                debug attr 129: adi,gc-max-dig-gain value: 15
                                debug attr 130: adi,gc-dig-gain-enable value: 0
                                debug attr 131: adi,gc-low-power-thresh value: 24
                                debug attr 132: adi,gc-dec-pow-measurement-duration value: 8192
                                debug attr 133: adi,gc-lmt-overload-low-thresh value: 704
                                debug attr 134: adi,gc-lmt-overload-high-thresh value: 800
                                debug attr 135: adi,gc-adc-large-overload-thresh value: 58
                                debug attr 136: adi,gc-adc-small-overload-thresh value: 47
                                debug attr 137: adi,gc-adc-ovr-sample-size value: 4
                                debug attr 138: adi,gc-rx2-mode value: 2
                                debug attr 139: adi,gc-rx1-mode value: 2
                                debug attr 140: adi,update-tx-gain-in-alert-enable value: 0
                                debug attr 141: adi,tx-attenuation-mdB value: 10000
                                debug attr 142: adi,rf-tx-bandwidth-hz value: 18000000
                                debug attr 143: adi,rf-rx-bandwidth-hz value: 18000000
                                debug attr 144: adi,qec-tracking-slow-mode-enable value: 0
                                debug attr 145: adi,dc-offset-count-low-range value: 50
                                debug attr 146: adi,dc-offset-count-high-range value: 40
                                debug attr 147: adi,dc-offset-attenuation-low-range value: 5
                                debug attr 148: adi,dc-offset-attenuation-high-range value: 6
                                debug attr 149: adi,dc-offset-tracking-update-event-mask value: 5
                                debug attr 150: adi,clk-output-mode-select value: 0
                                debug attr 151: adi,trx-synthesizer-target-fref-overwrite-hz value: 80008000
                                debug attr 152: adi,rx1-rx2-phase-inversion-enable value: 0
                                debug attr 153: adi,tx-rf-port-input-select-lock-enable value: 1
                                debug attr 154: adi,rx-rf-port-input-select-lock-enable value: 1
                                debug attr 155: adi,tx-rf-port-input-select value: 0
                                debug attr 156: adi,rx-rf-port-input-select value: 0
                                debug attr 157: adi,split-gain-table-mode-enable value: 0
                                debug attr 158: adi,1rx-1tx-mode-use-tx-num value: 1
                                debug attr 159: adi,1rx-1tx-mode-use-rx-num value: 1
                                debug attr 160: adi,2rx-2tx-mode-enable value: 0
                                debug attr 161: adi,digital-interface-tune-fir-disable value: 1
                                debug attr 162: adi,digital-interface-tune-skip-mode value: 0
                                debug attr 163: adi,tx-fastlock-pincontrol-enable value: 0
                                debug attr 164: adi,rx-fastlock-pincontrol-enable value: 0
                                debug attr 165: adi,rx-fastlock-delay-ns value: 0
                                debug attr 166: adi,tx-fastlock-delay-ns value: 0
                                debug attr 167: adi,tdd-skip-vco-cal-enable value: 0
                                debug attr 168: adi,tdd-use-dual-synth-mode-enable value: 0
                                debug attr 169: adi,debug-mode-enable value: 0
                                debug attr 170: adi,ensm-enable-txnrx-control-enable value: 0
                                debug attr 171: adi,ensm-enable-pin-pulse-mode-enable value: 0
                                debug attr 172: adi,frequency-division-duplex-independent-mode-enable value: 0
                                debug attr 173: adi,frequency-division-duplex-mode-enable value: 1
                                debug attr 174: direct_reg_access value: 0x0
        iio:device4: cf-ad9361-lpc (buffer capable)
                2 channels found:
                        voltage0:  (input, index: 0, format: le:S12/16>>0)
                        6 channel-specific attributes found:
                                attr  0: calibphase value: 0.000000
                                attr  1: calibbias value: 0
                                attr  2: calibscale value: 1.000000
                                attr  3: samples_pps ERROR: No such device (-19)
                                attr  4: sampling_frequency_available value: 30719999 3839999 
                                attr  5: sampling_frequency value: 30719999
                        voltage1:  (input, index: 1, format: le:S12/16>>0)
                        6 channel-specific attributes found:
                                attr  0: calibbias value: 0
                                attr  1: calibphase value: 0.000000
                                attr  2: calibscale value: 1.000000
                                attr  3: samples_pps ERROR: No such device (-19)
                                attr  4: sampling_frequency_available value: 30719999 3839999 
                                attr  5: sampling_frequency value: 30719999
                2 debug attributes found:
                                debug attr  0: pseudorandom_err_check value: CH0 : PN9 : Out of Sync : PN Error
CH1 : PN9 : Out of Sync : PN Error
                                debug attr  1: direct_reg_access value: 0x0
        iio:device2: xadc
                10 channels found:
                        voltage5: vccoddr (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 0.732421875
                                attr  1: raw value: 1848
                        voltage0: vccint (input)
                        2 channel-specific attributes found:
                                attr  0: raw value: 1385
                                attr  1: scale value: 0.732421875
                        voltage4: vccpaux (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 0.732421875
                                attr  1: raw value: 2455
                        temp0:  (input)
                        3 channel-specific attributes found:
                                attr  0: scale value: 123.040771484
                                attr  1: offset value: -2219
                                attr  2: raw value: 2646
                        voltage7: vrefn (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 0.732421875
                                attr  1: raw value: 8
                        voltage1: vccaux (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 0.732421875
                                attr  1: raw value: 2457
                        voltage2: vccbram (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 0.732421875
                                attr  1: raw value: 1377
                        voltage3: vccpint (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 0.732421875
                                attr  1: raw value: 1377
                        voltage8:  (input)
                        2 channel-specific attributes found:
                                attr  0: raw value: 3693
                                attr  1: scale value: 0.244140625
                        voltage6: vrefp (input)
                        2 channel-specific attributes found:
                                attr  0: raw value: 1711
                                attr  1: scale value: 0.732421875
                1 device-specific attributes found:
                                attr  0: sampling_frequency value: 961538
        iio:device0: adm1177
                2 channels found:
                        voltage0:  (input)
                        2 channel-specific attributes found:
                                attr  0: scale value: 6.433105468
                                attr  1: raw value: 769
                        current0:  (input)
                        2 channel-specific attributes found:
                                attr  0: raw value: 805
                                attr  1: scale value: 0.516601562

コマンドラインで

単なるアナログスイッチがRF信号のミキサーになる理由

SDRを調査してみると、ほとんどの場合において、受信した信号にsin信号とcos信号を乗算してI, Q信号を得るという処理が含まれています。

ダイレクトサンプリング方式だと、この乗算はデジタル領域で行うことになります。 自作SDR受信機では、この方法を取りました(参考)。 40Mサンプリング程度のADCを使用すれば、FM放送全体の周波数帯を(折り返しも含めて)十分サンプリングでき、 デジタル乗算方式を用いれば物理的回路が不要になり、とても簡便です。 また、sin, cos信号をデジタル的に生成しているので、位相誤差などが大きな問題になることもありません。

I, Q信号を得るための別の方法もあります。同調したい周波数(近辺)のsin, cos信号をPLLで生成し、 アナログ乗算器(ミキサ)で乗算を行い、結果をADCでサンプルする、というものです。 この方式を応用すれば、音声帯域(最大192kHz程度)の、 つまりマイクロフォンの音声を取り込むための汎用ADCのL, R入力に乗算結果を入力することで、 I, Q信号を得ることができます。すなわち、帯域幅の狭い、廉価なADCが使用できるということです。

このように、アナログ領域で乗算を行う方式の方が、昔から行われている手段のようです(当然といえば当然)。 もっとも、FM復調には300kHz程度の帯域が望ましいそうなので、192kHzだと少し音質は犠牲になるかも知れません。 また、Zero-IFにするとDC成分がのったりして、また別の問題に対処する必要があるようですが、それは別の機会に。

上記を回路として実装するにあたっては、ミキサが重要になります。ただ、少し調べてみると、 どうやら単なる(On/Off切り替えしかない)アナログスイッチがミキサの代わりになるという情報を見つけました。 参考として、How to Multiply RF Signals without a Multiplier: The Switching Mixerと、 Square Wave Signalsがとても分かりやすかったです。

大雑把にいうと、10MHzの方形波は結局のところ、10MHz, 30MHz, 50MHz,…という周波数のsin波の合成ですので、 たとえば、11MHzの信号を、10MHzでOn/Offが切り替わるアナログスイッチを通すことで、 11-10=1MHzの信号が基本波として残ります。もちろん、11+10=21MHzや、 その他30MHz, 50MHzとの差分の周波数にも信号が現れますが、これらはLPFで取り除くことができます。 結果として、10MHzの方形波をもって10MHzのsin波の代わりとすることができました。

考えてみれば三角関数のちょっとした応用ですが、数学がそのまま使えるところがSDRのまた面白いところです。