![](/media/cache/img/default_profile.jpg.50x50_q85.jpg)
Realtime sound spectrogram using FFT or linear prediction. Spectrogram is displayed on the display of PC. リアルタイム・スペクトログラム.解析の手法:FFT,線形予測法.スペクトログラムは PC のディスプレー装置に表示される.PC 側のプログラム:F446_Spectrogram.
Dependencies: Array_Matrix mbed SerialTxRxIntr F446_AD_DA UIT_FFT_Real
main.cpp@7:5ba884060d3b, 2019-11-24 (annotated)
- Committer:
- MikamiUitOpen
- Date:
- Sun Nov 24 11:14:01 2019 +0000
- Revision:
- 7:5ba884060d3b
- Parent:
- 6:c38ec7939609
8
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
MikamiUitOpen | 0:a539141b9dec | 1 | //--------------------------------------------------------------------- |
MikamiUitOpen | 3:74a50c14d3fd | 2 | // スペクトログラム (Nucleo-F446RE 用) |
MikamiUitOpen | 0:a539141b9dec | 3 | // |
MikamiUitOpen | 0:a539141b9dec | 4 | // ● ST-Link Firmware の V2.J28.M16 で動作確認 |
MikamiUitOpen | 0:a539141b9dec | 5 | // |
MikamiUitOpen | 0:a539141b9dec | 6 | // ● ST-Link Firmware のアップグレードには stsw-link07.zip |
MikamiUitOpen | 0:a539141b9dec | 7 | // に含まれている "ST-LinkUpgrade.exe" を使う |
MikamiUitOpen | 0:a539141b9dec | 8 | // |
MikamiUitOpen | 0:a539141b9dec | 9 | // ● PC 側のプログラム: "F446_Spectrogram" |
MikamiUitOpen | 0:a539141b9dec | 10 | // ● ボーレート: 460800 baud |
MikamiUitOpen | 0:a539141b9dec | 11 | // ● 受信データの文字列の終了マーク: "\r" |
MikamiUitOpen | 0:a539141b9dec | 12 | // |
MikamiUitOpen | 4:fe1885675421 | 13 | // ● 入力 A0: 左チャンネル,A1 右チャンネル |
MikamiUitOpen | 4:fe1885675421 | 14 | // ● 出力 A2: 左チャンネル,D13 右チャンネル |
MikamiUitOpen | 4:fe1885675421 | 15 | // 入力をそのまま出力する |
MikamiUitOpen | 4:fe1885675421 | 16 | // |
MikamiUitOpen | 7:5ba884060d3b | 17 | // 2018/11/24, Copyright (c) 2018 MIKAMI, Naoki |
MikamiUitOpen | 0:a539141b9dec | 18 | //--------------------------------------------------------------------- |
MikamiUitOpen | 0:a539141b9dec | 19 | |
MikamiUitOpen | 0:a539141b9dec | 20 | #include "mbed.h" |
MikamiUitOpen | 0:a539141b9dec | 21 | #include <string> |
MikamiUitOpen | 0:a539141b9dec | 22 | #include "Array.hpp" |
MikamiUitOpen | 0:a539141b9dec | 23 | #include "F446_ADC_Interrupt.hpp" |
MikamiUitOpen | 0:a539141b9dec | 24 | #include "FFT_Analyzer.hpp" |
MikamiUitOpen | 0:a539141b9dec | 25 | #include "LPC_Analyzer.hpp" |
MikamiUitOpen | 7:5ba884060d3b | 26 | #include "DoubleBufferMatrix.hpp" |
MikamiUitOpen | 7:5ba884060d3b | 27 | #include "Xfer.hpp" |
MikamiUitOpen | 0:a539141b9dec | 28 | using namespace Mikami; |
MikamiUitOpen | 0:a539141b9dec | 29 | |
MikamiUitOpen | 0:a539141b9dec | 30 | #ifndef __STM32F446xx_H |
MikamiUitOpen | 0:a539141b9dec | 31 | #error "Use Nucleo-F446RE" |
MikamiUitOpen | 0:a539141b9dec | 32 | #endif |
MikamiUitOpen | 0:a539141b9dec | 33 | |
MikamiUitOpen | 0:a539141b9dec | 34 | const int N_FFT_ = 512; // FFT の点数 |
MikamiUitOpen | 0:a539141b9dec | 35 | const int N_DATA_ = N_FFT_ + 1; // スペクトル解析に使うデータ数(差分処理を考慮) |
MikamiUitOpen | 0:a539141b9dec | 36 | const int N_FRAME_ = N_FFT_/2 + 1; // 1フレーム当たり標本化するデータ数 |
MikamiUitOpen | 0:a539141b9dec | 37 | const int N_FFT_2_ = N_FFT_/2; // FFT の点数の半分 |
MikamiUitOpen | 0:a539141b9dec | 38 | |
MikamiUitOpen | 0:a539141b9dec | 39 | const int FS_ = 16000; // 標本化周波数: 16 kHz |
MikamiUitOpen | 0:a539141b9dec | 40 | AdcDual_Intr myAdc_(FS_); // "F446_ADC_Interrupt.hpp" で定義 |
MikamiUitOpen | 4:fe1885675421 | 41 | DacDual myDac_; // "F446_DAC.cpp/hpp" で定義 |
MikamiUitOpen | 7:5ba884060d3b | 42 | DoubleBuffer<float> buf_(N_FRAME_); // AD の結果を保存するダブル・バッファ |
MikamiUitOpen | 0:a539141b9dec | 43 | |
MikamiUitOpen | 0:a539141b9dec | 44 | // 入力チャンネルを選択する関数とそれを割り当てる関数ポインタ |
MikamiUitOpen | 0:a539141b9dec | 45 | float InputL(float x1, float x2) { return x1; } |
MikamiUitOpen | 0:a539141b9dec | 46 | float InputR(float x1, float x2) { return x2; } |
MikamiUitOpen | 0:a539141b9dec | 47 | float InputLR(float x1, float x2) { return (x1 + x2)/2; } |
MikamiUitOpen | 0:a539141b9dec | 48 | typedef float (*FP_INPUT)(float, float); |
MikamiUitOpen | 0:a539141b9dec | 49 | FP_INPUT InputCurrent = InputLR; // 最初は左右チャンネルを使う |
MikamiUitOpen | 0:a539141b9dec | 50 | FP_INPUT InputNew = InputCurrent; |
MikamiUitOpen | 0:a539141b9dec | 51 | |
MikamiUitOpen | 0:a539141b9dec | 52 | // ADC 変換終了割り込みに対する割り込みサービス・ルーチン |
MikamiUitOpen | 0:a539141b9dec | 53 | void AdcIsr() |
MikamiUitOpen | 0:a539141b9dec | 54 | { |
MikamiUitOpen | 7:5ba884060d3b | 55 | float sn1, sn2; |
MikamiUitOpen | 0:a539141b9dec | 56 | myAdc_.Read(sn1, sn2); |
MikamiUitOpen | 7:5ba884060d3b | 57 | float xn = InputCurrent(sn1, sn2); |
MikamiUitOpen | 7:5ba884060d3b | 58 | buf_.Store(xn); // バッファへ格納 |
MikamiUitOpen | 0:a539141b9dec | 59 | myDac_.Write(xn, xn); |
MikamiUitOpen | 0:a539141b9dec | 60 | |
MikamiUitOpen | 7:5ba884060d3b | 61 | if (buf_.IsFullSwitch()) // バッファが満杯であればバッファを切り替える |
MikamiUitOpen | 7:5ba884060d3b | 62 | InputCurrent = InputNew; // 入力の切り替え |
MikamiUitOpen | 0:a539141b9dec | 63 | } |
MikamiUitOpen | 0:a539141b9dec | 64 | |
MikamiUitOpen | 0:a539141b9dec | 65 | int main() |
MikamiUitOpen | 0:a539141b9dec | 66 | { |
MikamiUitOpen | 7:5ba884060d3b | 67 | // FFT によるスペクトル解析オブジェクトの生成 |
MikamiUitOpen | 7:5ba884060d3b | 68 | FftAnalyzer *fftAnlz_ = new FftAnalyzer(N_DATA_, N_FFT_); |
MikamiUitOpen | 7:5ba884060d3b | 69 | // 線形予測法 によるスペクトル解析オブジェクトの生成 |
MikamiUitOpen | 7:5ba884060d3b | 70 | LpcAnalyzer *lpcAnlz_ = new LpcAnalyzer(N_DATA_, N_FFT_, 20); |
MikamiUitOpen | 7:5ba884060d3b | 71 | AnalyzerBase *analyzer = fftAnlz_; // 最初は FFT を使う |
MikamiUitOpen | 7:5ba884060d3b | 72 | float empha = 1.0f; // 高域強調器の係数 |
MikamiUitOpen | 7:5ba884060d3b | 73 | |
MikamiUitOpen | 7:5ba884060d3b | 74 | SerialRxTxIntr rxTx(32, 115200*4); // PC との通信用 |
MikamiUitOpen | 7:5ba884060d3b | 75 | Xfer tx(rxTx, N_FFT_/2+1); // PC に転送するためのオブジェクトの生成 |
MikamiUitOpen | 7:5ba884060d3b | 76 | |
MikamiUitOpen | 7:5ba884060d3b | 77 | Array<float> sn(N_FFT_, 0.0f); // スペクトル解析の対象となるデータ |
MikamiUitOpen | 7:5ba884060d3b | 78 | Array<float> db(N_FRAME_); // 解析結果:対数スペクトル [dB] |
MikamiUitOpen | 0:a539141b9dec | 79 | |
MikamiUitOpen | 4:fe1885675421 | 80 | NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高 |
MikamiUitOpen | 4:fe1885675421 | 81 | NVIC_SetPriority(USART2_IRQn, 1); |
MikamiUitOpen | 0:a539141b9dec | 82 | |
MikamiUitOpen | 4:fe1885675421 | 83 | float levelShift = 20; // dB 計算の際のシフト量の初期値 |
MikamiUitOpen | 0:a539141b9dec | 84 | |
MikamiUitOpen | 7:5ba884060d3b | 85 | bool ready = false; // スペクトルの計算終了で true |
MikamiUitOpen | 7:5ba884060d3b | 86 | bool okGo = false; // "GO" を受信したら true |
MikamiUitOpen | 4:fe1885675421 | 87 | |
MikamiUitOpen | 4:fe1885675421 | 88 | myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て |
MikamiUitOpen | 0:a539141b9dec | 89 | while (true) |
MikamiUitOpen | 0:a539141b9dec | 90 | { |
MikamiUitOpen | 1:cc596a8d40c9 | 91 | // PC からのコマンドの解析 |
MikamiUitOpen | 7:5ba884060d3b | 92 | if (rxTx.IsEol()) // 受信バッファのデータが有効になった場合の処理 |
MikamiUitOpen | 0:a539141b9dec | 93 | { |
MikamiUitOpen | 7:5ba884060d3b | 94 | string str = rxTx.GetBuffer(); |
MikamiUitOpen | 5:fcc1b0b4737e | 95 | if (str == "Spectrogram") |
MikamiUitOpen | 7:5ba884060d3b | 96 | rxTx.Tx("ACK\n"); // PC からの "Spectrogram" に対して "ACK" を送信する |
MikamiUitOpen | 4:fe1885675421 | 97 | else if (str.substr(0, 2) == "GO") |
MikamiUitOpen | 0:a539141b9dec | 98 | { |
MikamiUitOpen | 4:fe1885675421 | 99 | // str の内容 |
MikamiUitOpen | 0:a539141b9dec | 100 | // [0] 'G' |
MikamiUitOpen | 0:a539141b9dec | 101 | // [1] 'O' |
MikamiUitOpen | 0:a539141b9dec | 102 | // [2] 入力チャンネルの選択:'L', 'R', or '+' |
MikamiUitOpen | 0:a539141b9dec | 103 | // [3] スペクトルの値のレベルシフト:' ' ~ 'I' が -20 ~ 20 に対応 |
MikamiUitOpen | 0:a539141b9dec | 104 | // [4] 高域強調器の有無:'Y', 'N' |
MikamiUitOpen | 0:a539141b9dec | 105 | // [5] 解析方法 F: FFT,L: 線形予測法 |
MikamiUitOpen | 0:a539141b9dec | 106 | |
MikamiUitOpen | 4:fe1885675421 | 107 | switch (str[2]) |
MikamiUitOpen | 0:a539141b9dec | 108 | { |
MikamiUitOpen | 0:a539141b9dec | 109 | case 'L': InputNew = InputL; break; |
MikamiUitOpen | 0:a539141b9dec | 110 | case 'R': InputNew = InputR; break; |
MikamiUitOpen | 0:a539141b9dec | 111 | case '+': InputNew = InputLR; break; |
MikamiUitOpen | 0:a539141b9dec | 112 | default : InputNew = InputLR; break; |
MikamiUitOpen | 0:a539141b9dec | 113 | } |
MikamiUitOpen | 0:a539141b9dec | 114 | |
MikamiUitOpen | 4:fe1885675421 | 115 | levelShift = (float)(str[3] - ' '); // dB 計算の際のシフト量 |
MikamiUitOpen | 0:a539141b9dec | 116 | |
MikamiUitOpen | 7:5ba884060d3b | 117 | if (str[4] == 'Y') empha = 1.0f; // 高域強調器は有 |
MikamiUitOpen | 7:5ba884060d3b | 118 | else empha = 0; // 高域強調器は無 |
MikamiUitOpen | 0:a539141b9dec | 119 | |
MikamiUitOpen | 7:5ba884060d3b | 120 | if (str[5] == 'F') analyzer = fftAnlz_; // FFT |
MikamiUitOpen | 7:5ba884060d3b | 121 | else analyzer = lpcAnlz_; // 線形予測法 |
MikamiUitOpen | 0:a539141b9dec | 122 | |
MikamiUitOpen | 0:a539141b9dec | 123 | okGo = true; // データの転送要求あり |
MikamiUitOpen | 0:a539141b9dec | 124 | } |
MikamiUitOpen | 0:a539141b9dec | 125 | } |
MikamiUitOpen | 0:a539141b9dec | 126 | |
MikamiUitOpen | 7:5ba884060d3b | 127 | if (buf_.IsFull()) // 入力データが満杯の場合,以下の処理を行う |
MikamiUitOpen | 0:a539141b9dec | 128 | { |
MikamiUitOpen | 0:a539141b9dec | 129 | // フレームの後半のデータを前半に移動する |
MikamiUitOpen | 0:a539141b9dec | 130 | for (int n=0; n<N_FFT_2_; n++) |
MikamiUitOpen | 0:a539141b9dec | 131 | sn[n] = sn[n+N_FRAME_]; |
MikamiUitOpen | 0:a539141b9dec | 132 | // フレームの後半には新しいデータを格納する |
MikamiUitOpen | 0:a539141b9dec | 133 | for (int n=0; n<N_FRAME_; n++) |
MikamiUitOpen | 7:5ba884060d3b | 134 | sn[n+N_FFT_2_] = buf_.Get(n); |
MikamiUitOpen | 0:a539141b9dec | 135 | |
MikamiUitOpen | 7:5ba884060d3b | 136 | analyzer->SetHighEmphasizer(empha); // 高域強調の有無の指令 |
MikamiUitOpen | 7:5ba884060d3b | 137 | analyzer->Execute(sn, db); // スペクトル解析の実行 |
MikamiUitOpen | 7:5ba884060d3b | 138 | tx.Convert(db, levelShift); // スペクトル解析の結果を転送する形式に変換 |
MikamiUitOpen | 7:5ba884060d3b | 139 | ready = true; // スペクトル解析終了 |
MikamiUitOpen | 0:a539141b9dec | 140 | } |
MikamiUitOpen | 0:a539141b9dec | 141 | |
MikamiUitOpen | 0:a539141b9dec | 142 | // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する |
MikamiUitOpen | 0:a539141b9dec | 143 | if (okGo && ready) |
MikamiUitOpen | 0:a539141b9dec | 144 | { |
MikamiUitOpen | 7:5ba884060d3b | 145 | tx.ToPC(); // データを PC へ転送 |
MikamiUitOpen | 0:a539141b9dec | 146 | ready = false; |
MikamiUitOpen | 0:a539141b9dec | 147 | okGo = false; |
MikamiUitOpen | 0:a539141b9dec | 148 | } |
MikamiUitOpen | 0:a539141b9dec | 149 | } |
MikamiUitOpen | 0:a539141b9dec | 150 | } |