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

Committer:
MikamiUitOpen
Date:
Sun Nov 24 11:14:01 2019 +0000
Revision:
7:5ba884060d3b
Parent:
6:c38ec7939609
8

Who changed what in which revision?

UserRevisionLine numberNew 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 }