Synthesizer for Japanese five vowels with keyboard. 鍵盤と一緒になった日本語の5母音の合成器.
Dependencies: BSP_DISCO_F746NG_patch_fixed BUTTON_GROUP LCD_DISCO_F746NG TS_DISCO_F746NG mbed
Revision 0:a98746e7a170, committed 2016-02-24
- Comitter:
- MikamiUitOpen
- Date:
- Wed Feb 24 13:00:12 2016 +0000
- Commit message:
- 1
Changed in this revision
diff -r 000000000000 -r a98746e7a170 BSP_DISCO_F746NG_patch_fixed.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BSP_DISCO_F746NG_patch_fixed.lib Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/users/the_sz/code/BSP_DISCO_F746NG_patch_fixed/#0094f74cb733
diff -r 000000000000 -r a98746e7a170 BUTTON_GROUP.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/BUTTON_GROUP.lib Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/MikamiUitOpen/code/BUTTON_GROUP/#af578b53ff0e
diff -r 000000000000 -r a98746e7a170 LCD_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/LCD_DISCO_F746NG.lib Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/teams/ST/code/LCD_DISCO_F746NG/#d44525b1de98
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/BSP_AudioOut_Overwrite.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/BSP_AudioOut_Overwrite.cpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,112 @@ +//-------------------------------------------------------------- +// Overwrite functuions and define calback functions +// for functions in stm32746g_discovery_audio.cpp +//-------------------------------------------------------------- +#include "BSP_AudioOut_Overwrite.hpp" + +// These three callback functions are modyfied by Mikami +void BSP_AUDIO_OUT_HalfTransfer_CallBack() +{ + Mikami::SaiIO_O::FillBuffer1st(); +} + +void BSP_AUDIO_OUT_TransferComplete_CallBack() +{ + Mikami::SaiIO_O::FillBuffer2nd(); +} + +void BSP_AUDIO_OUT_Error_CallBack() +{ + Mikami::SaiIO_O::ErrorTrap(); +} + +//-------------------------------------------------------------- +// Followings are original by Nanase +//-------------------------------------------------------------- + +DMA_HandleTypeDef hdma_sai_tx; + +void AUDIO_OUT_SAIx_DMAx_IRQHandler() +{ + HAL_DMA_IRQHandler(&hdma_sai_tx); +} + +void BSP_AUDIO_OUT_MspInit(SAI_HandleTypeDef *hsai, void *Params) +{ + //static DMA_HandleTypeDef hdma_sai_tx; + GPIO_InitTypeDef gpio_init_structure; + + /* Enable SAI clock */ + AUDIO_OUT_SAIx_CLK_ENABLE(); + + /* Enable GPIO clock */ + AUDIO_OUT_SAIx_MCLK_ENABLE(); + AUDIO_OUT_SAIx_SCK_SD_ENABLE(); + AUDIO_OUT_SAIx_FS_ENABLE(); + + /* CODEC_SAI pins configuration: FS, SCK, MCK and SD pins ------------------*/ + gpio_init_structure.Pin = AUDIO_OUT_SAIx_FS_PIN; + gpio_init_structure.Mode = GPIO_MODE_AF_PP; + gpio_init_structure.Pull = GPIO_NOPULL; + gpio_init_structure.Speed = GPIO_SPEED_HIGH; + gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF; + HAL_GPIO_Init(AUDIO_OUT_SAIx_FS_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = AUDIO_OUT_SAIx_SCK_PIN; + gpio_init_structure.Mode = GPIO_MODE_AF_PP; + gpio_init_structure.Pull = GPIO_NOPULL; + gpio_init_structure.Speed = GPIO_SPEED_HIGH; + gpio_init_structure.Alternate = AUDIO_OUT_SAIx_SCK_AF; + HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = AUDIO_OUT_SAIx_SD_PIN; + gpio_init_structure.Mode = GPIO_MODE_AF_PP; + gpio_init_structure.Pull = GPIO_NOPULL; + gpio_init_structure.Speed = GPIO_SPEED_HIGH; + gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF; + HAL_GPIO_Init(AUDIO_OUT_SAIx_SCK_SD_GPIO_PORT, &gpio_init_structure); + + gpio_init_structure.Pin = AUDIO_OUT_SAIx_MCLK_PIN; + gpio_init_structure.Mode = GPIO_MODE_AF_PP; + gpio_init_structure.Pull = GPIO_NOPULL; + gpio_init_structure.Speed = GPIO_SPEED_HIGH; + gpio_init_structure.Alternate = AUDIO_OUT_SAIx_FS_SD_MCLK_AF; + HAL_GPIO_Init(AUDIO_OUT_SAIx_MCLK_GPIO_PORT, &gpio_init_structure); + + /* Enable the DMA clock */ + AUDIO_OUT_SAIx_DMAx_CLK_ENABLE(); + + if(hsai->Instance == AUDIO_OUT_SAIx) + { + /* Configure the hdma_saiTx handle parameters */ + hdma_sai_tx.Init.Channel = AUDIO_OUT_SAIx_DMAx_CHANNEL; + hdma_sai_tx.Init.Direction = DMA_MEMORY_TO_PERIPH; + hdma_sai_tx.Init.PeriphInc = DMA_PINC_DISABLE; + hdma_sai_tx.Init.MemInc = DMA_MINC_ENABLE; + hdma_sai_tx.Init.PeriphDataAlignment = AUDIO_OUT_SAIx_DMAx_PERIPH_DATA_SIZE; + hdma_sai_tx.Init.MemDataAlignment = AUDIO_OUT_SAIx_DMAx_MEM_DATA_SIZE; + hdma_sai_tx.Init.Mode = DMA_CIRCULAR; + hdma_sai_tx.Init.Priority = DMA_PRIORITY_HIGH; + hdma_sai_tx.Init.FIFOMode = DMA_FIFOMODE_ENABLE; + hdma_sai_tx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL; + hdma_sai_tx.Init.MemBurst = DMA_MBURST_SINGLE; + hdma_sai_tx.Init.PeriphBurst = DMA_PBURST_SINGLE; + + hdma_sai_tx.Instance = AUDIO_OUT_SAIx_DMAx_STREAM; + + /* Associate the DMA handle */ + __HAL_LINKDMA(hsai, hdmatx, hdma_sai_tx); + + /* Deinitialize the Stream for new transfer */ + HAL_DMA_DeInit(&hdma_sai_tx); + + /* Configure the DMA Stream */ + HAL_DMA_Init(&hdma_sai_tx); + } + + /* SAI DMA IRQ Channel configuration */ + HAL_NVIC_SetPriority(AUDIO_OUT_SAIx_DMAx_IRQ, AUDIO_OUT_IRQ_PREPRIO, 0); + HAL_NVIC_EnableIRQ(AUDIO_OUT_SAIx_DMAx_IRQ); +} + +
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/BSP_AudioOut_Overwrite.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/BSP_AudioOut_Overwrite.hpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,15 @@ +//-------------------------------------------------------------- +// Overwrite functuions and define calback function (Header) +// for functions in stm32746g_discovery_audio.cpp +//-------------------------------------------------------------- + +#ifndef F746_AUDIO_OUT_OVERWRITE_HPP +#define F746_AUDIO_OUT_OVERWRITE_HPP + +#include "stm32746g_discovery_audio.h" +#include "sai_io_o.hpp" + +void AUDIO_OUT_SAIx_DMAx_IRQHandler(); + +#endif // F746_AUDIO_OUT_OVERWRITE_HPP +
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/Radiator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/Radiator.cpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,15 @@ +//------------------------------------------------------------------------------ +// 口からの放射の効果 +// 作成者:三上直樹,2013/11/27 作成,(c)三上直樹 2013 +//------------------------------------------------------------------------------ + +#include "Radiator.hpp" + +// 差分に対応する処理の実行 +float Radiator::Execute(float xin) +{ + float yn = xin - c1_*xnM1_; + xnM1_ = xin; // x[n-1] ← x[n] + return yn; +} +
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/Radiator.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/Radiator.hpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,31 @@ +//------------------------------------------------------------------------------ +// 口からの放射の効果(ヘッダ) +// 作成者:三上直樹,2013/11/26 作成,(c)三上直樹 2013 +//------------------------------------------------------------------------------ + +#ifndef RADIATOR_HPP +#define RADIATOR_HPP + +class Radiator +{ +private: + const float c1_; + float xnM1_; + + // コピー・コンストラクタの使用禁止 + Radiator(const Radiator& g); + // 代入演算子の使用禁止 + Radiator& operator=(const Radiator& g); + +public: + // デフォルト・コンストラクタ + explicit Radiator(float c1 = 1.0f) : c1_(c1) { Clear(); } + + // 差分に対応する処理の実行 + float Execute(float xin); + + // 内部の遅延器のクリア + void Clear() { xnM1_ = 0; } +}; + +#endif // RADIATOR_HPP
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/Resonator.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/Resonator.cpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,34 @@ +//------------------------------------------------------------------------------ +// 音声合成で使う共振器 +// 作成者:三上直樹,2013/11/27 作成,(c)三上直樹 2013 +//------------------------------------------------------------------------------ + +#include "Resonator.hpp" + +// コンストラクタに共通な初期化 +void Resonator::Initialize(float fr, float bw, float fs) +{ + if (piT_ == 0) piT_ = 3.14159265f/fs; + Set(fr, bw); + Clear(); +} + +// 共振器のパラメータの設定 +void Resonator::Set(float fr, float bw) +{ + a1_ = 2.0f*expf(-piT_*bw)*cosf(2.0f*piT_*fr); + a2_ = -expf(-2.0f*piT_*bw); + b0_ = 1.0f - a1_ - a2_; +} + +// 共振器に対応する処理の実行 +float Resonator::Execute(float xin) +{ + float ym = a1_*yn1_ + a2_*yn2_ + b0_*xin; + yn2_ = yn1_; // 遅延器のデータの移動 + yn1_ = ym; // 遅延器のデータの移動 + return ym; +} + +// π/標本化周波数" の値に対応する実体 +float Resonator::piT_ = 0; \ No newline at end of file
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/Resonator.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/Resonator.hpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,47 @@ +//------------------------------------------------------------------------------ +// 音声合成で使う共振器(ヘッダ) +// 作成者:三上直樹,2013/11/27 作成,(c)三上直樹 2013 +//------------------------------------------------------------------------------ + +#include "mbed.h" + +#ifndef RESONATOR_HPP +#define RESONATOR_HPP + +class Resonator +{ +private: + static float piT_; + float a1_, a2_, b0_; + float yn1_, yn2_; + + // コンストラクタに共通な初期化 + void Initialize(float fr, float bw, float fs); + +public: + // 共振周波数と帯域幅に対応する構造体 + struct FrBw { float fr, bw; }; + + // デフォルト・コンストラクタ + Resonator() {} + + // 初期化を行うコンストラクタ + Resonator(float fr, float bw, float fs) { Initialize(fr, bw, fs); } + + // 初期化を行うコンストラクタ(構造体使用) + Resonator(FrBw fb, float fs) { Initialize(fb.fr, fb.bw, fs); } + + // 共振器のパラメータの設定 + void Set(float fr, float bw); + + // 共振器のパラメータの設定(構造体使用) + void Set(FrBw fb) { Set(fb.fr, fb.bw); } + + // 内部の遅延器をクリア + void Clear() { yn1_ = 0; yn2_ = 0; } + + // 共振器に対応する処理の実行 + float Execute(float xin); +}; + +#endif // RESONATOR_HPP
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/Rosenberg.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/Rosenberg.cpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,36 @@ +//------------------------------------------------------------------------------ +// 声帯波の合成 ― Rosenberg 波 +// 作成者:三上直樹,2013/10/27 作成,(c)三上直樹 2013 +//------------------------------------------------------------------------------ + +#include "Rosenberg.hpp" + + // 基本周期の設定 + void Rosenberg::SetPeriod(float f0) + { + period_ = 1.0f/f0; + t1_ = 0.4f/f0; + t2_ = 0.16f/f0; + } + + // Rosengerg 波の計算 + float Rosenberg::Execute() + { + float g = 0; + + if (t_ < t1_) + { + float x = t_/t1_; + g = amp_*(3.0f - 2.0f*x)*x*x; + } + if ((t_ >= t1_) && (t_ < t1_+t2_)) + { + float x = (t_ - t1_)/t2_; + g = amp_*(1.0f - x*x); + } + + if ((t_+=dt_) > period_) t_ -= period_; + + return g; + } +
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/Rosenberg.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/Rosenberg.hpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,44 @@ +//------------------------------------------------------------------------------ +// 声帯波の合成 ― Rosenberg 波(ヘッダ) +// 作成者:三上直樹,2013/10/27 作成,(c)三上直樹 2013 +//------------------------------------------------------------------------------ + +#ifndef ROSENBERG_HPP +#define ROSENBERGL_HPP + +class Rosenberg +{ +private: + const float dt_; + + float period_, t1_, t2_, t_, amp_; + + // コピー・コンストラクタの使用禁止 + Rosenberg(const Rosenberg& g); + // 代入演算子の使用禁止 + Rosenberg& operator=(const Rosenberg& g); + +public: + // 初期化を行うコンストラクタ + // f0: 基本周波数 + // fs: 標本化周波数 + // amp: 振幅 + Rosenberg(float f0, float fs, float amp) + : dt_(1.0f/fs), t_(0), amp_(amp) + { SetPeriod(f0); } + + // 基本周期の再設定 + // f0: 基本周波数 + void SetPeriod(float f0); + + // 振幅の再設定 + void SetAmplitude(float amp) { amp_ = amp; } + + // t_ = 0 に設定 + void Reset() { t_ = 0; } + + // Rosengerg 波の計算 + float Execute(); +}; + +#endif // ROSENBERG_HPP
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/sai_io_o.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/sai_io_o.cpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,95 @@ +//----------------------------------------------------------- +// SiaIO class for output +// 2016/02/16, Copyright (c) 2016 MIKAMI, Naoki +//----------------------------------------------------------- + +#include "sai_io_o.hpp" + +namespace Mikami +{ + SaiIO_O::SaiIO_O(int size, int fs) : FS_(fs), tmpIndex_(0) + { + nData_ = size; + bufferSize_ = (size*2)*2; + outBuffer_ = new int16_t[bufferSize_]; + tmp_ = new int16_t[size*2]; + ClearOutBuffer(); + xferred_ = false; + } + + void SaiIO_O::InitCodecOut() + { + if (BSP_AUDIO_OUT_Init(OUTPUT_DEVICE_HEADPHONE, VOLUME_OUT_, FS_) == AUDIO_ERROR) + ErrorTrap(); + + NVIC_SetVector(AUDIO_OUT_SAIx_DMAx_IRQ, (uint32_t)AUDIO_OUT_SAIx_DMAx_IRQHandler); + BSP_AUDIO_OUT_SetAudioFrameSlot(CODEC_AUDIOFRAME_SLOT_02); + + if (BSP_AUDIO_OUT_Play((uint16_t *)outBuffer_, + bufferSize_*AUDIODATA_SIZE) == AUDIO_ERROR) + ErrorTrap(); + } + + bool SaiIO_O::IsXferred() + { + if (xferred_) + { + tmpIndex_ = 0; + return true; + } + else + return false; + } + + void SaiIO_O::Output(int16_t xL, int16_t xR) + { + tmp_[tmpIndex_++] = xL; // Left + tmp_[tmpIndex_++] = xR; // Right + } + + void SaiIO_O::ClearOutBuffer() + { + for (int n=0; n<bufferSize_; n++) outBuffer_[n] = 0; + for (int n=0; n<bufferSize_/2; n++) tmp_[n] = 0; + } + + void SaiIO_O::StartOutPlay() + { + if (BSP_AUDIO_OUT_Play((uint16_t *)outBuffer_, + bufferSize_*AUDIODATA_SIZE) == AUDIO_ERROR) + ErrorTrap(); + } + + void SaiIO_O::StopOutPlay() + { + if (BSP_AUDIO_OUT_Stop(CODEC_PDWN_SW)) + ErrorTrap(); + } + + void SaiIO_O::ErrorTrap() + { + DigitalOut led1(LED1); + fprintf(stderr, "\r\n### ERROR\r\n"); + while(true) + { + led1 = !led1; + wait_ms(250); + } + } + + void SaiIO_O::FillBuffer(uint32_t offset) + { + int k = offset; + for (int n=0; n<nData_*2; n++) + outBuffer_[k++] = tmp_[n]; + xferred_ = true; + } + + // Instances for static variables + int32_t SaiIO_O::nData_; + int32_t SaiIO_O::bufferSize_; + int16_t* SaiIO_O::outBuffer_; + int16_t* SaiIO_O::tmp_; + __IO bool SaiIO_O::xferred_; +} +
diff -r 000000000000 -r a98746e7a170 MyClasses_Functions/sai_io_o.hpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MyClasses_Functions/sai_io_o.hpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,61 @@ +//----------------------------------------------------------- +// SiaIO class for output (Header) +// 2016/02/16, Copyright (c) 2016 MIKAMI, Naoki +//----------------------------------------------------------- + +#ifndef F746_SAI_IO_HPP +#define F746_SAI_IO_HPP + +#include "mbed.h" +#include "stm32746g_discovery_audio.h" +#include "BSP_AudioOut_Overwrite.hpp" + +namespace Mikami +{ + class SaiIO_O + { + public: + SaiIO_O(int size, int fs); + + void InitCodecOut(); + + bool IsXferred(); + void Output(int16_t xL, int16_t xR); + + void ResetXferred() { xferred_ = false; } + int32_t GetLength() { return nData_; } + + void ClearOutBuffer(); + void StartOutPlay(); + void StopOutPlay(); + void OutPause() { BSP_AUDIO_OUT_Pause(); } + void OutResume() {BSP_AUDIO_OUT_Resume(); } + + // These three member functions are called from + // callback functions in "BSP_AudioOut_Overwrite.cpp" + + // Called form BSP_AUDIO_OUT_HalfTransfer_CallBack() + static void FillBuffer1st() { FillBuffer(0); } + // Called form BSP_AUDIO_OUT_TransferComplete_CallBack() + static void FillBuffer2nd() { FillBuffer(bufferSize_/2); } + // Also called form BSP_AUDIO_OUT_Error_CallBack() + static void ErrorTrap(); + + private: + const int FS_; + static const uint8_t VOLUME_OUT_ = 95; + + static int32_t nData_; + static int32_t bufferSize_; + + static int16_t* outBuffer_; + static int16_t* tmp_; + + static __IO bool xferred_; + + __IO int32_t tmpIndex_; + + static void FillBuffer(uint32_t offset); + }; +} +#endif // F746_SAI_IO_HPP
diff -r 000000000000 -r a98746e7a170 TS_DISCO_F746NG.lib --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TS_DISCO_F746NG.lib Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,1 @@ +https://developer.mbed.org/teams/ST/code/TS_DISCO_F746NG/#fe0cf5e2960f
diff -r 000000000000 -r a98746e7a170 main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,171 @@ +//------------------------------------------------------------ +// 合成母音発生器+キーボード +// 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; + } + } +}
diff -r 000000000000 -r a98746e7a170 mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Feb 24 13:00:12 2016 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/f141b2784e32 \ No newline at end of file