ファミコンの矩形波で#を鳴らすには??

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
KEYONN_

ファミコンの矩形波で#を鳴らすには??

#1

投稿記事 by KEYONN_ » 15年前

cc65というファミコン用のc言語開発環境でゲームを作っているTKOZです。
このサイトには大変お世話になっております。

ところで、ファミコンの矩形波でドレミファソラシドは再生できたのですが、#(シャープ)の
音を鳴らすにはどうすればいいのでしょうか?

↓のサイトはドレミをレジスタに設定するときに周波数を計算するときに参考にしたサイトです。
http://panna.dyndns.org/etc/onritu.html
http://hp.vector.co.jp/authors/VA042397/nes/apu.html

softya

Re:ファミコンの矩形波で#を鳴らすには??

#2

投稿記事 by softya » 15年前

#は半音上げる分けですから、下のサイトの様な周波数になります。
http://homepage1.nifty.com/toshio-k/inspi/interval.html
ミとシには#は存在しません → 鍵盤を見ると分かります。

KEYONN_

Re:ファミコンの矩形波で#を鳴らすには??

#3

投稿記事 by KEYONN_ » 15年前

>>softyaさん
情報ありがとうございます。
2段階の変換を関数電卓で計算して、
テーブルにしました。

loとhiの2つのテーブルと、あの曲のmusictblです。

聴けば分かります。w

はじめてのチュウです。

一応、ソース書いときます。
#define APU_CH1_REG0 (*(unsigned char*)0x4000)
#define APU_CH1_REG1 (*(unsigned char*)0x4001)
#define APU_CH1_REG2 (*(unsigned char*)0x4002)
#define APU_CH1_REG3 (*(unsigned char*)0x4003)
#define APU_PLAY_CH  (*(unsigned char*)0x4015)
#define APU_REG0_DUTY_875  0x00
#define APU_REG0_DUTY_750  0x40
#define APU_REG0_DUTY_500  0x80
#define APU_REG0_DUTY_250  0xC0
#define APU_REG0_COUNT_OFF 0x00
#define APU_REG0_COUNT_ON  0x20
#define APU_REG0_FIX_OFF   0x00
#define APU_REG0_FIX_ON    0x10
#define APU_REG1_FRQCHG_ON  0x80
#define APU_REG1_FRQCHG_OFF 0x00
#define APU_REG1_FRQCHG_DSC 0x08
#define APU_REG1_FRQCHG_ASC 0x00

#define DO 0
#define DOS 1
#define RE 2
#define RES 3
#define MI 4
#define FA 5
#define FAS 6
#define SO 7
#define SOS 8
#define RA 9
#define RAS 10
#define SI 11
#define DO2 12
#define DOS2 13
#define RE2 14
#define RES2 15
#define MI2 16
#define FA2 17
#define FAS2 18
#define SO2 19
#define SOS2 20
#define RA2 21
#define RAS2 22
#define SI2 23
#define DO3 24
#define ST 25
#define END 26
#define REST 27

// スクリーンのオン・オフ
void ShowScreen(char ShowFlag)
{
    if (ShowFlag == 1) {
        *(char*)0x2000 = 0x08;
        *(char*)0x2001 = 0x1e;
    } else {
        *(char*)0x2000 = 0x00;
        *(char*)0x2001 = 0x00;
    }
}

// スクロール設定
void SetScroll(unsigned char x, unsigned char y)
{
    *(char*)0x2005 = x;
    *(char*)0x2005 = y;
}

void SoundPlay(unsigned char note, unsigned char vol)
{
    unsigned char scale_hi3[/url]={  1,   1,   1,  1,    1,   1,   1,  1,  1,     0,   0,   0,
                                 0,   0,   0,   0,   0,   0,   0,  0,  0,     0,   0,   0,
                                 0};
    							 
    unsigned char scale_lo3[/url]={171, 149 ,125, 104, 83,  64,   46, 29,  14,  254, 240, 188,
                               214, 201, 190, 179, 170, 160, 151, 143, 134, 127, 120, 113,
                               107};
    vol &= 0x0F;
    APU_PLAY_CH = 0x0B;
    APU_CH1_REG0 = APU_REG0_DUTY_875 | APU_REG0_COUNT_ON | APU_REG0_FIX_ON | vol;
    APU_CH1_REG1 = APU_REG1_FRQCHG_ON;
    
    if(scale_lo3[note]==REST) return;
    
    APU_CH1_REG2 = scale_lo3[note];
    APU_CH1_REG3 = 0xF8 | scale_hi3[note];
    
}

// メイン関数
char NesMain()
{
    const char palettes[/url] = {
        0x0f, 0x00, 0x10, 0x20,
        0x0f, 0x06, 0x16, 0x26,
        0x0f, 0x08, 0x18, 0x28,
        0x0f, 0x0a, 0x1a, 0x2a
    };
    const char string[/url] = "HELLO, MUSIC!";
    char msctbl[/url]={
    DO2,RA,SO,FA,FA,SO,RA,DO2,RE2,DO2,REST,REST,DO2,RA,SO,FA,FA,SO,//18
    RA,DO2,RE2,DO2,REST,REST,MI,SO,DO2,RA,SO,SO,SO,FA,//14
    REST,REST,FA,SO,FA,RA,SO,FA,FA,SO,RA,REST,RA,DO2,RE2,DO2,RA,//17
    SO,FA,FA,FA,SO,FA,RA,SO,FA,FA,REST,FA,FA,RA,DO2,DO2,DO2,//17
    RE2,RA,SO,FA,REST,REST,FA,FA,RA,DO2,DO2,DO2,RE2,RA,SO,//15
    FA,REST,REST,SI,RE2,REST,SI,SI,RE2,REST,MI2,MI2,//12
    FAS2,REST,MI2,MI2,FAS2,MI2,RE2,REST,RA,RA,SO,FA,//12
    RA,RE2,DO2,REST,REST,FA,FA,RA,RE2,DO2,REST,RA,DO2,FA2,FA2,//15
    RE2,RA,DO2,REST,RA,DO2,FA2,SO2,FA2,DOS2,DO2,MI2,//12
    RE2,RA,SO,SO,RE2,MI2,RE2,DO2,REST,RA,RA,SO,FA,RA,//14
    RE2,DO2,REST,FA,FA,RA,RE2,DO2,REST,RA,DO2,FA2,FA2,RE2,//14
    RA,DO2,REST,RA,DO2,FA2,SO2,FA2,DOS2,DO2,MI2,RE2,RA,//13
    REST,REST,SO,SO,RE2,RE2,DO2,DO2,RE2,RA,SO,SO,FA,//13
    REST,DO2,RA,SO,FA,FA,SO,RA,DO2,RE2,DO2,REST,REST,//14
    DO2,RA,SO,FA,FA,SO,RA,DO2,RE2,DO2,REST,RA,DO2,REST,REST,REST,REST,REST};//18
    unsigned char i;
	long int cnt=0;
	char index=0;
	
    ShowScreen(0);

    // パレットを書き込み
    *(char*)0x2006 = 0x3f;
    *(char*)0x2006 = 0x00;
    for (i = 0; i < 0x10; i ++)
        *(char*)0x2007 = palettes;

    // ネームテーブルへ書き込み
    *(char*)0x2006 = 0x21;
    *(char*)0x2006 = 0xc9;
    for (i = 0; i < 13; i ++)
        *(char*)0x2007 = string;

    SetScroll(0, 0);
    ShowScreen(1);
    

    // 無限ループ
    while (1){
    	cnt++;
    	if(cnt>960)
    	{
    		cnt=0;
    		SoundPlay(msctbl[index],8);
    		index++;
    		if(index>217)index=0;
    	}
    }

    return 0;
}

KEYONN_

Re:ファミコンの矩形波で#を鳴らすには??

#4

投稿記事 by KEYONN_ » 15年前

鳴らしてみれば分かるのですが、途中で「プツ」と変な音が鳴ります。
電卓での計算違いか、もしくは、曲データの打ち間違えか、分かりませんが、
とりあえず、デバッグしてみます。

softya

Re:ファミコンの矩形波で#を鳴らすには??

#5

投稿記事 by softya » 15年前

PSG系のサウンドドライバを見た事があるので、私も後でコードを検証しますよ。
ただ、ちょっと後になっちゃいます。

勘では、必要無いのにPSGのレジスタ毎フレーム書き換えてません?

softya

Re:ファミコンの矩形波で#を鳴らすには??

#6

投稿記事 by softya » 15年前

とりあえず、見つけたバグだけ。

> if(scale_lo3[note]==REST) return;
if(note==REST) return;
が正解では?

それと、

再生方法
1. I/O【0x4015】で設定するチャンネルの再生をオフにする
2. チャンネルのレジスタに情報を設定
3. I/O【0x4015】で設定したチャンネルの再生をオンにする

を守ってませんが、鳴っている最中に「チャンネルのレジスタに情報を設定」するとノイズが出ると思います。

パッと目に付いたところだけなので、また明日みてみます。
理由:NESのAPUの仕様はPSGより複雑だったため。

ところで、NES研究所の「FM音源4チャンネルとPCM音源1チャンネル」と書いてありますが、どうみてもFM音源では無いですよね。
http://ja.wikipedia.org/wiki/FM%E9%9F%B3%E6%BA%90

KEYONN_

Re:ファミコンの矩形波で#を鳴らすには??

#7

投稿記事 by KEYONN_ » 15年前

>>softyaさんへ
バグを見つけてくださり、ありがとうございます。

とりあえず、
if(note==REST) return;
にしたら、ノイズが無くなったので、報告しておきます。

しかし、音がnote==RESTになった時に、音色の再生が止まらなくなったので、
困りました。

で、その後、このif文を
APU_PLAY_CH=0x0B;
の上に置き、さらに、
if(note==REST){APU_PLAY_CH==0x00;return;}
としました。

>ところで、NES研究所の「FM音源4チャンネルとPCM音源1チャンネル」と
>書いてありますが、どうみてもFM音源では無いですよね。
そうですね。違うと思います。

ヒントをくれてくださり、ありがとうございます。

softya

Re:ファミコンの矩形波で#を鳴らすには??

#8

投稿記事 by softya » 15年前

えーと、解決したって事でしょうか?

KEYONN_

Re:ファミコンの矩形波で#を鳴らすには??

#9

投稿記事 by KEYONN_ » 15年前

そうです。解決しました。
解決ボタンを押すのを忘れてました。
ありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る