marunomaruno-memo

marunomaruno-memo

Lego Mindstomes NXT - NXC プログラミング (5) ミュージック

2008年01月15日 | Weblog
■ rso ファイル

2 つのサウンドファイル(.rso)を鳴らします。
最初は、NTX の起動音を 2 秒間。つぎに、"Good Job" を 2 秒間
繰り返します(実際には、2回と少し)。

---
/**
 * PlayingFile01.nxc
 * 「トライボット」使用
 * rso ファイルを鳴らす。
 * @author maruno
 * @version 1.0, 2008-01-12
 * @since 1.0
 */
#include "NXCDefs.h"

task main()
{
    PlayFileEx("! Startup.rso", 2, false); // (1)
    Wait(2000);

    PlayFileEx("Good Job.rso", 2, true);   // (2)
    Wait(2000);
}
---


□ PlayFileEx("! Startup.rso", 2, false); // (1)

指定された rso ファイルを鳴らすのは、PlayFileEx 関数を使いま
す。
このとき、つぎに Wait 関数を指定しないと、音は鳴りません。


□ PlayFileEx 関数
---
PlayFileEx(filename, volume, bLoop) Function

指定されたサウンドファイル(.rso)またはメロディファイル(.rmd)
を鳴らす。このとき、音量は、0 (無音) から 4 (最大)まで指定で
きます。また、繰り返すかどうかを bool 型の bLoop で指定しま
す。true のときは繰り返します。

例:
PlayFileEx("startup.rso", 3, true);
---

□ PlayFileEx("Good Job.rso", 2, true); // (2)

"Good Job" を繰り返します。

ただし、これはもしかしたら鳴らないかもしれません。これは、指
定されたサウンドファイル "Good Job.rso" が NXT の中に入って
いないからです。

ちなみに、ファームウェア v1.03 をダウンロードした直後だと、
つぎの rso ファイルがあります。
! Attention.rso
! Click.rso
! Startup.rso
Woops.rso


□ ファイルのダウンロード

[Tools] メニュー から、 [NeXT Explorer] 項目をクリックして、
NeXT Explorer を開いてください。左側のペインが、NXT のファイ
ルのリスト。右側のペインがローカルのファイルシステムです。

NXT のファイルリストの中に、指定された "Good Job.rso" がなけ
れば、ローカルからそのファイルをドラッグしてダウンロードしま
す。

サウンドファイルは、Lego ソフトウェアをインストールしたディ
レクトリのサブディレクトリにいろいろと入っています。標準の場
所にインストールしたのなら、つぎのディレクトリになります。
C:\Program Files\LEGO Software\LEGO MINDSTORMS NXT\engine\So
unds

NeXT Explorer の右側のペインを操作して、目的のファイルを左側
のペインにドラッグすれば、ファイルのダウンロードは終わりです。

ダウンロードできたら、もう 1 度実行しましょう。今度は、"Good
Job" を繰り返します。



■ 音を鳴らす

トーンを使って、音を鳴らすことができます。これには、周波数、
持続時間、音量を指定する PlayToneEx 関数を使います。また、こ
の関数も PlayFileEx 関数と同じように Wait 関数を使わないと、
実際には音は鳴りません。

---
/**
 * PlayingMusic01.nxc
 * 「トライボット」使用
 * 音を鳴らす。
 * @author maruno
 * @version 1.0, 2008-01-12
 * @since 1.0
 */
#include "NXCDefs.h"

task main()
{
    // 音階6 を B から C まで
    PlayToneEx(1976, 400, 2, false); Wait(500);
    PlayToneEx(1865, 400, 2, false); Wait(500);
    PlayToneEx(1760, 400, 2, false); Wait(500);
    PlayToneEx(1661, 400, 2, false); Wait(500);
    PlayToneEx(1568, 400, 2, false); Wait(500);
    PlayToneEx(1480, 400, 2, false); Wait(500);
    PlayToneEx(1397, 400, 2, false); Wait(500);
    PlayToneEx(1319, 400, 2, false); Wait(500);
    PlayToneEx(1245, 400, 2, false); Wait(500);
    PlayToneEx(1175, 400, 2, false); Wait(500);
    PlayToneEx(1109, 400, 2, false); Wait(500);
    PlayToneEx(1047, 400, 2, false); Wait(500);
}
---


□ PlayToneEx(1976, 400, 2, false); Wait(500); // (1)

周波数 1976、持続時間 400 ミリ秒、音量 2 でトーンを鳴らしま
す。
ただし、この関数も、すぐにつぎの命令を実行してしまうので、
Wait 関数を使ってスリープ状態を作ってあげなければなりません。
多少、持続時間に余裕を持たせてあげた方がいいでしょう。


□ PlayToneEx 関数
---
PlayToneEx(frequency, duration, volume, bLoop) Function

トーンを、周波数、持続時間、音量を指定して鳴らす。周波数は
Hz、持続時間はミリ秒、音量は 0 (なし) から 4 (最大)を指定す
る。

例:
PlayToneEx(440, 500, 2, false);
---


□ 周波数はつぎの表によります。

---
Sound  3   4   5   6    7    8    9
B     247 494 988 1976 3951 7902
A#    233 466 932 1865 3729 7458
A     220 440 880 1760 3520 7040 14080
G#        415 831 1661 3322 6644 13288
G         392 784 1568 3136 6272 12544
F#        370 740 1480 2960 5920 11840
F         349 698 1397 2794 5588 11176
E         330 659 1319 2637 5274 10548
D#        311 622 1245 2489 4978 9956
D         294 587 1175 2349 4699 9398
C#        277 554 1109 2217 4435 8870
C         262 523 1047 2093 4186 8372
---




■ トーンを鳴らすマクロ

PlayingMusic01 と同じであるが、PlayToneEx 関数と Wait 関数を
使ったマクロ PLAY_TONE を作る。引数は PlayToneEx に加えて、
間隔時間として interval を指定する。duration + interval で、
Wait 関数の時間とする。
ついでに、音階 A を 3 から 9 まで鳴らしてみる。

---
/**
 * PlayingMusic02.nxc
 * 「トライボット」使用
 * 音を鳴らす。
 * @author maruno
 * @version 1.0, 2008-01-12
 * @since 1.0
 */
#include "NXCDefs.h"

#define PLAY_TONE(frequency, duration, volume, bLoop, interval) \
    do { \
        PlayToneEx((frequency), (duration), (volume), (bLoop)); \
        Wait((duration)+(interval)); \
    } while(false)

task main()
{
    // 音階6 を B から C まで
    PLAY_TONE(1976, 400, 2, false, 100);
    PLAY_TONE(1865, 400, 2, false, 100);
    PLAY_TONE(1760, 400, 2, false, 100);
    PLAY_TONE(1661, 400, 2, false, 100);
    PLAY_TONE(1568, 400, 2, false, 100);
    PLAY_TONE(1480, 400, 2, false, 100);
    PLAY_TONE(1397, 400, 2, false, 100);
    PLAY_TONE(1319, 400, 2, false, 100);
    PLAY_TONE(1245, 400, 2, false, 100);
    PLAY_TONE(1175, 400, 2, false, 100);
    PLAY_TONE(1109, 400, 2, false, 100);
    PLAY_TONE(1047, 400, 2, false, 100);

    Wait(500);
    
    // 音階A を 3 から 9 まで
    PLAY_TONE(220, 400, 2, false, 100);
    PLAY_TONE(440, 400, 2, false, 100);
    PLAY_TONE(880, 400, 2, false, 100);
    PLAY_TONE(1760, 400, 2, false, 100);
    PLAY_TONE(3520, 400, 2, false, 100);
    PLAY_TONE(7040, 400, 2, false, 100);
    PLAY_TONE(14080, 400, 2, false, 100);
}
---



■ 実際の音楽っぽく

つぎは、ある曲を実装したものです。
楽譜を基に実装したのだが、まったく違うものらしい。
わたしの楽譜の読み方が違うのか、周波数のトーンが間違っている
のか?
(中学の音楽は 1 がついたこともあったくらいなので...)

---
/**
 * PlayingMusic03.nxc
 * 「トライボット」使用
 * 音を鳴らす。
 * @author maruno
 * @version 1.0, 2008-01-12
 * @since 1.0
 */
#include "NXCDefs.h"

#define FR_B3  247
#define FR_B4  494
#define FR_B5  988
#define FR_B6  1976
#define FR_B7  3951
#define FR_B8  7902

#define FR_AS3 233
#define FR_AS4 466
#define FR_AS5 932
#define FR_AS6 1865
#define FR_AS7 3729
#define FR_AS8 7458

#define FR_A3  220
#define FR_A4  440
#define FR_A5  880
#define FR_A6  1760
#define FR_A7  3520
#define FR_A8  7040
#define FR_A9  14080

#define FR_GS4 415
#define FR_GS5 831
#define FR_GS6 1661
#define FR_GS7 3322
#define FR_GS8 6644
#define FR_GS9 13288

#define FR_G4  392
#define FR_G5  784
#define FR_G6  1568
#define FR_G7  3136
#define FR_G8  6272
#define FR_G9  12544

#define FR_FS4 370
#define FR_FS5 740
#define FR_FS6 1480
#define FR_FS7 2960
#define FR_FS8 5920
#define FR_FS9 11840

#define FR_F4  349
#define FR_F5  698
#define FR_F6  1397
#define FR_F7  2794
#define FR_F8  5588
#define FR_F9  11176

#define FR_E4  330
#define FR_E5  659
#define FR_E6  1319
#define FR_E7  2637
#define FR_E8  5274
#define FR_E9  10548

#define FR_DS4 311
#define FR_DS5 622
#define FR_DS6 1245
#define FR_DS7 2489
#define FR_DS8 4978
#define FR_DS9 9956

#define FR_D4  294
#define FR_D5  587
#define FR_D6  1175
#define FR_D7  2349
#define FR_D8  4699
#define FR_D9  9398

#define FR_CS4 277
#define FR_CS5 554
#define FR_CS6 1109
#define FR_CS7 2217
#define FR_CS8 4435
#define FR_CS9 8870

#define FR_C4  262
#define FR_C5  523
#define FR_C6  1047
#define FR_C7  2093
#define FR_C8  4186
#define FR_C9  8372

#define NOTE_SEMIBREVE 1200                 // 全音符
#define NOTE_MINIM     (NOTE_SEMIBREVE / 2) // 二分音符
#define NOTE_CROTCHET  (NOTE_MINIM     / 2) // 四分音符
#define NOTE_QUAVER    (NOTE_CROTCHET  / 2) // 八分音符

#define PLAY_TONE(frequency, duration, volume, bLoop, interval) \
    do { \
        PlayToneEx((frequency), (duration), (volume), (bLoop)); \
        Wait((duration)+(interval)); \
    } while(false)

#define INTERVAL 80

task main()
{
    PLAY_TONE(FR_C6,  NOTE_MINIM,    2, false, INTERVAL);
    PLAY_TONE(FR_C5,  NOTE_QUAVER,   2, false, INTERVAL);
    PLAY_TONE(FR_C4,  NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_C5,  NOTE_CROTCHET, 2, false, INTERVAL);

    PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET);

    PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET);

    PLAY_TONE(FR_G6,  NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_G8,  NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_G8,  NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET);

    PLAY_TONE(FR_C6,  NOTE_MINIM,    2, false, INTERVAL);
    PLAY_TONE(FR_C5,  NOTE_QUAVER,   2, false, INTERVAL);
    PLAY_TONE(FR_C4,  NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_C5,  NOTE_CROTCHET, 2, false, INTERVAL);

    PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_AS6, NOTE_CROTCHET, 2, false, INTERVAL + NOTE_CROTCHET);

    PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_DS5, NOTE_CROTCHET, 2, false, INTERVAL);
    PLAY_TONE(FR_DS6, NOTE_MINIM,    2, false, INTERVAL);
    PLAY_TONE(FR_DS5, NOTE_QUAVER,   2, false, INTERVAL);

    PLAY_TONE(FR_C4, NOTE_SEMIBREVE, 2, false, INTERVAL);
}
---


周波数をあらわすマクロなどもまとめて、ヘッダーファイルにしておくといいでしょう。

以上


最新の画像もっと見る

コメントを投稿