このセクションでは、RCXのサウンド機能を使ってみましょう。 基本的には、NQCでは、RCXの組み込みサウンド6種類を鳴らすための PlaySound というコマンドと、 ユーザが音の高さや長さを指定して音を鳴らすための PlayTone というコマンドが使えます。

目次

6.1 組み込こまれた音を鳴らす

nqc では PlaySound を使って以下のような6種類の組み込まれた音を鳴らすことができます。

PlaySound(SOUND_CLICK) ;        // ピッ
PlaySound(SOUND_DOUBLE_BEEP) ;  // ピーッ、ピーッ
PlaySound(SOUND_DOWN) ;         // ピロピロ〜と低くなる音
PlaySound(SOUND_UP) ;           // ピロピロ〜と高く音
PlaySound(SOUND_LOW_BEEP) ;     // ブーという低い音
PlaySound(SOUND_FAST_UP) ;      // ピロピロ〜と速く高くなる音

ただしこれらの命令は、音が終るのを待たずに次の命令を実行するので、続けて鳴らすときには、次のように Wait を使ってプログラムの進行をわざと遅らせる必要があります。

task main()
{
    PlaySound(SOUND_UP) ;  Wait(150);   // 1.5 秒待つ
    PlaySound(SOUND_DOWN) ;
}

これらの音を出す命令を適当にプログラムに埋め込んでおけば、プログラムの動きもよくわかり、デバッグの際も役立ちます。 例えば、センサーで目標物を捉えた時に『ピッ』と鳴らしたり、 失敗した時には『ブー』と鳴らすようにしておけば、 音を使ってプログラムの進行状況を把握することができます。

6.2 周波数を指定して音を鳴らす

PlayTone を使えば、指定した周波数の音を 指定した時間だけ鳴らすことができます。 例えば、

PlayTone(440,50) ; 

は、周波数が 440 Hz の音を 0.5 秒間鳴らします。 時間は 1/100 秒の単位で指定します。

ところで、音楽を演奏する場合、 周波数で表現された音よりも楽譜に書かれている ド・レ・ミ…、や C・D・E… で表現した音のほうが ほとんどの人にとって分かりやすいと思います。 そこで、よく出てくる音が何 Hz に相当するのか計算しておきましょう。

まず基準となる A の音を 440 Hz と決めます (もちろんこれと違う選び方をする場合も多くあります)。 一旦、基準の音の周波数が決まれば、 1オクターブ高いAの音は周波数が2倍ですから 880 Hz、 逆に、1オクターブ低いAの音は周波数が1/2倍ですから 220 Hz となります。

他の音の周波数は1オクターブを (対数で) 12 等分することによって 得られます (ピアノの白鍵7+黒鍵5に相当)。 A より半音高い A# の音の周波数は A の周波数の 2 の 1/12 乗倍 (= 1.059463倍) で 466 Hz となります。 同様に B の音の周波数は A# の 2 の 1/12 乗倍の 494 Hz、…、 というふうに半音上がると周波数は 2 の 1/12 乗倍になります。

このように、1オクターブを12等分する音律を12平均律といいます。 この12平均律以外にもいろいろな音律がありますので、 興味のある人は「音律」「調律」などのキーワードで調べてみてください。

以下の表は12平均律でのいろいろな音の周波数をまとめたものです。 右に1列だけ移動すると1オクターブ高く(周波数が2倍に)なるように、 また1行下に移動すると半音上がる(= 1.059463倍)ように書いてあります。

A285511022044088017603520
A#295811723346693218653729
B316212324749498819763951
C3365131262523104720934186
C#3569139277554110922174435
D3773147294587117523494699
D#3978156311622124524894978
E4182165330659131926375274
F4487175349698139727945588
F#4692185370740148029605920
G4998196392784156831366272
G#52104208415831166133226645

演奏例

以下は、『メリーさんのひつじ』をハ長調で演奏する プログラムの例です。 この例のようにあらかじめ特定の周波数を定数として定義しておくと便利です。

また、このプログラムでは音楽を演奏する play_music というタスクを別に定義して、これを main の中から 起動しています。

#define Do  523
#define Re  587
#define Mi  659
#define Fa  698
#define Sol 784

task play_music()   // 音楽を演奏するタスク
{
    while (true)
    {
        PlayTone(Mi,25); Wait(30);  // Wait の時間の方を少し長くして
        PlayTone(Re, 5); Wait(10);  // 同じ音を続けて鳴らす場合にも
        PlayTone(Do,15); Wait(20);  // 一つの音にならないようにしている
        PlayTone(Re,15); Wait(20);

        PlayTone(Mi,15); Wait(20);
        PlayTone(Mi,15); Wait(20);
        PlayTone(Mi,35); Wait(40);

        PlayTone(Re,15); Wait(20);
        PlayTone(Re,15); Wait(20);
        PlayTone(Re,35); Wait(40);

        PlayTone(Mi,15); Wait(20);
        PlayTone(Sol,15); Wait(20);
        PlayTone(Sol,35); Wait(40);

        PlayTone(Mi,25); Wait(30);
        PlayTone(Re, 5); Wait(10);
        PlayTone(Do,15); Wait(20);
        PlayTone(Re,15); Wait(20);

        PlayTone(Mi,15); Wait(20);
        PlayTone(Mi,15); Wait(20);
        PlayTone(Mi,35); Wait(40);

        PlayTone(Re,15); Wait(20);
        PlayTone(Re,15); Wait(20);
        PlayTone(Mi,25); Wait(30);
        PlayTone(Re, 5); Wait(10);

        PlayTone(Do,55); Wait(60);
        Wait(20);
    }
}

task main()
{
    SetSensor(SENSOR_1, SENSOR_TOUCH);

    start play_music ;    // 演奏を開始
    OnFwd(OUT_A+OUT_B);   // 前進

    until (SENSOR_1 == 1);
    stop play_music ;     // 演奏を停止
    Off(OUT_A+OUT_B);     // 動きも停止
}

ところで、RCX1 では PlayTone の引数として定数だけが許されていましたが、 RCX2 では変数の周波数も使うことができます。 変数を使えば、一つのプログラム内で曲の調を変えて演奏することができます (コンパイルする時に -Trcx2オプションが必要)。

ただ、NQC では浮動小数点型の変数は扱えないので 全て整数で計算する必要があり、 しかも整数は 16bit なので -32768〜32767 の範囲しか使えません。 しかしそれでも、 計算方法を工夫すればかなりいろいろなことができると思います。

例えば全ての音を 5/4 倍したり、3/2 倍して演奏すれば、 どのような調になるか一度試してみてください。

★ 練習問題
明るいところでは、長調で、暗いところでは短調で、 曲を演奏するプログラムを作成しなさい (曲は何でもよい)。



トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2009-11-27 (金) 16:30:00 (3550d)