home *** CD-ROM | disk | FTP | other *** search
/ Sound Sensations! / sound_sensations.iso / voice / polymusi / polymusi.txt < prev    next >
Text File  |  1985-07-20  |  6KB  |  122 lines

  1. Polyphonic Music on the IBM PC 
  2. Steve Muenter
  3. Rocketdyne Microcomputer Users Group
  4.  
  5. Sitting at the keyboard of my IBM PC, I realized that other computers could
  6. produce music with three simultaneous tones for chords and harmony while my
  7. IBM was limited to only one tone at a time.  To rectify this, I wrote an
  8. assembly language program which produces three tones from the IBM
  9. PC's internal speaker without any hardware modification.
  10.  
  11. Normally, a single tone is generated through the speaker using the 8253
  12. Programmable Interval Timer.  The microprocessor loads a divisor into
  13. the 8253's register for counter 2. The 1.19 MHz system clock is divided
  14. by this number and the resulting square wave is sent to the speaker.
  15. Once the divisor is loaded, the microprocessor is free to do
  16. something else while the tone plays in the background.
  17.  
  18. Since the hardware is not set up to produce three tones simultaneously,
  19. it becomes necessary to get the microprocessor to do the dividing of
  20. the system clock.  The program loop which performs the divisions for the
  21. three tones must be very quick in order to produce tones with high
  22. audio frequencies.  I found when using memory to store intermediate
  23. division results, the relatively slow memory accesses took too many clock
  24. cycles giving three low growls at best.  Using the 8088 internal
  25. registers speeded up the loop considerably since the register
  26. accesses are about ten times faster than memory accesses.
  27.  
  28. The assembly language routine presented here was written to be
  29. called from BASIC.  The code is divided into three sections.  The
  30. first section (from "tri" to "sort") sets up the pointers to the data
  31. passed to the routine.  Also, the 8088 internal registers are zeroed.
  32.  
  33. The second section (from "sort" to "loop") sorts the 16-bit integer
  34. numbers passed to the routine.  The three most significant bits of the
  35. integer identify the remaining 13 bits as either voice 1, 2, or 3
  36. period data, note duration data, tempo data or end-of-song flag.  The
  37. bit pattern 000 identifies that the song has ended and causes the routine
  38. to return to BASIC.  The pattern 001 sets the duration of time that the
  39. current notes will play before the next notes start.  The pattern 010
  40. sets the tempo of the playback.  The pattern 100 identifies that the 13
  41. remaining bits represent period data for voice 1.  The pattern 101
  42. identifies voice 2 period data, and the pattern 110 identifies voice 3
  43. data.
  44.  
  45. The last section (from "loop" to "end") performs the division of the
  46. system clock and switching of the speaker for each of the three voices.
  47. This is the section of the program that actually makes the tones.  For
  48. speed, the routine for each voice is written entirely rather than written
  49. as a single subroutine called three times.  This was done because jumps
  50. and calls require at least fifteen clock cycles.
  51.  
  52. Although the assembly language routine parses the 16-bit binary data
  53. into three bits identifying data type and thirteen bits representing a
  54. numerical value, BASIC treats this data as an array of 2's complement
  55. 16-bit single precision integers. This means that the decimal
  56. equivalent of the number is given by the following equation.
  57.  
  58.  
  59. N = -2^15*a(15) + 2^14*a(14) +
  60.      2^13*a(13) + 2^12*a(12) +
  61.      2^11*a(11) + 2^10*a(10) +
  62.      2^9*a(9) + 2^8*a(8) + 2^7*a(7) +
  63.      2^6*a(6) + 2^5*a(5) + 2^4*a(4) +
  64.      2^3*a(3) + 2^2*a(2) + 2^1*a(1) +
  65.      2^0*a(0)
  66.  
  67.  
  68. where a(n) is a 1 or 0 in the nth bit of the 16 bit number.  Notice that
  69. the most significant bit (the 16th bit) represents a negative number
  70. (-32768) whereas all the other bits represent positive numbers.  The
  71. numerical range of the 2's complement integers is -32768 to 32767.
  72.  
  73. It can be seen that the pattern of the three most significant bits can
  74. be represented as a decimal number. The pattern for identifying duration
  75. data (001) corresponds to a decimal value of 8192.  Tempo data (010)
  76. equals 16384, voice 1 data (100) equals -32768, voice 2 data (101)
  77. equals -24576, and voice three data (110) equals -16384.  The 13
  78. remaining bits can represent decimal numbers ranging from 0 to 16383.
  79.  
  80. The accompanying BASIC program contains data statements which load
  81. an integer array with the data for playing the first part of the Rondo
  82. Alla Turca by Wolfgang A. Mozart. The first entry in the integer data
  83. array sets the tempo of the playback. A typical tempo value of 512 plus the
  84. tempo identifier 16384 gives the integer data value 16896.
  85.  
  86. A note's duration is specified by its length relative to a 32nd note.  For
  87. example, a quarter note equals eight 32nd notes, so a decimal value of 8
  88. is added to the duration identifier, 8192.  The resulting number is 8192 +
  89. 8 = 8200.  Likewise, a whole note is represented by the decimal integer
  90. 8192 + 32 = 8224.
  91.  
  92. The voice data is determined by adding the number representing the
  93. frequency of the desired note to the number identifying the desired voice
  94. of the three possible.  The following table gives the numbers representing
  95. the notes of the scale.  For example, middle C on voice 1 is represented by
  96. adding the voice 1 identifier with the value for middle C.  The
  97. resulting number is -32768 + 1024 = -31744.  To turn voice 1 off, the
  98. data would be -32768 + 0 = -32768.
  99.  
  100.  
  101.          NOTE DATA TABLE
  102.  
  103.   LOW       MIDDLE       HIGH
  104.   ---       ------       ----
  105. C  = 512   C  = 1024   C  = 2048
  106. C# = 542   C# = 1085   C# = 2170
  107. D  = 575   D  = 1149   D  = 2299
  108. D# = 609   D# = 1218   D# = 2435
  109. E  = 645   E  = 1290   E  = 2580
  110. F  = 683   F  = 1367   F  = 2734
  111. F# = 724   F# = 1448   F# = 2896
  112. G  = 767   G  = 1534   G  = 3069
  113. G# = 813   G# = 1625   G# = 3251
  114. A  = 861   A  = 1722   A  = 3444
  115. A# = 912   A# = 1825   A# = 3649
  116. B  = 967   B  = 1933   B  = 3866
  117. No tone = 0
  118.  
  119. [Editor's note : The programs discussed above can be found on this diskette 
  120. as separate files, TRI.BIN, TRI.ASM and TRTEST.BAS.  The programs do not 
  121. operate properly on the PCjr or the PC AT due to timing considerations.]
  122.