
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
Revision 4:fe1885675421, committed 2018-07-23
- Comitter:
- MikamiUitOpen
- Date:
- Mon Jul 23 05:53:29 2018 +0000
- Parent:
- 3:74a50c14d3fd
- Child:
- 5:fcc1b0b4737e
- Commit message:
- 5
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialTxRxIntr.lib Mon Jul 23 05:53:29 2018 +0000 @@ -0,0 +1,1 @@ +http://os.mbed.com/users/MikamiUitOpen/code/SerialTxRxIntr/#f6e15c19dd75
--- a/main.cpp Wed Mar 08 09:57:41 2017 +0000 +++ b/main.cpp Mon Jul 23 05:53:29 2018 +0000 @@ -10,12 +10,16 @@ // ● ボーレート: 460800 baud // ● 受信データの文字列の終了マーク: "\r" // -// 2017/03/08, 三上 直樹 +// ● 入力 A0: 左チャンネル,A1 右チャンネル +// ● 出力 A2: 左チャンネル,D13 右チャンネル +// 入力をそのまま出力する +// +// 2018/07/23, Copyright (c) 2018 MIKAMI, Naoki //--------------------------------------------------------------------- #include "mbed.h" #include <string> -#include "myFunctions.hpp" +#include "myFunction.hpp" #include "Array.hpp" #include "F446_ADC_Interrupt.hpp" #include "FFT_Analyzer.hpp" @@ -43,7 +47,7 @@ const int FS_ = 16000; // 標本化周波数: 16 kHz AdcDual_Intr myAdc_(FS_); // "F446_ADC_Interrupt.hpp" で定義 -DacDual myDac_; // "F446_DAC" で定義 +DacDual myDac_; // "F446_DAC.cpp/hpp" で定義 // FFT によるスペクトル解析オブジェクトの生成 FftAnalyzer *fftAnlz_ = new FftAnalyzer(N_DATA_, N_FFT_); @@ -51,18 +55,10 @@ LpcAnalyzer *lpcAnlz_ = new LpcAnalyzer(N_DATA_, N_FFT_, 20); AnalyzerBase *analyzer_ = fftAnlz_; // 最初は FFT を使う -Serial pc_(USBTX, USBRX); // PC との通信で使うオブジェクト -DigitalOut myLed_(D10, 1); // LED1 が使えないので D10 を使う +SerialRxTxIntr rxTx_(32, 115200*4); // PC との通信用 -const int DATA_SIZE_ = N_FFT_/2 + 1; -Array<uint16_t> txData_(DATA_SIZE_); // 送信用データ -string rxBuffer_; // 受信バッファ - -float levelShift_ = 20; // dB 計算の際のシフト量の初期値 float empha_ = 1.0f; // 高域強調器の係数 -__IO bool eol_; // "\r" を受信した場合に true - // 入力チャンネルを選択する関数とそれを割り当てる関数ポインタ float InputL(float x1, float x2) { return x1; } float InputR(float x1, float x2) { return x2; } @@ -93,37 +89,34 @@ int main() { + const int DATA_SIZE = N_FFT_/2 + 1; + Array<uint16_t> txData(DATA_SIZE); // 送信用データ float sn[N_DATA_]; // スペクトル解析の対象となるデータ float db[N_FRAME_]; // 解析結果である対数スペクトル [dB] for (int n=0; n<N_DATA_; n++) sn[n] = 0; for (int n=0; n<N_FRAME_; n++) xPong_[n] = 2048; // uint16_t 型の 0 に対応 - rxBuffer_ = ""; // 受信バッファのクリア - eol_ = false; + NVIC_SetPriority(ADC_IRQn, 0); // AD変換終了割り込みの優先度が最高 + NVIC_SetPriority(USART2_IRQn, 1); - pc_.baud(115200*4); // ボーレートの設定 - pc_.format(); // default: 8 bits, nonparity, 1 stop bit - - NVIC_SetPriority(ADC_IRQn, 1); // AD変換終了割り込みの優先度が最高 - NVIC_SetPriority(USART2_IRQn, 2); - - pc_.attach(&Rx); // 受信割り込みの割り当て + float levelShift = 20; // dB 計算の際のシフト量の初期値 full_ = false; - myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て - __IO bool ready = false; // スペクトルの計算終了で true __IO bool okGo = false; // "GO" を受信したら true + + myAdc_.SetIntrVec(&AdcIsr); // AD変換終了割り込みの割り当て while (true) { // PC からのコマンドの解析 - if (eol_) + if (rxTx_.IsEol()) // 受信バッファのデータが有効になった場合の処理 { - if (rxBuffer_.find("ENQ") != string::npos) - pc_.printf("ACK\n"); // "ACK" を PC へ転送 - else if (rxBuffer_.find("GO") != string::npos) + string str = rxTx_.GetBuffer(); + if (str.substr(0, 3) == "ENQ") + rxTx_.Tx("ACK"); + else if (str.substr(0, 2) == "GO") { - // rxBuffer_ の内容 + // str の内容 // [0] 'G' // [1] 'O' // [2] 入力チャンネルの選択:'L', 'R', or '+' @@ -131,7 +124,7 @@ // [4] 高域強調器の有無:'Y', 'N' // [5] 解析方法 F: FFT,L: 線形予測法 - switch (rxBuffer_[2]) // 'L', 'R', or '+' + switch (str[2]) { case 'L': InputNew = InputL; break; case 'R': InputNew = InputR; break; @@ -139,20 +132,16 @@ default : InputNew = InputLR; break; } - levelShift_ = (float)(rxBuffer_[3] - ' '); // dB 計算の際のシフト量 + levelShift = (float)(str[3] - ' '); // dB 計算の際のシフト量 - if (rxBuffer_[4] == 'Y') empha_ = 1.0f; // 高域強調器は有 - else empha_ = 0; // 高域強調器は無 + if (str[4] == 'Y') empha_ = 1.0f; // 高域強調器は有 + else empha_ = 0; // 高域強調器は無 - if (rxBuffer_[5] == 'F') analyzer_ = fftAnlz_; // FFT - else analyzer_ = lpcAnlz_; // 線形予測法 + if (str[5] == 'F') analyzer_ = fftAnlz_; // FFT + else analyzer_ = lpcAnlz_; // 線形予測法 okGo = true; // データの転送要求あり } - - eol_ = false; - rxBuffer_ = ""; // 受信バッファのクリア - wait_ms(1); } if (full_) // 入力データが満杯かどうか調べる @@ -170,13 +159,13 @@ analyzer_->Execute(sn, db); // スペクトル解析の実行 const float FACTOR = 10000.0f/80.0f; // 表示範囲: 0 ~ 80 dB - for (int n=0; n<DATA_SIZE_; n++) + for (int n=0; n<DATA_SIZE; n++) { - float xDb = FACTOR*(db[n] + 30.0f + levelShift_); + float xDb = FACTOR*(db[n] + 30.0f + levelShift); if (xDb > 10000.0f) xDb = 10000.0f; if (xDb < 0.0f) xDb = 0.0f; uint16_t spc = (uint16_t)xDb; - txData_[n] = spc; + txData[n] = spc; } ready = true; // スペクトル解析終了 } @@ -184,9 +173,10 @@ // 転送要求がありスペクトル解析が終了している場合にデータを PC へ転送する if (okGo && ready) { - Xfer(txData_); // データを PC へ転送 + Xfer(txData); // データを PC へ転送 ready = false; okGo = false; } } } +
--- a/mbed.bld Wed Mar 08 09:57:41 2017 +0000 +++ b/mbed.bld Mon Jul 23 05:53:29 2018 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/e1686b8d5b90 \ No newline at end of file +http://mbed.org/users/mbed_official/code/mbed/builds/a7c7b631e539 \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/myFunction.hpp Mon Jul 23 05:53:29 2018 +0000 @@ -0,0 +1,31 @@ +//--------------------------------------------------------------------- +// データを PC へ転送 +// +// 2018/07/23, Copyright (c) 2018 MIKAMI, Naoki +//--------------------------------------------------------------------- + +#include <string> +#include "Array.hpp" +#include "SerialRxTxIntr.hpp" +using namespace Mikami; + +#ifndef MY_FUNCTION_XFER_HPP +#define MY_FUNCTION_XFER_HPP + +extern SerialRxTxIntr rxTx_; + +// データを PC へ転送(0 ~ 10,000 の範囲の値を 2 文字で表すコード化を利用) +void Xfer(Array<uint16_t> &xn) +{ + string str = ""; + for (int n=0; n<xn.Length(); n++) + { + div_t a = div(xn[n], 100); + str += a.quot + 0x10; + str += a.rem + 0x10; + } + rxTx_.Tx(str); + rxTx_.Tx("EOT"); +} + +#endif // MY_FUNCTION_XFER_HPP
--- a/myFunctions.cpp Wed Mar 08 09:57:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -#include "myFunctions.hpp" - -// シリアル・ポートの受信割り込み -void Rx() -{ - unsigned char chr = pc_.getc(); - // '\r' を受信した場合はメッセージの終了とする - // '\r' は,rxBuffer_ には追加されない - if (chr == '\r') eol_ = true; - else rxBuffer_ += chr; // '\r' が来るまで文字が追加される - - // 受信するメッセージの文字数のチェック - if (rxBuffer_.size() > RX_MAX_) - while (true) // 文字数がオーバーの場合 LED が点滅する - { - myLed_ = !myLed_; - wait(0.1f); - } -} - -// データを PC へ転送(0 ~ 10,000 の範囲の値を 2 文字で表すコード化を利用) -void Xfer(Array<uint16_t> &xn) -{ - for (int n=0; n<xn.Length(); n++) - { - div_t a = div(xn[n], 100); - pc_.putc(a.quot + 0x10); - pc_.putc(a.rem + 0x10); - } - pc_.printf("\n"); // データの最後を通知 - wait_ms(1); // これは必須 - pc_.printf("EOT\n"); // 転送終了であることを送信 -}
--- a/myFunctions.hpp Wed Mar 08 09:57:41 2017 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,22 +0,0 @@ -#include "mbed.h" -#include <string> -#include "Array.hpp" -using namespace Mikami; - -#ifndef MY_FUNCTIONS_HPP -#define MY_FUNCTIONS_HPP - -const int RX_MAX_ = 32; // 受信バッファの文字数の最大値 - -extern string rxBuffer_; // 受信バッファ -extern __IO bool eol_; // "\r" を受信した場合に true - -extern Serial pc_; -extern DigitalOut myLed_; - -// シリアル・ポートの受信割り込み -void Rx(); -// データを PC へ転送 -void Xfer(Array<uint16_t> &xn); - -#endif // MY_FUNCTIONS_HPP