Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: Array_Matrix mbed SerialTxRxIntr DSP_ADDA UIT_FFT_Real Window
Revision 1:d4e3f39ce206, committed 2021-12-08
- Comitter:
- MikamiUitOpen
- Date:
- Wed Dec 08 03:15:17 2021 +0000
- Parent:
- 0:3bf11d2ab6ad
- Child:
- 2:2ca9f8a0f6ef
- Commit message:
- 2
Changed in this revision
--- a/DoubleBuffer.hpp Thu Sep 09 08:55:42 2021 +0000
+++ b/DoubleBuffer.hpp Wed Dec 08 03:15:17 2021 +0000
@@ -2,7 +2,7 @@
// ダブル・バッファの template クラス
// バッファに2次元配列(Matrix クラス)を使用
//
-// 2021/05/22, Copyright (c) 2021 MIKAMI, Naoki
+// 2021/10/22, Copyright (c) 2021 MIKAMI, Naoki
//--------------------------------------------------------
#ifndef DOUBLE_BUFFER_HPP
@@ -11,19 +11,19 @@
#include "Matrix.hpp"
using namespace Mikami;
-template<class T> class DoubleBuffer
+class DoubleBuffer
{
public:
// コンストラクタ
- explicit DoubleBuffer(int size, T initialValue = 0)
+ explicit DoubleBuffer(int size, float initialValue = 0)
: N_(size), buf_(2, size, initialValue), ping_(0), pong_(1),
index_(0), full_(false) {}
// データを格納
- void Store(T data) { buf_[ping_][index_++] = data; }
+ void Store(float data) { buf_[ping_][index_++] = data; }
// 出力バッファからデータの取り出し
- T Get(int n) const { return buf_[pong_][n]; }
+ float Get(int n) const { return buf_[pong_][n]; }
// バッファが満杯でバッファを切り替える
void IsFullSwitch()
@@ -46,7 +46,7 @@
private:
const int N_; // バッファのサイズ
- Matrix<T> buf_; // バッファ
+ Matrix<float> buf_; // バッファ
int ping_, pong_; // バッファ切替用
int index_; // 入力データのカウンタ
bool full_; // 満杯の場合 true
--- a/MySpectrogram/FFT_Spectrogram.cpp Thu Sep 09 08:55:42 2021 +0000
+++ b/MySpectrogram/FFT_Spectrogram.cpp Wed Dec 08 03:15:17 2021 +0000
@@ -1,23 +1,23 @@
//-------------------------------------------------------
// スペクトログラムで使う FFT 解析用クラス
//
-// 2021/05/24, Copyright (c) 2021 MIKAMI, Naoki
+// 2021/11/17, Copyright (c) 2021 MIKAMI, Naoki
//-------------------------------------------------------
#include "FFT_Spectrogram.hpp"
namespace Mikami
{
- FftSpectropgram::FftSpectropgram(int nData, int nFft)
- : N_DATA_(nData), N_FFT_(nFft),
- fft_(nFft), wHm_(nFft, nData-1), b1_(1.0f),
- xData_(nFft), wData_(nFft), yFft_(nFft/2+1) {}
+ FftSpectropgram::FftSpectropgram(int nFft)
+ : N_FFT_(nFft), fft_(nFft), wHm_(nFft),
+ xData_(nFft), wData_(nFft), yFft_(nFft/2+1)
+ { SwEmphasis(false); } // 最初は高域強調なし
- void FftSpectropgram::Execute(const Array<float> &xn, Array<float> &absFt)
+ void FftSpectropgram::Execute(const Array<float> &xn,
+ Array<float> &absFt)
{
- // 高域強調
- for (int n=0; n<N_DATA_-1; n++)
- xData_[n] = xn[n+1] - b1_*xn[n];
+ // データのコピー,高域強調の有無は SwEmphasis() で切り替え
+ (this->*fp)(xn);
// 直流分を除去
float sum = 0;
@@ -25,9 +25,18 @@
float ave = sum/N_FFT_;
for (int n=0; n<N_FFT_; n++) xData_[n] = xData_[n] - ave;
- wData_ = wHm_.Execute(xData_); // 窓掛け
- fft_.Execute(wData_, yFft_); // FFT の実行
+ wData_ = wHm_.Execute(xData_); // 窓掛け
+ fft_.Execute(wData_, yFft_); // FFT の実行
for (int n=0; n<=N_FFT_/2; n++) // 絶対値に変換
absFt[n] = 100.0f*abs(yFft_[n]);
}
+
+ // データを作業領域にコピーする際に高域強調処理を行う
+ void FftSpectropgram::CopyH(const Array<float> &xn)
+ {
+ // 差分の処理
+ for (int n=1; n<N_FFT_; n++) // n=1 から開始
+ xData_[n] = xn[n] - xn[n-1];
+ xData_[0] = xData_[1]; // n=0 に対応
+ }
}
\ No newline at end of file
--- a/MySpectrogram/FFT_Spectrogram.hpp Thu Sep 09 08:55:42 2021 +0000
+++ b/MySpectrogram/FFT_Spectrogram.hpp Wed Dec 08 03:15:17 2021 +0000
@@ -1,11 +1,11 @@
//-------------------------------------------------------
// スペクトログラムで使う FFT 解析用クラス(ヘッダ)
//
-// 2021/05/24, Copyright (c) 2021 MIKAMI, Naoki
+// 2021/11/17, Copyright (c) 2021 MIKAMI, Naoki
//-------------------------------------------------------
-#ifndef FFT_SPECTROGRAM_HPP
-#define FFT_SPECTROGRAM_HPP
+#ifndef FFT_ANALYZER_HPP
+#define FFT_ANALYZER_HPP
#include "Array.hpp"
#include "fftReal.hpp"
@@ -16,32 +16,35 @@
class FftSpectropgram
{
public:
- // nData: 解析で使うデータ数
- // nFft: 解析で使う FFT の点数
- FftSpectropgram(int nData, int nFft);
+ // nFft: FFT のデータ点の数
+ explicit FftSpectropgram(int nFft);
virtual ~FftSpectropgram() {}
- void Execute(const Array<float> &xn, Array<float> &db);
- // 高域強調の程度を決める定数の設定(b1 = 1 で差分,b1 = 0 で高域強調なし)
- void SetHighEmphasizer(float b1) { b1_ = b1; }
+ void Execute(const Array<float> &xn, Array<float> &absFt);
+
+ // データのコピーを行う際の高域強調の有無切り替え
+ void SwEmphasis(bool on)
+ { fp = on ? &FftSpectropgram::CopyH : &FftSpectropgram::Copy; }
private:
- const int N_DATA_;
const int N_FFT_;
FftReal fft_;
- HammingWindow wHm_;
- float b1_;
+ HammingWindow wHm_; // ハミング窓
- Array<float> xData_; // 解析で使うデータ
+ Array<float> xData_; // 解析対象の時系列データ
Array<float> wData_; // 窓掛けされたデータ
- Array<Complex> yFft_; // FFT の出力
+ Array<Complex> yFft_; // FFT の結果
- float Norm(Complex x)
- { return x.real()*x.real() + x.imag()*x.imag(); }
+ // コピーの際に使う関数に対する関数ポインタ
+ void (FftSpectropgram::*fp)(const Array<float> &xn);
+ // データを作業領域にコピー:高域強調は行わない
+ void Copy(const Array<float> &xn) { xData_ = xn; }
+ // データを作業領域にコピー:高域強調は行う
+ void CopyH(const Array<float> &xn);
// コピー・コンストラクタおよび代入演算子の禁止のため
FftSpectropgram(const FftSpectropgram& );
FftSpectropgram& operator=(const FftSpectropgram& );
};
}
-#endif // FFT_SPECTROGRAM_HPP
\ No newline at end of file
+#endif // FFT_ANALYZER_HPP
\ No newline at end of file
--- a/MySpectrogram/Window.lib Thu Sep 09 08:55:42 2021 +0000 +++ b/MySpectrogram/Window.lib Wed Dec 08 03:15:17 2021 +0000 @@ -1,1 +1,1 @@ -https://os.mbed.com/users/MikamiUitOpen/code/Window/#823e9a4ab223 +https://os.mbed.com/users/MikamiUitOpen/code/Window/#d8673bf6f89c
--- a/main.cpp Thu Sep 09 08:55:42 2021 +0000
+++ b/main.cpp Wed Dec 08 03:15:17 2021 +0000
@@ -4,22 +4,22 @@
// 標本化周波数を 10 倍に設定し,アンチエイリアシングフィルタを使う
//
// ● PC 側のプログラム: "CQ_Spectrogram"
-// ● ボーレート: 最初: 9600 baud
+// ● ボーレート: 最初: 9600 baud
// 通信確立後: 460800 baud
// ● 受信データの文字列の終了マーク: "\r"
//
// ● 入力: A1
//
-// 2021/07/11, Copyright (c) 2021 MIKAMI, Naoki
+// 2021/11/17, Copyright (c) 2021 MIKAMI, Naoki
//---------------------------------------------------------------------
#include <string>
#include "Array.hpp"
#include "DSP_AdcIntr.hpp"
+#include "FFT_Spectrogram.hpp"
+#include "DoubleBuffer.hpp"
#include "Coefs_IIR_LP.hpp" // 縦続形 IIR フィルタの係数
#include "IirCascade.hpp" // 縦続形 IIR フィルタ
-#include "FFT_Spectrogram.hpp"
-#include "DoubleBuffer.hpp"
#include "XferSpectrum.hpp"
using namespace Mikami;
@@ -28,15 +28,14 @@
#endif
const int N_FFT_ = 512; // FFT の点数
-const int N_DATA_ = N_FFT_ + 1; // スペクトル解析に使うデータ数(差分処理を考慮)
-const int N_FRAME_ = N_FFT_/2 + 1; // 1フレーム当たり標本化するデータ数
-const int N_FFT_2_ = N_FFT_/2; // FFT の点数の半分
-const int RATIO_ = 10; // オーバーサンプリングの倍率
+const int N_SMPL_ = N_FFT_/2; // 1度に標本化するデータ数
+const int N_SPC_ = N_FFT_/2 + 1; // 有効なスペクトルの点数
+const int RATIO_ = 10; // ダウンサンプリングの倍率:1/10
const int N_TX_ = 251; // PC に転送するデータ数
DspAdcIntr myAdc_(10.24f*RATIO_, A1); // 標本化周波数: 100 kHz
IirCascade aaf_(ORDER1_, CK1_, G01_); // ダウンサンプリング用 Anti-alias フィルタ
-DoubleBuffer<float> buf_(N_FRAME_); // AD の結果を保存するダブル・バッファ
+DoubleBuffer buf_(N_SMPL_); // ダウンサンプリングの結果を保存するダブル・バッファ
// ADC 変換終了割り込みに対する割り込みサービス・ルーチン
void AdcIsr()
@@ -56,15 +55,12 @@
int main()
{
- // FFT によるスペクトル解析オブジェクトの生成
- FftSpectropgram analyzer(N_DATA_, N_FFT_);
- float empha; // 高域強調器の係数
+ SerialRxTxIntr rxTx; // PC との通信用
+ XferSpectrum tx(rxTx, N_TX_); // PC に転送するためのオブジェクトの生成
+ FftSpectropgram analyzer(N_FFT_); // スペクトログラムで使うオブジェクトの生成
- SerialRxTxIntr rxTx; // PC との通信用
- XferSpectrum tx(rxTx, N_TX_); // PC に転送するためのオブジェクトの生成
-
- Array<float> sn(N_FFT_+1, 0.0f); // スペクトル解析の対象となるデータ
- Array<float> absFt(N_FRAME_); // 解析結果:スペクトルの絶対値
+ Array<float> sn(N_FFT_, 0.0f); // スペクトル解析の対象となるデータ
+ Array<float> absFt(N_SPC_); // 解析結果:スペクトルの絶対値
NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高
NVIC_SetPriority(USART2_IRQn, 1);
@@ -85,16 +81,9 @@
wait_ms(10);
rxTx.Baud(460800); // 以降は 460,800 baud
}
- else if (str.substr(0, 2) == "GO")
+ if (str.substr(0, 2) == "GO")
{
- // str の内容
- // [0] 'G'
- // [1] 'O'
- // [2] 高域強調の有無:'Y', 'N'
-
- if (str[2] == 'Y') empha = 1.0f; // 高域強調は有効
- else empha = 0; // 高域強調は無効
-
+ analyzer.SwEmphasis(str[2] == 'Y');
okGo = true; // データの転送要求あり
}
}
@@ -102,15 +91,14 @@
if (buf_.IsFull()) // 入力データが満杯の場合,以下の処理を行う
{
// フレームの後半のデータを前半に移動する
- for (int n=0; n<N_FFT_2_; n++)
- sn[n] = sn[n+N_FRAME_];
+ for (int n=0; n<N_SMPL_; n++)
+ sn[n] = sn[n+N_SMPL_];
// フレームの後半には新しいデータを格納する
- for (int n=0; n<N_FRAME_; n++)
- sn[n+N_FFT_2_] = buf_.Get(n);
+ for (int n=0; n<N_SMPL_; n++)
+ sn[n+N_SMPL_] = buf_.Get(n);
- analyzer.SetHighEmphasizer(empha); // 高域強調の有無の指令
- analyzer.Execute(sn, absFt); // スペクトル解析の実行
- ready = true; // スペクトル解析終了
+ analyzer.Execute(sn, absFt); // スペクトル解析の実行
+ ready = true; // スペクトル解析終了
}
// 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する