2nd of May 2021 – Init_Sound

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  );
 }
}

Tagged on: ,

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.