I said my next “immediate” todos were to add sound stuff in BASIC.
Half done – this took surprisingly much longer than anticipated. I am not going to write too much about it. But if interested, this is a working implementation in “C” – to get rid of the last “goto” would have ment major changes… which I didn’t want to do (or double the last two loops)…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 | const static unsigned char Music_Table_1[] = { 0xF7, 0xEF, 0xDF, 0x01, 0x02, 0x04 //;For noise }; const static unsigned char Music_Table_2[] = { 0xFE, 0xFD, 0xFB, 0x08, 0x10, 0x20 // ;For music }; const static unsigned int Freq_Table[]= { 0x03BD,0x0387,0x0354,0x0324,0x02F7,0x02CD,0x02A4,0x027E, 0x025B,0x0239,0x0219,0x01FB,0x01DE,0x01C3,0x01AA,0x0192, 0x017C,0x0166,0x0152,0x013F,0x012D,0x011C,0x010C,0x00FD, 0x00EF,0x00E2,0x00D5,0x00C9,0x00BE,0x00B3,0x00A9,0x00A0, 0x0097,0x008E,0x0086,0x007F,0x0078,0x0071,0x006B,0x0065, 0x005F,0x005A,0x0055,0x0050,0x004B,0x0047,0x0043,0x003F, 0x003C,0x0038,0x0035,0x0032,0x002F,0x002D,0x002A,0x0028, 0x0026,0x0024,0x0022,0x0020,0x001E,0x001C,0x001B,0x0000 }; bool is_Playing = false; int Vec_Music_Flag; // no sound // 1 new sound // -1 sound in progress int Vec_Music_Chan=0; unsigned char *Vec_Music_Ptr = 0; unsigned char Vec_ADSR_Timers[3]; unsigned char Vec_Music_Twang_Count[3]; signed char Vec_Music_Twang_Value[3]; signed char Vec_Duration; int Vec_Music_Freq[3]; unsigned char Vec_ADSR_Table[16]; signed char Vec_Twang_Table[16]; void VectrexMusicPlayer::Init_Music() { int ch; if (!Vec_Music_Flag) return; // no music if (Vec_Music_Flag==1) // new Music { Vec_Music_Flag = -1; Vec_Music_Ptr = music->music; v_noSound(); Vec_ADSR_Timers[0] =0x1f; Vec_ADSR_Timers[1] =0x1f; Vec_ADSR_Timers[2] =0x1f; Vec_Music_Freq[0] = 0; Vec_Music_Freq[1] = 0; Vec_Music_Freq[2] = 0; Vec_Music_Chan=0; Vec_Duration = 0; } else // continue music { for (ch=2; ch>=0;ch--) { if (Vec_ADSR_Timers[ch] != 0x1f) // not maximum { Vec_ADSR_Timers[ch]++; } } for (ch=0; ch<3;ch++) { if (++Vec_Music_Twang_Count[ch] > ch+7) Vec_Music_Twang_Count[ch] = 0; Vec_Music_Twang_Value[ch] = Vec_Twang_Table[(Vec_Music_Twang_Count[ch])&7]; } Vec_Duration--; if (Vec_Duration>=0) goto LF74E; Vec_Music_Chan--; if (Vec_Music_Chan<0) Vec_Music_Chan=2; } while (1) { unsigned char b = *Vec_Music_Ptr; Vec_ADSR_Timers[Vec_Music_Chan] = 0; if (b&0x40) { // noise v_writePSG_double_buffered(7, Music_Table_1[Vec_Music_Chan] & v_readPSG_double_buffered(7)); v_writePSG_double_buffered(7, Music_Table_1[Vec_Music_Chan+3] | v_readPSG_double_buffered(7)); v_writePSG_double_buffered(6, b&0x1f); } else { // sound v_writePSG_double_buffered(7, Music_Table_2[Vec_Music_Chan] & v_readPSG_double_buffered(7)); v_writePSG_double_buffered(7, Music_Table_2[Vec_Music_Chan+3] | v_readPSG_double_buffered(7)); Vec_Music_Freq[Vec_Music_Chan] = Freq_Table[b & 0x3f]; } b = *Vec_Music_Ptr++; if (b&0x80) { Vec_Music_Chan--; if (Vec_Music_Chan<0) Vec_Music_Chan=2; continue; } b = *Vec_Music_Ptr++; if (b&0x80) { // music finished completely! Vec_Music_Flag =0; is_Playing = 0; v_noSound(); return; } Vec_Duration = b&0x3f; break; } LF74E: for (ch = 2;ch>=0;ch--) { unsigned char nibble = Vec_ADSR_Table[Vec_ADSR_Timers[ch]>>1]; if ((Vec_ADSR_Timers[ch] & 1) == 1) nibble = nibble>>4; nibble = nibble &0x0f; v_writePSG_double_buffered(8+ch, nibble); // volume is decoded in ADSR nibbles } for (ch = 0;ch <3; ch++) { unsigned int baseFreq = Vec_Music_Freq[ch]; baseFreq += Vec_Music_Twang_Value[ch]; v_writePSG_double_buffered(ch*2+0, baseFreq&0xff ); v_writePSG_double_buffered(ch*2+1, (baseFreq>>8)&0x0f ); } } |