Synthesizer for Japanese five vowels with keyboard. 鍵盤と一緒になった日本語の5母音の合成器.

Dependencies:   BSP_DISCO_F746NG_patch_fixed BUTTON_GROUP LCD_DISCO_F746NG TS_DISCO_F746NG mbed

Committer:
MikamiUitOpen
Date:
Wed Feb 24 13:00:12 2016 +0000
Revision:
0:a98746e7a170
1

Who changed what in which revision?

UserRevisionLine numberNew contents of line
MikamiUitOpen 0:a98746e7a170 1 //------------------------------------------------------------
MikamiUitOpen 0:a98746e7a170 2 // 合成母音発生器+キーボード
MikamiUitOpen 0:a98746e7a170 3 // Vowel synthesizer with keyboard
MikamiUitOpen 0:a98746e7a170 4 // タッチしている母音に対応する音が出る
MikamiUitOpen 0:a98746e7a170 5 // 黒鍵はサポートしていない
MikamiUitOpen 0:a98746e7a170 6 //
MikamiUitOpen 0:a98746e7a170 7 // 2016/02/24, Copyright (c) 2016 MIKAMI, Naoki
MikamiUitOpen 0:a98746e7a170 8 //------------------------------------------------------------
MikamiUitOpen 0:a98746e7a170 9
MikamiUitOpen 0:a98746e7a170 10 #include "button_group.hpp"
MikamiUitOpen 0:a98746e7a170 11 #include "sai_io_o.hpp"
MikamiUitOpen 0:a98746e7a170 12 #include "Rosenberg.hpp" // 合成声帯波用
MikamiUitOpen 0:a98746e7a170 13 #include "Resonator.hpp" // 共振器用
MikamiUitOpen 0:a98746e7a170 14 #include "Radiator.hpp" // 放射の効果用
MikamiUitOpen 0:a98746e7a170 15
MikamiUitOpen 0:a98746e7a170 16 using namespace Mikami;
MikamiUitOpen 0:a98746e7a170 17
MikamiUitOpen 0:a98746e7a170 18 const uint32_t N_DATA_ = 300;//1400;
MikamiUitOpen 0:a98746e7a170 19
MikamiUitOpen 0:a98746e7a170 20 SaiIO_O mySai_(N_DATA_, I2S_AUDIOFREQ_16K);
MikamiUitOpen 0:a98746e7a170 21
MikamiUitOpen 0:a98746e7a170 22 const int N_VWL_ = 5; // 母音の種類の数
MikamiUitOpen 0:a98746e7a170 23 const int N_RSN_ = 3; // 共振器の数
MikamiUitOpen 0:a98746e7a170 24
MikamiUitOpen 0:a98746e7a170 25 // フォルマント周波数,帯域幅のデータ:{周波数, 帯域幅}
MikamiUitOpen 0:a98746e7a170 26 const Resonator::FrBw FORMANT_[N_VWL_][N_RSN_] =
MikamiUitOpen 0:a98746e7a170 27 {{ {654, 50}, {1060, 55}, {2375, 60} }, // ア
MikamiUitOpen 0:a98746e7a170 28 { {302, 40}, {2057, 60}, {3004, 65} }, // イ
MikamiUitOpen 0:a98746e7a170 29 { {375, 45}, {1208, 55}, {2165, 60} }, // ウ
MikamiUitOpen 0:a98746e7a170 30 { {541, 50}, {1784, 60}, {2452, 60} }, // エ
MikamiUitOpen 0:a98746e7a170 31 { {458, 45}, { 807, 50}, {2379, 60} }}; // オ
MikamiUitOpen 0:a98746e7a170 32
MikamiUitOpen 0:a98746e7a170 33 int main()
MikamiUitOpen 0:a98746e7a170 34 {
MikamiUitOpen 0:a98746e7a170 35 const float FS = I2S_AUDIOFREQ_16K; // 標本化周波数: 16 kHz
MikamiUitOpen 0:a98746e7a170 36 const float F0 = 125.0f; // 基本周波数:125 Hz
MikamiUitOpen 0:a98746e7a170 37 const float A0 = 10000.0f; // 声帯波の振幅
MikamiUitOpen 0:a98746e7a170 38 const float A0M[N_VWL_] = // 声帯波の倍率
MikamiUitOpen 0:a98746e7a170 39 { 1.0f, 3.0f, 2.0f, 1.0f, 1.0f };
MikamiUitOpen 0:a98746e7a170 40
MikamiUitOpen 0:a98746e7a170 41 Rosenberg gs(F0, FS, A0); // 声帯波発生用オブジェクト初期化
MikamiUitOpen 0:a98746e7a170 42 Resonator rs[N_RSN_]; // 共振器用オブジェクト配列の宣言
MikamiUitOpen 0:a98746e7a170 43 Radiator rd(0.8f); // 放射の効果用オブジェクトの初期化
MikamiUitOpen 0:a98746e7a170 44
MikamiUitOpen 0:a98746e7a170 45 LCD_DISCO_F746NG lcd; // LCD 用オブジェクト
MikamiUitOpen 0:a98746e7a170 46 const uint32_t BACK_COLOR = 0xFF006A6C; // Teal green
MikamiUitOpen 0:a98746e7a170 47 const uint32_t TOUCHED_COLOR = 0xFF7F7FFF;
MikamiUitOpen 0:a98746e7a170 48 const uint32_t ORIGINAL_COLOR = 0xFF0068B7;
MikamiUitOpen 0:a98746e7a170 49
MikamiUitOpen 0:a98746e7a170 50 lcd.Clear(BACK_COLOR);
MikamiUitOpen 0:a98746e7a170 51 lcd.SetBackColor(BACK_COLOR);
MikamiUitOpen 0:a98746e7a170 52 lcd.SetTextColor(LCD_COLOR_WHITE);
MikamiUitOpen 0:a98746e7a170 53 lcd.SetFont(&Font20);
MikamiUitOpen 0:a98746e7a170 54 lcd.DisplayStringAt(0, 10, (uint8_t *)"Vowel Synthesizer", CENTER_MODE);
MikamiUitOpen 0:a98746e7a170 55
MikamiUitOpen 0:a98746e7a170 56 TS_DISCO_F746NG ts; // タッチパネル用オブジェクト
MikamiUitOpen 0:a98746e7a170 57 const string FIVE_VOEWLS[N_VWL_] = {"a", "i", "u", "e", "o"};
MikamiUitOpen 0:a98746e7a170 58 ButtonGroup vowel(lcd, ts, 10, 40, 50, 40,
MikamiUitOpen 0:a98746e7a170 59 ORIGINAL_COLOR, BACK_COLOR,
MikamiUitOpen 0:a98746e7a170 60 N_VWL_, FIVE_VOEWLS, 0, 5, 1, Font20);
MikamiUitOpen 0:a98746e7a170 61 vowel.Draw(0, TOUCHED_COLOR);
MikamiUitOpen 0:a98746e7a170 62
MikamiUitOpen 0:a98746e7a170 63 // 白鍵用
MikamiUitOpen 0:a98746e7a170 64 const string NO_CHAR[8] = {"", "", "", "", "", "", "", ""};
MikamiUitOpen 0:a98746e7a170 65 const int X0S = 90;
MikamiUitOpen 0:a98746e7a170 66 const int Y0S = 120;
MikamiUitOpen 0:a98746e7a170 67 const int WIDTH = 43;
MikamiUitOpen 0:a98746e7a170 68 ButtonGroup scale(lcd, ts, X0S, Y0S, WIDTH, 140,
MikamiUitOpen 0:a98746e7a170 69 LCD_COLOR_WHITE, BACK_COLOR,
MikamiUitOpen 0:a98746e7a170 70 8, NO_CHAR, 5, 0, 8);
MikamiUitOpen 0:a98746e7a170 71
MikamiUitOpen 0:a98746e7a170 72 const float F_DO = 110.0f*powf(2, 3.0f/12.0f);
MikamiUitOpen 0:a98746e7a170 73 const float F_OCTAVE[8] =
MikamiUitOpen 0:a98746e7a170 74 { F_DO, F_DO*powf(2, 2.0f/12.0f),
MikamiUitOpen 0:a98746e7a170 75 F_DO*powf(2, 4.0f/12.0f), F_DO*powf(2, 5.0f/12.0f),
MikamiUitOpen 0:a98746e7a170 76 F_DO*powf(2, 7.0f/12.0f), F_DO*powf(2, 9.0f/12.0f),
MikamiUitOpen 0:a98746e7a170 77 F_DO*powf(2, 11.0f/12.0f), F_DO*2};
MikamiUitOpen 0:a98746e7a170 78
MikamiUitOpen 0:a98746e7a170 79 // 黒鍵用(音は出ない)
MikamiUitOpen 0:a98746e7a170 80 const int H0 = 70;
MikamiUitOpen 0:a98746e7a170 81 const int X0B = X0S+WIDTH/2+5;
MikamiUitOpen 0:a98746e7a170 82 const int WB = WIDTH-5;
MikamiUitOpen 0:a98746e7a170 83 const int MPOS = WIDTH + 5;
MikamiUitOpen 0:a98746e7a170 84 lcd.SetTextColor(LCD_COLOR_BLACK);
MikamiUitOpen 0:a98746e7a170 85 lcd.FillRect(X0B, Y0S, WB, H0);
MikamiUitOpen 0:a98746e7a170 86 lcd.FillRect(X0B+MPOS, Y0S, WB, H0);
MikamiUitOpen 0:a98746e7a170 87 lcd.FillRect(X0B+MPOS*3, Y0S, WB, H0);
MikamiUitOpen 0:a98746e7a170 88 lcd.FillRect(X0B+MPOS*4, Y0S, WB, H0);
MikamiUitOpen 0:a98746e7a170 89 lcd.FillRect(X0B+MPOS*5, Y0S, WB, H0);
MikamiUitOpen 0:a98746e7a170 90
MikamiUitOpen 0:a98746e7a170 91 // 男声,女声
MikamiUitOpen 0:a98746e7a170 92 const string MF[2] ={"M", "F"};
MikamiUitOpen 0:a98746e7a170 93 ButtonGroup mf(lcd, ts, X0S, 40, 60, 40,
MikamiUitOpen 0:a98746e7a170 94 ORIGINAL_COLOR, BACK_COLOR,
MikamiUitOpen 0:a98746e7a170 95 2, MF, 5, 0, 2, Font20);
MikamiUitOpen 0:a98746e7a170 96 mf.Draw(0, TOUCHED_COLOR);
MikamiUitOpen 0:a98746e7a170 97
MikamiUitOpen 0:a98746e7a170 98 mySai_.InitCodecOut();
MikamiUitOpen 0:a98746e7a170 99 mySai_.OutPause();
MikamiUitOpen 0:a98746e7a170 100
MikamiUitOpen 0:a98746e7a170 101 float f0 = 1;
MikamiUitOpen 0:a98746e7a170 102 int mf0 = -1;
MikamiUitOpen 0:a98746e7a170 103 int sw0 = -1;
MikamiUitOpen 0:a98746e7a170 104 // 共振器の準備
MikamiUitOpen 0:a98746e7a170 105 for (int k=0; k<N_RSN_; k++)
MikamiUitOpen 0:a98746e7a170 106 rs[k] = Resonator(FORMANT_[0][k], FS);
MikamiUitOpen 0:a98746e7a170 107 // 声帯波の振幅設定
MikamiUitOpen 0:a98746e7a170 108 gs.SetAmplitude(A0*A0M[0]);
MikamiUitOpen 0:a98746e7a170 109
MikamiUitOpen 0:a98746e7a170 110 int dore0 = -1;
MikamiUitOpen 0:a98746e7a170 111 while (true)
MikamiUitOpen 0:a98746e7a170 112 {
MikamiUitOpen 0:a98746e7a170 113 int mfNow;
MikamiUitOpen 0:a98746e7a170 114 if (mf.GetTouchedNumber(mfNow, TOUCHED_COLOR))
MikamiUitOpen 0:a98746e7a170 115 {
MikamiUitOpen 0:a98746e7a170 116 if (mfNow != mf0)
MikamiUitOpen 0:a98746e7a170 117 {
MikamiUitOpen 0:a98746e7a170 118 // 男声,女声の切り替え
MikamiUitOpen 0:a98746e7a170 119 f0 = (mfNow == 0) ? 1.0f : 2.0f;
MikamiUitOpen 0:a98746e7a170 120 mf0 = mfNow;
MikamiUitOpen 0:a98746e7a170 121 }
MikamiUitOpen 0:a98746e7a170 122 }
MikamiUitOpen 0:a98746e7a170 123
MikamiUitOpen 0:a98746e7a170 124 int sw;
MikamiUitOpen 0:a98746e7a170 125 if (vowel.GetTouchedNumber(sw, TOUCHED_COLOR))
MikamiUitOpen 0:a98746e7a170 126 {
MikamiUitOpen 0:a98746e7a170 127 if (sw != sw0)
MikamiUitOpen 0:a98746e7a170 128 {
MikamiUitOpen 0:a98746e7a170 129 // 共振器の準備
MikamiUitOpen 0:a98746e7a170 130 for (int k=0; k<N_RSN_; k++)
MikamiUitOpen 0:a98746e7a170 131 rs[k] = Resonator(FORMANT_[sw][k], FS);
MikamiUitOpen 0:a98746e7a170 132 // 声帯波の振幅設定
MikamiUitOpen 0:a98746e7a170 133 gs.SetAmplitude(A0*A0M[sw]);
MikamiUitOpen 0:a98746e7a170 134
MikamiUitOpen 0:a98746e7a170 135 sw0 = sw;
MikamiUitOpen 0:a98746e7a170 136 }
MikamiUitOpen 0:a98746e7a170 137 }
MikamiUitOpen 0:a98746e7a170 138 int dore;
MikamiUitOpen 0:a98746e7a170 139 if (scale.GetTouchedNumber(dore)) // キーがタッチされている場合
MikamiUitOpen 0:a98746e7a170 140 {
MikamiUitOpen 0:a98746e7a170 141 if (dore != dore0) // タッチするキーが変わった場合
MikamiUitOpen 0:a98746e7a170 142 {
MikamiUitOpen 0:a98746e7a170 143 // 音階に対応する基本周期に設定
MikamiUitOpen 0:a98746e7a170 144 gs.SetPeriod(F_OCTAVE[dore]*f0);
MikamiUitOpen 0:a98746e7a170 145 dore0 = dore;
MikamiUitOpen 0:a98746e7a170 146 mySai_.OutResume();
MikamiUitOpen 0:a98746e7a170 147 }
MikamiUitOpen 0:a98746e7a170 148
MikamiUitOpen 0:a98746e7a170 149 if (mySai_.IsXferred())
MikamiUitOpen 0:a98746e7a170 150 {
MikamiUitOpen 0:a98746e7a170 151 for (int n=0; n<mySai_.GetLength(); n++)
MikamiUitOpen 0:a98746e7a170 152 {
MikamiUitOpen 0:a98746e7a170 153 float gn = gs.Execute(); // 合成声帯波発生
MikamiUitOpen 0:a98746e7a170 154 float vn = gn; // 声帯波を声道へ入力
MikamiUitOpen 0:a98746e7a170 155 for (int k=0; k<N_RSN_; k++)
MikamiUitOpen 0:a98746e7a170 156 vn = rs[k].Execute(vn); // 声道の効果
MikamiUitOpen 0:a98746e7a170 157 float yn = rd.Execute(vn); // 放射の効果
MikamiUitOpen 0:a98746e7a170 158
MikamiUitOpen 0:a98746e7a170 159 mySai_.Output(yn, gn);
MikamiUitOpen 0:a98746e7a170 160 }
MikamiUitOpen 0:a98746e7a170 161 mySai_.ResetXferred();
MikamiUitOpen 0:a98746e7a170 162 }
MikamiUitOpen 0:a98746e7a170 163 }
MikamiUitOpen 0:a98746e7a170 164 else // キーがタッチされていない場合
MikamiUitOpen 0:a98746e7a170 165 {
MikamiUitOpen 0:a98746e7a170 166 mySai_.OutPause();
MikamiUitOpen 0:a98746e7a170 167 mySai_.ClearOutBuffer();
MikamiUitOpen 0:a98746e7a170 168 dore0 = -1;
MikamiUitOpen 0:a98746e7a170 169 }
MikamiUitOpen 0:a98746e7a170 170 }
MikamiUitOpen 0:a98746e7a170 171 }