RGKT-NDS-STDY-018(008)
よくよく考えてみたら300行超えてるようなソースを
誰がサンプルコードとしてみてくれるだろうか。
少なくとも俺は、他に最適でシンプルなコードがあったらそちらを参考にすると思う。
最低限の動作確認に必要な箇所と最低限のUIの操作感を考慮すると
このぐらいのコード量になってしまったっというか。言い訳です。ええ。(−−;
なんてこと思ってたら
とりあえず公開しちゃって良いかって気分になってきたんで公開しときます。
ぶっちゃけサンプルとしてじゃなく俺が楽しんで且つ理解するために
勢い任せで書いちゃったのがコード量肥大化の原因な気がします。
もっともっとハードコーディングで利便性よりも関数動作の分かり易さとかを念頭に書くべきだったと
今更ながら後悔してたり。
もうちょっとシンプルなコードを
改めて書くかも知れないです。(´・ω・`)
PSG Func check program. (ソースコード)
/*--------------------------------------------------------------------------------- PSG Func Check Program. Feb 18, 2009 - Feb 23, 2009 1st Release(source code only). CODING BY. AYUMI.KAWAI @REGEKATSU ADVISER BY. YUKI.INOUE @REGEKATSU This program was made from devkitPro Version 1-4-9. REGEKATSU -Console/Homebrew Programming- this web site. http://akiba.geocities.jp/consolehomebrewprogramming/ ---------------------------------------------------------------------------------*/ #include <nds.h> #include <stdio.h> //def DutyCycle #define DutyCycle_BaseNum 12.5f #define DutyCycle_MinNum 0 #define DutyCycle_MaxNum 7 //def VOLUME typedef enum{ VOLUME_MIN_NUM = 0, VOLUME_MAX_NUM = 127, VOLUME_DEF_NUM = 63 }VOLUME_NUM; //def PAN typedef enum{ PAN_MIN_NUM = 0, PAN_MAX_NUM = 127, PAN_DEF_NUM = 63 }PAN_NUM; //def OCTAVE typedef enum{ OCTAVE_MIN_NUM = 0, OCTAVE_MAX_NUM = 5, OCTAVE_DEF_NUM = 2, OCTAVE_BASE_NUM = 12 }OCTAVE_NUM; typedef enum{ OCTAVE_UP = 1, OCTAVE_DOWN = -1, OCTAVE_NEUTRAL = 0 }OCTAVE_MODE; //def NOTE #define NOTE_MIN_NUM 0 #define NOTE_MAX_NUM 71 typedef enum{ NOTE_NULL = -1, NOTE_C = 0, NOTE_C_SHARP = 1, NOTE_D = 2, NOTE_D_SHARP = 3, NOTE_E = 4, NOTE_F = 5, NOTE_F_SHARP = 6, NOTE_G = 7, NOTE_G_SHARP = 8, NOTE_A = 9, NOTE_A_SHARP = 10, NOTE_B = 11, NOTE_SHARP_TRUE = 1, NOTE_SHARP_FALSE = 0 }NOTE_DATA; //def KEY_SELECT INPUT MODE typedef enum{ OCTAVE_CHANGE_DISABLE, OCTAVE_CHANGE_ENABLE }OCTAVE_CHANGE_MODE; //PSG FreqTable. 6 octaves, One dimension 72 arrays. //平均律を10倍して小数点以下を四捨五入で切り捨てた値をテーブルとして持ち、 //テーブルにあるベース周波数を×8倍し、÷10でNDS用に最適化して、 //その値を周波数値として渡し、soundPlayPSG() 関数にて再生している。 uint16 freq_table[] = { // +0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, // C, C+, D, D+, E, F, F+, G, G+, A, A+, B, /* octave 0 */ 654, 693, 734, 778, 824, 873, 925, 980, 1038, 1100, 1165, 1235, /* octave 1 */ 1308, 1386, 1468, 1556, 1648, 1746, 1850, 1960, 2077, 2200, 2331, 2469, /* octave 2 */ 2616, 2772, 2937, 3111, 3296, 3492, 3700, 3920, 4153, 4400, 4662, 4939, /* octave 3 */ 5233, 5444, 5873, 6223, 6593, 6985, 7400, 7840, 8306, 8800, 9323, 9878, /* octave 4 */ 10465, 11087, 11747, 12445, 13185, 13969, 14800, 15680, 16612, 17600, 18647, 19755, /* octave 5 */ 20930, 22175, 23493, 24890, 26370, 27938, 29600, 31360, 33224, 35200, 37293, 39511 }; //main routine int main(void) { DutyCycle set_duty_cycle = DutyCycle_12; //set DutyCycle float draw_duty_cycle = DutyCycle_BaseNum; //draw DutyCycle int cur_octave = OCTAVE_DEF_NUM; //current octave status int now_octave_mode = OCTAVE_NEUTRAL; //now octave up/down mode status OCTAVE_MODE octave_mode = OCTAVE_UP; //KEY_R octave up/down mode status int set_note = NOTE_NULL; //set note(C-HC) data uint16 set_freq = 0; //set freq(nds optimized) data u8 set_volume = VOLUME_DEF_NUM; //set volume(0-127) data u8 set_pan = PAN_DEF_NUM; //set pan(0-127) data OCTAVE_CHANGE_MODE octave_change_mode = OCTAVE_CHANGE_ENABLE; //KEY_SELECT change octave mode uint32 kdr_status = 0; //keyDownRepeat status int sound_id = 0; //sound channel id(number) //initialize console consoleDemoInit(); //console font color change BG_PALETTE_SUB[255] = RGB15(0, 31, 0); //draw lcd on top lcdSwap(); //draw copyright iprintf("\x1b[0;0HPSG Func check program."); iprintf("\x1b[1;0HFeb 22, 2009"); iprintf("\x1b[2;0HCODING BY. AYUMI.K @REGEKATSU"); //draw layout iprintf("\x1b[5;2HK_L\x1b[6;2H+"); //KEY_L note sharp iprintf("\x1b[5;26HK_R\x1b[6;26HUP "); //KEY_R octave up/down iprintf("\x1b[7;6HK_UP\x1b[8;6HE"); //KEY_UP E iprintf("\x1b[9;2HK_LF\x1b[10;2HD"); //KEY_LEFT D iprintf("\x1b[9;10HK_RI\x1b[10;10HF"); //KEY_RIGHT F iprintf("\x1b[11;6HK_DN\x1b[12;6HC"); //KEY_DOWN C iprintf("\x1b[7;22HK_X\x1b[8;22HHC"); //KEY_X HC iprintf("\x1b[9;18HK_Y\x1b[10;18HG"); //KEY_Y G iprintf("\x1b[9;26HK_A\x1b[10;26HB"); //KEY_A B iprintf("\x1b[11;22HK_B\x1b[12;22HA"); //KEY_B A printf("\x1b[15;2HK_ST Duty Cycle %04.1f%% (%d)", draw_duty_cycle, set_duty_cycle); iprintf("\x1b[16;2HK_SL Change Octave UP/DN"); iprintf("\x1b[17;3H+K_R Inc/Dec Oct UP/DN"); iprintf("\x1b[18;3H+K_UP/DN Inc/Dec Vol %03d", set_volume); iprintf("\x1b[19;3H+K_LF/RI L/R Pan %03d", set_pan); iprintf("\x1b[20;2HCurrent Octave Num %d", cur_octave); iprintf("\x1b[21;2HInput Keys State "); iprintf("\x1b[22;2Hfreq_table[ ] == 0000Hz"); //doraw 12 equal temperament) //set keysSetRepeat keysSetRepeat(30, 6); //initialize sound play soundEnable(); //main loop while(1) { //get keys status scanKeys(); kdr_status = keysDownRepeat(); //set base note if(keysHeld() & KEY_DOWN){ //note DO set_note = NOTE_C; printf("\x1b[21;20HC "); }else if(keysHeld() & KEY_LEFT){ //note RE set_note = NOTE_D; printf("\x1b[21;20HD "); }else if(keysHeld() & KEY_UP){ //note MI set_note = NOTE_E; printf("\x1b[21;20HE "); }else if(keysHeld() & KEY_RIGHT){ //note FA set_note = NOTE_F; printf("\x1b[21;20HF "); }else if(keysHeld() & KEY_Y){ //note SO set_note = NOTE_G; printf("\x1b[21;20HG "); }else if(keysHeld() & KEY_B){ //note RA set_note = NOTE_A; printf("\x1b[21;20HA "); }else if(keysHeld() & KEY_A){ //note SHI set_note = NOTE_B; printf("\x1b[21;20HB "); }else if(keysHeld() & KEY_X){ //note HighDO set_note = NOTE_C + (OCTAVE_BASE_NUM * OCTAVE_UP); printf("\x1b[21;20HHC"); }else{ //note free set_note = NOTE_NULL; printf("\x1b[21;20H "); } //set note sharp if(keysHeld() & KEY_L){ if((set_note == NOTE_E) || (set_note == NOTE_B) || (set_note == NOTE_NULL)) set_note += NOTE_SHARP_FALSE; else set_note += NOTE_SHARP_TRUE; printf("\x1b[21;22H+L"); }else{ printf("\x1b[21;22H "); } //select button enhancing operation if(keysHeld() & KEY_SELECT){ //PSG sound play off set_note = NOTE_NULL; //increment current octave if(kdr_status & KEY_R){ if(cur_octave < OCTAVE_MAX_NUM) cur_octave++; else if(cur_octave >= OCTAVE_MAX_NUM) cur_octave = OCTAVE_MIN_NUM; printf("\x1b[20;22H%d", cur_octave); } //increment volume else if(kdr_status & KEY_UP){ if(set_volume < VOLUME_MAX_NUM) set_volume++; else if(set_volume >= VOLUME_MAX_NUM) set_volume = VOLUME_MIN_NUM; printf("\x1b[18;26H%03d", set_volume); } //decrement volume else if(kdr_status & KEY_DOWN){ if(set_volume > VOLUME_MIN_NUM) set_volume--; else if(set_volume <= VOLUME_MIN_NUM) set_volume = VOLUME_MAX_NUM; printf("\x1b[18;26H%03d", set_volume); } //increment pan else if(kdr_status & KEY_RIGHT){ if(set_pan < PAN_MAX_NUM) set_pan++; else if(set_pan >= PAN_MAX_NUM) set_pan = PAN_MIN_NUM; printf("\x1b[19;22H%03d", set_pan); } //decrement pan else if(kdr_status & KEY_LEFT){ if(set_pan > PAN_MIN_NUM) set_pan--; else if(set_pan <= PAN_MIN_NUM) set_pan = PAN_MAX_NUM; printf("\x1b[19;22H%03d", set_pan); } //セレクトボタン+他キーの組合わせ入力(拡張操作)があった場合、 //次回セレクト押下までの間、オクターブチェンジを無効にする。 if(keysDown() & (KEY_R | KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT)) octave_change_mode = OCTAVE_CHANGE_DISABLE; } //change octave up down else if(keysUp() & KEY_SELECT){ if(octave_change_mode){ //change octave mode Enable if(octave_mode == OCTAVE_UP){ //change octave down octave_mode = OCTAVE_DOWN; printf("\x1b[6;26HDOWN"); }else{ //change octave up octave_mode = OCTAVE_UP; printf("\x1b[6;26HUP "); } }else{ //change octave mode Disable octave_change_mode = OCTAVE_CHANGE_ENABLE; } } //set octave up down if(keysHeld() & KEY_R){ //set on octave up down now_octave_mode = octave_mode; printf("\x1b[21;24H+R"); }else{ //set off octave up down now_octave_mode = OCTAVE_NEUTRAL; printf("\x1b[21;24H "); } //set duty cycle if(kdr_status & KEY_START){ if(set_duty_cycle < 7) set_duty_cycle++; else if(set_duty_cycle >= 7) set_duty_cycle = DutyCycle_12; //draw duty cycle draw_duty_cycle = (set_duty_cycle == 7)?0.0f:DutyCycle_BaseNum * (set_duty_cycle + 1); printf("\x1b[15;20H%04.1f%% (%d)", draw_duty_cycle, set_duty_cycle); } //set note data if(set_note != NOTE_NULL){ //is note data //1st overflow check if((set_note + cur_octave * OCTAVE_BASE_NUM) < NOTE_MIN_NUM) //note lower overflow set_note = set_note + ((cur_octave + 1) * OCTAVE_BASE_NUM); else if((set_note + cur_octave * OCTAVE_BASE_NUM) > NOTE_MAX_NUM) //note upper overflow set_note = set_note + ((cur_octave - 1) * OCTAVE_BASE_NUM); //2nd overflow check else if((set_note + ((cur_octave + now_octave_mode) * OCTAVE_BASE_NUM)) < NOTE_MIN_NUM) //note lower overflow set_note = set_note + cur_octave * OCTAVE_BASE_NUM; else if((set_note + ((cur_octave + now_octave_mode) * OCTAVE_BASE_NUM)) > NOTE_MAX_NUM) //note upper overflow set_note = set_note + cur_octave * OCTAVE_BASE_NUM; //note no overflow else set_note = set_note + ((cur_octave + now_octave_mode) * OCTAVE_BASE_NUM); } //play and draw note data if(set_note != NOTE_NULL){ //is note data if(keysDown() & (KEY_UP | KEY_DOWN | KEY_LEFT | KEY_RIGHT | KEY_A | KEY_B | KEY_X | KEY_Y | KEY_L | KEY_R | KEY_START)){ soundPause(sound_id); //set freq is optimized for nds set_freq = freq_table[set_note] * 8 / 10; sound_id = soundPlayPSG(set_duty_cycle, set_freq, set_volume, set_pan); } //draw 12 equal temperament iprintf("\x1b[22;12H[%02d] == %04dHz", set_note, freq_table[set_note] / 10); }else{ //no note data soundPause(sound_id); iprintf("\x1b[22;12H[ ] == 0000Hz"); } swiWaitForVBlank(); } return 0; }