cc65というファミコン用のc言語開発環境でゲームを作っているTKOZです。
このサイトには大変お世話になっております。
ところで、ファミコンの矩形波でドレミファソラシドは再生できたのですが、#(シャープ)の
音を鳴らすにはどうすればいいのでしょうか?
↓のサイトはドレミをレジスタに設定するときに周波数を計算するときに参考にしたサイトです。
http://panna.dyndns.org/etc/onritu.html
http://hp.vector.co.jp/authors/VA042397/nes/apu.html
ファミコンの矩形波で#を鳴らすには??
Re:ファミコンの矩形波で#を鳴らすには??
#は半音上げる分けですから、下のサイトの様な周波数になります。
http://homepage1.nifty.com/toshio-k/inspi/interval.html
ミとシには#は存在しません → 鍵盤を見ると分かります。
http://homepage1.nifty.com/toshio-k/inspi/interval.html
ミとシには#は存在しません → 鍵盤を見ると分かります。
Re:ファミコンの矩形波で#を鳴らすには??
>>softyaさん
情報ありがとうございます。
2段階の変換を関数電卓で計算して、
テーブルにしました。
loとhiの2つのテーブルと、あの曲のmusictblです。
聴けば分かります。w
はじめてのチュウです。
一応、ソース書いときます。
情報ありがとうございます。
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; }
Re:ファミコンの矩形波で#を鳴らすには??
鳴らしてみれば分かるのですが、途中で「プツ」と変な音が鳴ります。
電卓での計算違いか、もしくは、曲データの打ち間違えか、分かりませんが、
とりあえず、デバッグしてみます。
電卓での計算違いか、もしくは、曲データの打ち間違えか、分かりませんが、
とりあえず、デバッグしてみます。
Re:ファミコンの矩形波で#を鳴らすには??
PSG系のサウンドドライバを見た事があるので、私も後でコードを検証しますよ。
ただ、ちょっと後になっちゃいます。
勘では、必要無いのにPSGのレジスタ毎フレーム書き換えてません?
ただ、ちょっと後になっちゃいます。
勘では、必要無いのにPSGのレジスタ毎フレーム書き換えてません?
Re:ファミコンの矩形波で#を鳴らすには??
とりあえず、見つけたバグだけ。
> 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
> 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
Re:ファミコンの矩形波で#を鳴らすには??
>>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音源では無いですよね。
そうですね。違うと思います。
ヒントをくれてくださり、ありがとうございます。
バグを見つけてくださり、ありがとうございます。
とりあえず、
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音源では無いですよね。
そうですね。違うと思います。
ヒントをくれてくださり、ありがとうございます。