ダイオードによる包絡線検波のプログラムを組んでみます。
MCMを使っていったん12KHzのAM信号を作り、それの絶対値を求める(実際には0と比較して大きいほうを取り出し)ことでダイオード検波を行います。最後の平滑化はLPFを使います。伝送する音声の帯域は3KHzです。図1にブロックダイアグラムを示します。ダイオード検波の部分はstk::max()関数を使いました。信号と0の間で比較を行い、大きなほうを選ぶことで負の値をきります。
図1 AM変調と包絡線復調
復調結果にはDC成分がのっていますが、そのままにしています。
#include "modem.h"
#include <stdlib.h>
#include <def2191.h> // ファイルの先頭に置く
#include <sysreg.h>
short tlpfCoeff[127]={
#include "tlpf.txt"
};
short rlpfCoeff[31]={
#include "rlpf.txt"
};
//**************************************************************************
//
// CModem::CModemの定義
//
//
//**************************************************************************
CModem::CModem():mcm::fwEzKit2191()
{
osc = new stk::CSinCosDDS(16384,0); // 12KHz
rlpf = new stk::CFirFilter(31, rlpfCoeff );
tlpf = new stk::CFirFilter(127, tlpfCoeff );
temp = new short[bufSize];
carrier = new short[bufSize];
}
//**************************************************************************
//
// CModem::~CModemの定義
//
//
//**************************************************************************
CModem::~CModem()
{
delete osc;
delete tlpf;
delete rlpf;
delete[] temp;
delete[] carrier;
}
//**************************************************************************
//
// CModem::handleBufferの定義
//
// handleBufferメソッドはDMA転送が終わるたびに受信バッファと送信
// バッファをパラメータに呼ばれる。受信バッファには直前のDMAで受信した
// データが入っている。handleBufferから戻るときに送信バッファにデータを
// おいておくと、次のDMA転送で送信される。
//
//**************************************************************************
void CModem::handleBuffer( struct mcm::sample * bufTx,
struct mcm::sample * bufRx )
{
stk::copy( temp, &bufRx[0].r, bufSize, 1, sizeof( mcm::sample ) );
tlpf->run( temp, temp, bufSize );
stk::mul( temp, temp, (int)(0.5*32767), bufSize ); // 飽和回避のためのスケーリング
stk::add( temp, temp, (int)(0.5*32767), bufSize ); // DCオフセットを付加
osc->run( carrier, bufSize ); // 搬送波生成
stk::mul( temp, temp, carrier, bufSize ); // 振幅変調
stk::max( temp, temp, (short)0, (short)bufSize ); // ダイオード検波
rlpf->run( temp, temp, bufSize ); // 可聴領域だけ取り出す
stk::copy( &bufTx[0].r, temp, bufSize, sizeof( mcm::sample ) );
stk::copy( &bufTx[0].l, temp, bufSize, sizeof( mcm::sample ) );
}
3KHzともなるとかなりこもった音になります。それでも「天使の歌声」オリビア・ニュートンジョンがちゃんと聞けるあたりはご立派。
次は⇒プロダクト検波