1.音を鳴らす
まずは、単純に音を鳴らすプログラムを作成します。
次のプログラムを作成してください。ここでは sound1.c とします。
今回新たに用いたAPIなどについて解説します。
これで単純に音を鳴らすことができました。ecrobot_sound_tone関数は鳴り終わるまで待つ動作をせず、次の処理に移ってしまいます。
よって、systick_wait_ms関数と同様に使うとよいです。
また、ecrobot_sound_tone関数の周波数指定で音を出すときに音階に従って指定したい場合は、次の表を参考にすると良いでしょう。
sound1.c
#include "kernel.h" #include "kernel_id.h" #include "ecrobot_interface.h" DeclareTask(Task1); /* Task1を宣言 */ void ecrobot_device_initialize(){} /* OSEK起動時の処理(何もしない)*/ void ecrobot_device_terminate(){} /* OSEK終了時の処理(何もしない)*/ void user_1ms_isr_type2(void){} TASK(Task1) { ecrobot_sound_tone(440,10, 50); /* 音を鳴らす */ systick_wait_ms(100); /* 100ms待つ */ display_string("THAT'S ALL !"); /* メッセージを表示する */ display_update(); TerminateTask(); /* 処理終了 */ } |
今回新たに用いたAPIなどについて解説します。
ecrobot_sound_tone(440,10, 50)
スピーカーから音を鳴らします。
第一の引数は音程を指定します。単位はHzです。範囲は 31Hz 〜 2100Hz の間です。
第二の変数は音の長さを指定します。単位は1msです。
第三の変数は音の大きさを指定します。範囲は0〜100までです。
第一の引数は音程を指定します。単位はHzです。範囲は 31Hz 〜 2100Hz の間です。
第二の変数は音の長さを指定します。単位は1msです。
第三の変数は音の大きさを指定します。範囲は0〜100までです。
これで単純に音を鳴らすことができました。ecrobot_sound_tone関数は鳴り終わるまで待つ動作をせず、次の処理に移ってしまいます。
よって、systick_wait_ms関数と同様に使うとよいです。
また、ecrobot_sound_tone関数の周波数指定で音を出すときに音階に従って指定したい場合は、次の表を参考にすると良いでしょう。
音階 | オクターブ | |||
---|---|---|---|---|
3 | 4 | 5 | 6 | |
B | 247 | 494 | 988 | |
A# | 233 | 466 | 932 | |
A | 220 | 440 | 880 | 1760 |
G# | 415 | 831 | 1661 | |
G | 392 | 784 | 1568 | |
F# | 370 | 740 | 1480 | |
F | 349 | 698 | 1397 | |
E | 330 | 659 | 1319 | |
D# | 311 | 622 | 1245 | |
D | 294 | 584 | 1175 | |
C# | 277 | 554 | 1109 | |
C | 262 | 523 | 1047 |
2.メロディーを作成する
先ほどの機能を用いれば、メロディーを作成することができます。
それでは次のプログラムを作成してください。ここでは sound2.c とします。
プログラムを動かすとご存知「カエルの歌」が演奏されます。
今回は、音符を鳴らすために、同じ処理が何度も登場します。これを上の例では、ユーザー関数を定義してひとまとめにしています。
繰り返し使う処理をユーザ関数としてまとめると、プログラム全体の流れが分かりやすくなります。
このプログラムでは RingTone という音を鳴らして一定時間待つという部分だけを関数化しましたが、音楽演奏全体を一つの関数として定義することも可能です。
それでは次のプログラムを作成してください。ここでは sound2.c とします。
sound2.c
#include "kernel.h" #include "kernel_id.h" #include "ecrobot_interface.h" DeclareTask(Task1); /* Task1を宣言 */ void ecrobot_device_initialize(){} /* OSEK起動時の処理(何もしない)*/ void ecrobot_device_terminate(){} /* OSEK終了時の処理(何もしない)*/ void user_1ms_isr_type2(void){} #define TEMPO 250 #define DURATION 100 #define VOLUME 50 void RingTone(int freq, int time, int vol){ /* 音符を再生するユーザー関数を定義 */ ecrobot_sound_tone(freq, DURATION , vol); systick_wait_ms(time); } TASK(Task1) { RingTone(523, TEMPO*2, VOLUME); RingTone(587, TEMPO*2, VOLUME); RingTone(659, TEMPO*2, VOLUME); RingTone(698, TEMPO*2, VOLUME); RingTone(659, TEMPO*2, VOLUME); RingTone(587, TEMPO*2, VOLUME); RingTone(523, TEMPO*4, VOLUME); RingTone(659, TEMPO*2, VOLUME); RingTone(698, TEMPO*2, VOLUME); RingTone(784, TEMPO*2, VOLUME); RingTone(880, TEMPO*2, VOLUME); RingTone(784, TEMPO*2, VOLUME); RingTone(698, TEMPO*2, VOLUME); RingTone(659, TEMPO*4, VOLUME); RingTone(523, TEMPO*4, VOLUME); RingTone(523, TEMPO*4, VOLUME); RingTone(523, TEMPO*4, VOLUME); RingTone(523, TEMPO*4, VOLUME); RingTone(523, TEMPO, VOLUME); RingTone(523, TEMPO, VOLUME); RingTone(587, TEMPO, VOLUME); RingTone(587, TEMPO, VOLUME); RingTone(659, TEMPO, VOLUME); RingTone(659, TEMPO, VOLUME); RingTone(698, TEMPO, VOLUME); RingTone(698, TEMPO, VOLUME); RingTone(659, TEMPO*2, VOLUME); RingTone(587, TEMPO*2, VOLUME); RingTone(523, TEMPO*4, VOLUME); display_string("THAT'S ALL !"); /* メッセージを表示する */ display_update(); TerminateTask(); /* 処理終了 */ } |
プログラムを動かすとご存知「カエルの歌」が演奏されます。
今回は、音符を鳴らすために、同じ処理が何度も登場します。これを上の例では、ユーザー関数を定義してひとまとめにしています。
繰り返し使う処理をユーザ関数としてまとめると、プログラム全体の流れが分かりやすくなります。
このプログラムでは RingTone という音を鳴らして一定時間待つという部分だけを関数化しましたが、音楽演奏全体を一つの関数として定義することも可能です。
3.課題
1.サンプルプログラムの動作を確認せよ。
2.何かの曲の一小節を演奏するようなプログラムを作成せよ。
2.何かの曲の一小節を演奏するようなプログラムを作成せよ。