/* SoundKey.c David T. Jarvis Atari ST -- Lattice C -- Version 052686 */ #define SPACE_K 32 /* space key */ #define ESC_K 27 /* ESC key */ #define RETURN_K 13 /* return key */ #define DURA 1000 /* note duration */ #define TUNE_INC 6 /* adjust tuning by this much */ #define MAX_OCT 6 /* maximum octave */ #define MAX_VOL 15 /* maximum volume */ #define MAX_WAV 15 /* maximum waveform */ #define N_P_OCT 15 /* notes per octave */ #define MOUS_OFF 256 /* disable mouse */ #define MOUS_ON 257 /* enable mouse */ #define T_OUTLINE 0x10 /* text style--outline */ #define T_NORMAL 0x0 /* text style--normal */ #define T_SKEWED 0x0004 /* text style--skewed */ #define T_THICK 0X0001 /* text style--thick */ #define CH_ENA_R 7 /* voice channel enable(read) */ #define CH_ALO_W 128 /* channel,voice a lo,write */ #define CH_AHI_W 129 /* channel,voice a hi,write */ #define CH_BLO_W 130 /* " , " b lo, " */ #define CH_BHI_W 131 /* " , " b hi, " */ #define CH_CLO_W 132 /* " , " c lo, " */ #define CH_CHI_W 133 /* " , " c hi, " */ #define CH_ENA_W 135 /* voice channel enable(write) */ #define CH_AVL_W 136 /* channel a volume, write */ #define CH_BVL_W 137 /* " b " , " */ #define CH_CVL_W 138 /* " c " , " */ #define RG_ENV_W 140 /* envelope register, write */ #define RG_WAV_W 141 /* waveform register, write */ #define CONTERM 0X484 /* attributes of console */ #include /* standard io library */ #include /* GEMDOS,BIOS,XBIOS macros */ #include /* character type macros */ #define Supexec(a) xbios(38,a) /* Exec routine,supervisor mode */ /* play contains the numbers to plug into the ST sound chip */ short int play[ MAX_OCT ][ N_P_OCT ] = { { 3906,3689,3472,3189,3048,2906,2728,2551,2411,2272,2160,2049,1923,1817,1712 }, { 1923,1817,1712,1633,1524,1436,1350,1275,1205,1136,1076,1016,954,902,850 }, { 954,902,850,807,757,714,675,637,602,568,537,506,477,451,425 }, { 477,451,425,401,378,358,338,318,301,284,268,253,239,225,212 }, { 239,225,212,200,189,179,169,159,150,142,134,126,119,112,106 }, { 119,112,106,100, 94, 89, 84, 79, 75, 71, 67, 63, 59, 54, 51 } }; short int contrl[12], intin[256], intout[256], ptsin[256], ptsout[256], workin[20], workout[100], handle, i, j, dvar, port_state, key_rate,fast_key = 1, x_note, y_note, z_note, old_note = 0; char c, x_low, x_high, y_low, y_high, z_low, z_high; char *std_msg = "Press ESC to Exit "; short int hold_n = 0, /* flag-- hold notes */ period = 10, /* period for sound waves */ wave = 0, /* waveform */ vol_a = MAX_VOL, /* voice a volume */ vol_b = MAX_VOL, /* voice b volume */ vol_c = MAX_VOL, /* voice c volume */ oct_a = 2, /* voice a octave */ oct_b = 2, /* voice b octave */ oct_c = 2, /* voice c octave */ tune = 6, /* tuning (added to pitch) */ tn_a=2,tn_b=2,tn_c=2, /* tuning for individual voices */ diss = 3; /* dissonance level */ int nonoise(); /* routine to disable noise */ main() { /* Check for correct resolution */ if (Getrez() != 1) { printf("Sorry, this program must be run in medium resolution.\n"); exit(0); } /* Initialize application */ appl_init(); handle=graf_handle( &dvar, &dvar, &dvar, &dvar ); for ( i = 0; i < 10; workin[ i++ ]=1 ); workin[ 10 ] = 2; v_opnvwk( workin, &handle, workout ); /* Hide mouse, disable keyclick,bell, speed up keyboard repeat rate */ graf_mouse( MOUS_OFF, 0 ); Supexec(nonoise); key_rate = Kbrate( 0x01,0x01 ); /* Initialize sound chip, enable channels a and b */ sound_off(); port_state = Giaccess( i, CH_ENA_R ); Giaccess( (port_state & 0xc0) | 56, CH_ENA_W ); /* Make music */ play_keys(); /* turn off the sound chip, restore initial state */ Giaccess( port_state, CH_ENA_W ); /* restore keyboard repeat rate, close application and exit */ Kbrate( (key_rate >> 8) & 0x00ff, key_rate & 0x00ff ); v_clsvwk( handle ); appl_exit(); } play_keys() { register char c=' ', c2=' '; keys_screen(); while (c != ESC_K) { if (Bconstat(2)) { vol_c = 0; c = Bconin(2); c = tolower(c); switch(c) { case '1': locate(22,1); put_msg( "H=>Higher, L=>Lower, RETURN=>Done "); x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 0 ] + tn_b; sound_on(); do { c2 = Bconin(2); c2 = tolower(c2); switch(c2) { case 'h': if (tune) { tune -= TUNE_INC; tn_a = tune/(oct_a+1); tn_b = tune/(oct_b+1); tn_c = tune/(oct_c+1); x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 0 ] + tn_b; sound_on(); dsp_vals(); } break; case 'l': if (tune < TUNE_INC*5) { tune += TUNE_INC; tn_a = tune/(oct_a+1); tn_b = tune/(oct_b+1); tn_c = tune/(oct_c+1); y_note = play[ oct_b ][ 0 ] + tn_b; x_note = play[ oct_a ][ 0 ] + tn_a; sound_on(); dsp_vals(); } break; default: break; } } while (c2 != RETURN_K ); sound_off(); put_msg( std_msg ); x_note = old_note; break; case '2': locate(22,1); put_msg( "M => More, L=>Less, RETURN=>Done "); x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 0 ] + tn_b + diss; sound_on(); do { c2 = Bconin(2); c2 = tolower(c2); switch(c2) { case 'l': if (diss) { diss--; x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 0 ] + tn_b + diss; sound_on(); dsp_vals(); } break; case 'm': if (diss < 7) { diss++; x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 0 ] + tn_b + diss; sound_on(); dsp_vals(); } break; default: break; } } while (c2 != RETURN_K ); sound_off(); put_msg( std_msg ); x_note = old_note; break; case '3': wave++; if (wave == 1) wave = 4; if (wave == 5) wave = 8; if (wave > MAX_WAV) wave = 0; Giaccess( wave, RG_WAV_W ); dsp_vals(); x_note = old_note; break; case '4': Kbrate((key_rate>>8)&0x00ff,key_rate&0x00ff); fast_key = 0; dsp_vals(); x_note = old_note; break; case '5': fast_key = 1; Kbrate( 0x01,0x01 ); dsp_vals(); x_note = old_note; break; case 'a': x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 0 ] + tn_b + diss; break; case 'w': x_note = play[ oct_a ][ 1 ] + tn_a; y_note = play[ oct_b ][ 1 ] + tn_b + diss; break; case 's': x_note = play[ oct_a ][ 2 ] + tn_a; y_note = play[ oct_b ][ 2 ] + tn_b + diss; break; case 'e': x_note = play[ oct_a ][ 3 ] + tn_a; y_note = play[ oct_b ][ 3 ] + tn_b + diss; break; case 'd': x_note = play[ oct_a ][ 4 ] + tn_a; y_note = play[ oct_b ][ 4 ] + tn_b + diss; break; case 'f': x_note = play[ oct_a ][ 5 ] + tn_a; y_note = play[ oct_b ][ 5 ] + tn_b + diss; break; case 't': x_note = play[ oct_a ][ 6 ] + tn_a; y_note = play[ oct_b ][ 6 ] + tn_b + diss; break; case 'g': x_note = play[ oct_a ][ 7 ] + tn_a; y_note = play[ oct_b ][ 7 ] + tn_b + diss; break; case 'u': x_note = play[ oct_a ][ 8 ] + tn_a; y_note = play[ oct_b ][ 8 ] + tn_b + diss; break; case 'j': x_note = play[ oct_a ][ 9 ] + tn_a; y_note = play[ oct_b ][ 9 ] + tn_b + diss; break; case 'i': x_note = play[ oct_a ][ 10 ] + tn_a; y_note = play[ oct_b ][ 10 ] + tn_b + diss; break; case 'k': x_note = play[ oct_a ][ 11 ] + tn_a; y_note = play[ oct_b ][ 11 ] + tn_b + diss; break; case 'o': x_note = play[ oct_a ][ 12 ] + tn_a; y_note = play[ oct_b ][ 12 ] + tn_b + diss; break; case 'l': x_note = play[ oct_a ][ 13 ] + tn_a; y_note = play[ oct_b ][ 13 ] + tn_b + diss; break; case 'p': x_note = play[ oct_a ][ 14 ] + tn_a; y_note = play[ oct_b ][ 14 ] + tn_b + diss; break; case 'z': x_note = play[ oct_a ][ 0 ] + tn_a; y_note = play[ oct_b ][ 4 ] + tn_b; z_note = play[ oct_c ][ 7 ] + tn_c; vol_c = vol_a; break; case 'x': x_note = play[ oct_a ][ 2 ] + tn_a; y_note = play[ oct_b ][ 5 ] + tn_b; z_note = play[ oct_c ][ 9 ] + tn_c; vol_c = vol_a; break; case 'c': x_note = play[ oct_a ][ 4 ] + tn_a; y_note = play[ oct_b ][ 7 ] + tn_b; z_note = play[ oct_c ][ 11 ] + tn_c; vol_c = vol_a; break; case 'v': x_note = play[ oct_a ][ 5 ] + tn_a; y_note = play[ oct_b ][ 9 ] + tn_b; z_note = play[ oct_c ][ 12 ] + tn_c; vol_c = vol_a; break; case 'b': x_note = play[ oct_a ][ 2 ] + tn_a; y_note = play[ oct_b ][ 7 ] + tn_b; z_note = play[ oct_c ][ 11 ] + tn_c; vol_c = vol_a; break; case 'n': x_note = play[ oct_a ][ 4 ] + tn_a; y_note = play[ oct_b ][ 9 ] + tn_b; z_note = play[ oct_c ][ 12 ] + tn_c; vol_c = vol_a; break; case 'm': x_note = play[ oct_a ][ 2 ] + tn_a; y_note = play[ oct_b ][ 5 ] + tn_b; z_note = play[ oct_c ][ 11 ] + tn_c; vol_c = vol_a; break; case ',': case '<': x_note = play[ oct_a ][ 4 ] + tn_a; y_note = play[ oct_b ][ 7 ] + tn_b; z_note = play[ oct_c ][ 12 ] + tn_c; vol_c = vol_a; break; case ']': oct_a++; oct_b++; oct_c++; if (oct_a > MAX_OCT) oct_a = 0; if (oct_b > MAX_OCT) oct_b = 0; if (oct_c > MAX_OCT) oct_c = 0; x_note = old_note; tn_a = tune/(oct_a+1); tn_b = tune/(oct_b+1); tn_c = tune/(oct_c+1); dsp_vals(); break; case '[': oct_a--; oct_b--; oct_c--; if (oct_a < 0) oct_a = MAX_OCT; if (oct_b < 0) oct_b = MAX_OCT; if (oct_c < 0) oct_c = MAX_OCT; x_note = old_note; tn_a = tune/(oct_a+1); tn_b = tune/(oct_b+1); tn_c = tune/(oct_c+1); dsp_vals(); break; case '}': oct_a++; if (oct_a > MAX_OCT) oct_a = 0; x_note = old_note; tn_a = tune/(oct_a+1); dsp_vals(); break; case '{': oct_a--; if (oct_a < 0) oct_a = MAX_OCT; x_note = old_note; tn_a = tune/(oct_a+1); dsp_vals(); break; case SPACE_K: x_note = old_note; hold_n = !hold_n; dsp_vals(); if (!hold_n) sound_off(); break; default: x_note = old_note; break; } if (x_note != old_note) { x_low = (char)(x_note); y_low = (char)(y_note); z_low = (char)(z_note); x_high = (char)(x_note >> 8); y_high = (char)(y_note >> 8); z_high = (char)(z_note >> 8); Giaccess( x_low, CH_ALO_W ); Giaccess( x_high, CH_AHI_W ); Giaccess( y_low, CH_BLO_W ); Giaccess( y_high, CH_BHI_W ); Giaccess( z_low, CH_CLO_W ); Giaccess( z_high, CH_CHI_W ); Giaccess( vol_a, CH_AVL_W ); Giaccess( vol_b, CH_BVL_W ); Giaccess( vol_c, CH_CVL_W ); j = 1; } } else { j++; if ((j == DURA) && (!hold_n)) { Giaccess( 0, CH_AVL_W ); Giaccess( 0, CH_BVL_W ); Giaccess( 0, CH_CVL_W ); } } } sound_off(); } keys_screen() { keys_menu(); /* Display control keys menu */ dsp_prms(); /* Display parameter names */ dsp_vals(); /* Display parameter values */ draw_kbd(); /* Draw a keyboard map */ author(); } keys_menu() { v_clrwk( handle ); empt_box(4,6,636,198,1); empt_box(8,18,312,102,3); vst_effects( handle, T_SKEWED ); vst_color( handle,2 ); v_gtext( handle, 264, 6, "ST SYNTHESIZER" ); vst_effects( handle, T_OUTLINE ); vst_color( handle,3 ); v_gtext( handle, 80, 16, "PARAMETER CONTROL" ); vst_effects( handle, T_NORMAL ); vst_color( handle,1 ); v_gtext( handle,16,30, "1 -- Tune Keyboard (on C)" ); v_gtext( handle,16,38, "2 -- Dissonance" ); v_gtext( handle,16,46, "3 -- Next Waveform" ); v_gtext( handle,16,54, "4,5 -- Slow/Fast Key Speed" ); v_gtext( handle,16,62, "[ -- Lower Octave, Both Voices"); v_gtext( handle,16,70, "] -- Higher Octave, Both Voices"); v_gtext( handle,16,78, "{ -- Lower Octave, Voice A"); v_gtext( handle,16,86, "} -- Higher Octave, Voice A"); v_gtext( handle,16,94, "SPACE -- Toggle Sustain Mode"); empt_box( 8,182,324,194,3 ); vst_color( handle,2 ); vst_effects( handle, T_THICK ); } dsp_prms() { empt_box( 320,18,632,102,3 ); vst_effects( handle, T_OUTLINE ); vst_color( handle,3 ); v_gtext( handle,400,16,"PARAMETER VALUES" ); vst_effects( handle, T_NORMAL ); vst_color( handle,1 ); v_gtext( handle,328,30, "Tuning : "); v_gtext( handle,328,38, "Dissonance : "); v_gtext( handle,328,46, "Waveform : "); v_gtext( handle,328,54, "Key Speed : "); v_gtext( handle,328,62, "Octave A : "); v_gtext( handle,328,70, "Octave B : "); v_gtext( handle,328,78, "Octave C : "); v_gtext( handle,328,86, "Octave Mix : "); v_gtext( handle,328,94, "Sustain : "); } dsp_vals() { char buffer[ 36 ]; vst_color( handle,1 ); vst_effects( handle,T_NORMAL ); sprintf(buffer,"%d%s",tune," "); v_gtext( handle,448,30,buffer ); sprintf(buffer,"%d%s",diss," "); v_gtext( handle,448,38,buffer ); sprintf(buffer,"%d%s",wave," "); v_gtext( handle,448,46,buffer ); if (fast_key) sprintf(buffer,"%s","Fast "); else sprintf(buffer,"%s","Normal "); v_gtext( handle,448,54,buffer ); sprintf(buffer,"%d%s",oct_a," "); v_gtext( handle,448,62,buffer ); sprintf(buffer,"%d%s",oct_b," "); v_gtext( handle,448,70,buffer ); sprintf(buffer,"%d%s",oct_c," "); v_gtext( handle,448,78,buffer ); if (oct_a == oct_b) sprintf(buffer,"%s","Same "); else sprintf(buffer,"%s","Split "); v_gtext( handle,448,86,buffer ); if (hold_n) sprintf(buffer,"%s","On "); else sprintf(buffer,"%s","Off "); v_gtext( handle,448,94,buffer ); } draw_kbd() { int row, key, kl, kt, kr, kb, offset=0, rowsize = 15; int ledge = 120; int tedge = 114; int keynum = 0; short int ret_key[ 14 ]; empt_box( ledge-8,tedge-4,ledge+4+306,tedge+8+45,2 ); vst_color( handle,1 ); vst_effects( handle,T_SKEWED ); v_gtext( handle,500,tedge+6,"Control"); vst_color( handle,2 ); v_gtext( handle,500,tedge+18,"Notes"); vst_color( handle,3 ); v_gtext( handle,500,tedge+30,"Chords"); v_gtext( handle,500,tedge+42,"Not Used"); empt_box( 460,tedge,475,tedge+7,1 ); empt_box( 460,tedge+12,475,tedge+19,2 ); full_box( 460,tedge+24,475,tedge+31,3,6 ); empt_box( 460,tedge+36,475,tedge+43,3 ); for (row = 0, kl = 10; row < 4; row++) { kl = ledge; kt = tedge + (row*10); kr = kl + 15 + offset; kb = kt + 7; empt_box( kl,kt,kr,kb,3 ); kl += offset; keynum++; for (key = 1; key < rowsize; key++) { kl += 20; kr += 20; if ((row == 0)&&(key == 14)) kr += 7; switch(keynum) { case 1: case 2: case 3: case 4: case 5: case 26: case 27: empt_box( kl,kt,kr,kb,1 ); break; case 17: case 18: case 20: case 22: case 23: case 24: case 25: case 30: case 31: case 32: case 33: case 34: case 36: case 37: case 38: empt_box( kl,kt,kr,kb,2 ); break; case 28: ret_key[ 0 ] = ret_key[ 10 ] = ret_key[ 12 ] = kl; ret_key[ 1 ] = ret_key[ 3 ] = ret_key[ 13 ] = kt; ret_key[ 2 ] = ret_key[ 4 ] = kr; ret_key[ 5 ] = ret_key[ 7 ] = kt + 17; ret_key[ 6 ] = ret_key[ 8 ] = kl - 11; ret_key[ 9 ] = ret_key[ 11 ] = kt + 10; vsl_color( handle,3 ); v_pline( handle,7,ret_key ); empt_box( kl+20,kt,kr+17,kb,3 ); empt_box( kl+20,kt+10,kr+17,kb+10,3 ); break; case 41: break; case 43: case 44: case 45: case 46: case 47: case 48: case 49: case 50: full_box( kl,kt,kr,kb,3,6 ); break; case 53: empt_box( kl,kt,kr + 5,kb,3 ); break; default: empt_box( kl,kt,kr,kb,3 ); break; } keynum++; } rowsize--; offset += 10; } tedge += (row*10); empt_box( ledge+20,tedge,ledge+40,tedge+7,3 ); vsl_color( handle,1 ); empt_box( ledge+45,tedge,ledge+240,tedge+7,1 ); vsl_color( handle,3 ); empt_box( ledge+245,tedge,ledge+265,tedge+7,3 ); } author() { long time = 150000L; vst_color( handle,2 ); vst_effects( handle,T_SKEWED ); v_gtext( handle,14,192," by David T. Jarvis "); while (time--) ; put_msg( std_msg ); } put_msg( s ) char *s; { vst_color( handle,2 ); vst_effects( handle,T_THICK ); v_gtext( handle,14,192,s ); } locate( row, col ) short int row, col; { Cconout( ESC_K ); Cconout('Y'); Cconout( row + 32 ); Cconout( col + 32 ); } sound_off() { Giaccess( 0, CH_AVL_W ); Giaccess( 0, CH_BVL_W ); Giaccess( 0, CH_CVL_W ); } sound_on() { x_low = (char)(x_note); y_low = (char)(y_note); z_low = (char)(z_note); x_high = (char)(x_note >> 8); y_high = (char)(y_note >> 8); z_high = (char)(z_note >> 8); Giaccess( period, RG_ENV_W ); Giaccess( wave, RG_WAV_W ); Giaccess( x_low, CH_ALO_W ); Giaccess( x_high, CH_AHI_W ); Giaccess( y_low, CH_BLO_W ); Giaccess( y_high, CH_BHI_W ); Giaccess( z_low, CH_CLO_W ); Giaccess( z_high, CH_CHI_W ); Giaccess( vol_a, CH_AVL_W ); Giaccess( vol_b, CH_BVL_W ); Giaccess( vol_c, CH_CVL_W ); } empt_box( left, top, right, bottom, color ) short int left, top, right, bottom, color; { short int pxy[ 10 ]; pxy[ 0 ] = left; pxy[ 1 ] = top; pxy[ 2 ] = right; pxy[ 3 ] = top; pxy[ 4 ] = right; pxy[ 5 ] = bottom; pxy[ 6 ] = left; pxy[ 7 ] = bottom; pxy[ 8 ] = left; pxy[ 9 ] = top; vsl_color( handle,color ); v_pline( handle, 5, pxy ); } full_box( left,top,right,bottom,color,style ) short int left,top,right,bottom,color,style; { short int pxy[ 4 ]; vsl_color( handle,color ); vsf_interior( handle,2 ); vsf_color( handle,color ); vswr_mode( handle,1 ); vsf_style( handle,style ); vsf_perimeter( handle,1 ); empt_box( left,top,right,bottom,color ); pxy[ 0 ] = left; pxy[ 1 ] = top; pxy[ 2 ] = right; pxy[ 3 ] = bottom; vr_recfl( handle,pxy ); } nonoise() { char *con_ptr; con_ptr = CONTERM; *con_ptr = *con_ptr & (char)0xfa; }