Synthesizer for Japanese five vowels with keyboard. 鍵盤と一緒になった日本語の5母音の合成器.
Dependencies: BSP_DISCO_F746NG_patch_fixed BUTTON_GROUP LCD_DISCO_F746NG TS_DISCO_F746NG mbed
main.cpp
- Committer:
- MikamiUitOpen
- Date:
- 2016-02-24
- Revision:
- 0:a98746e7a170
File content as of revision 0:a98746e7a170:
//------------------------------------------------------------ // 合成母音発生器+キーボード // Vowel synthesizer with keyboard // タッチしている母音に対応する音が出る // 黒鍵はサポートしていない // // 2016/02/24, Copyright (c) 2016 MIKAMI, Naoki //------------------------------------------------------------ #include "button_group.hpp" #include "sai_io_o.hpp" #include "Rosenberg.hpp" // 合成声帯波用 #include "Resonator.hpp" // 共振器用 #include "Radiator.hpp" // 放射の効果用 using namespace Mikami; const uint32_t N_DATA_ = 300;//1400; SaiIO_O mySai_(N_DATA_, I2S_AUDIOFREQ_16K); const int N_VWL_ = 5; // 母音の種類の数 const int N_RSN_ = 3; // 共振器の数 // フォルマント周波数,帯域幅のデータ:{周波数, 帯域幅} const Resonator::FrBw FORMANT_[N_VWL_][N_RSN_] = {{ {654, 50}, {1060, 55}, {2375, 60} }, // ア { {302, 40}, {2057, 60}, {3004, 65} }, // イ { {375, 45}, {1208, 55}, {2165, 60} }, // ウ { {541, 50}, {1784, 60}, {2452, 60} }, // エ { {458, 45}, { 807, 50}, {2379, 60} }}; // オ int main() { const float FS = I2S_AUDIOFREQ_16K; // 標本化周波数: 16 kHz const float F0 = 125.0f; // 基本周波数:125 Hz const float A0 = 10000.0f; // 声帯波の振幅 const float A0M[N_VWL_] = // 声帯波の倍率 { 1.0f, 3.0f, 2.0f, 1.0f, 1.0f }; Rosenberg gs(F0, FS, A0); // 声帯波発生用オブジェクト初期化 Resonator rs[N_RSN_]; // 共振器用オブジェクト配列の宣言 Radiator rd(0.8f); // 放射の効果用オブジェクトの初期化 LCD_DISCO_F746NG lcd; // LCD 用オブジェクト const uint32_t BACK_COLOR = 0xFF006A6C; // Teal green const uint32_t TOUCHED_COLOR = 0xFF7F7FFF; const uint32_t ORIGINAL_COLOR = 0xFF0068B7; lcd.Clear(BACK_COLOR); lcd.SetBackColor(BACK_COLOR); lcd.SetTextColor(LCD_COLOR_WHITE); lcd.SetFont(&Font20); lcd.DisplayStringAt(0, 10, (uint8_t *)"Vowel Synthesizer", CENTER_MODE); TS_DISCO_F746NG ts; // タッチパネル用オブジェクト const string FIVE_VOEWLS[N_VWL_] = {"a", "i", "u", "e", "o"}; ButtonGroup vowel(lcd, ts, 10, 40, 50, 40, ORIGINAL_COLOR, BACK_COLOR, N_VWL_, FIVE_VOEWLS, 0, 5, 1, Font20); vowel.Draw(0, TOUCHED_COLOR); // 白鍵用 const string NO_CHAR[8] = {"", "", "", "", "", "", "", ""}; const int X0S = 90; const int Y0S = 120; const int WIDTH = 43; ButtonGroup scale(lcd, ts, X0S, Y0S, WIDTH, 140, LCD_COLOR_WHITE, BACK_COLOR, 8, NO_CHAR, 5, 0, 8); const float F_DO = 110.0f*powf(2, 3.0f/12.0f); const float F_OCTAVE[8] = { F_DO, F_DO*powf(2, 2.0f/12.0f), F_DO*powf(2, 4.0f/12.0f), F_DO*powf(2, 5.0f/12.0f), F_DO*powf(2, 7.0f/12.0f), F_DO*powf(2, 9.0f/12.0f), F_DO*powf(2, 11.0f/12.0f), F_DO*2}; // 黒鍵用(音は出ない) const int H0 = 70; const int X0B = X0S+WIDTH/2+5; const int WB = WIDTH-5; const int MPOS = WIDTH + 5; lcd.SetTextColor(LCD_COLOR_BLACK); lcd.FillRect(X0B, Y0S, WB, H0); lcd.FillRect(X0B+MPOS, Y0S, WB, H0); lcd.FillRect(X0B+MPOS*3, Y0S, WB, H0); lcd.FillRect(X0B+MPOS*4, Y0S, WB, H0); lcd.FillRect(X0B+MPOS*5, Y0S, WB, H0); // 男声,女声 const string MF[2] ={"M", "F"}; ButtonGroup mf(lcd, ts, X0S, 40, 60, 40, ORIGINAL_COLOR, BACK_COLOR, 2, MF, 5, 0, 2, Font20); mf.Draw(0, TOUCHED_COLOR); mySai_.InitCodecOut(); mySai_.OutPause(); float f0 = 1; int mf0 = -1; int sw0 = -1; // 共振器の準備 for (int k=0; k<N_RSN_; k++) rs[k] = Resonator(FORMANT_[0][k], FS); // 声帯波の振幅設定 gs.SetAmplitude(A0*A0M[0]); int dore0 = -1; while (true) { int mfNow; if (mf.GetTouchedNumber(mfNow, TOUCHED_COLOR)) { if (mfNow != mf0) { // 男声,女声の切り替え f0 = (mfNow == 0) ? 1.0f : 2.0f; mf0 = mfNow; } } int sw; if (vowel.GetTouchedNumber(sw, TOUCHED_COLOR)) { if (sw != sw0) { // 共振器の準備 for (int k=0; k<N_RSN_; k++) rs[k] = Resonator(FORMANT_[sw][k], FS); // 声帯波の振幅設定 gs.SetAmplitude(A0*A0M[sw]); sw0 = sw; } } int dore; if (scale.GetTouchedNumber(dore)) // キーがタッチされている場合 { if (dore != dore0) // タッチするキーが変わった場合 { // 音階に対応する基本周期に設定 gs.SetPeriod(F_OCTAVE[dore]*f0); dore0 = dore; mySai_.OutResume(); } if (mySai_.IsXferred()) { for (int n=0; n<mySai_.GetLength(); n++) { float gn = gs.Execute(); // 合成声帯波発生 float vn = gn; // 声帯波を声道へ入力 for (int k=0; k<N_RSN_; k++) vn = rs[k].Execute(vn); // 声道の効果 float yn = rd.Execute(vn); // 放射の効果 mySai_.Output(yn, gn); } mySai_.ResetXferred(); } } else // キーがタッチされていない場合 { mySai_.OutPause(); mySai_.ClearOutBuffer(); dore0 = -1; } } }