Programming - digital audio output to AY.

MSD #12
                              
                    LET'S LISTEN 
                              


Vishev Alex/MSD/20.12.99(c)


   The noble purpose of this message is to enlighten the people
about the technology of working with digital sound. Let's get started.



             A little science.


  If you are at odds with physics, then it is your sacred duty to
first servant to remind you of what it is
sound. So, sound is a mechanical vibration propagating
mine in an elastic medium and perceived by the organs of hearing. Music-
vocal sounds are characterized by pitch, volume and
timbre. The pitch of a tone corresponds to its frequency: the higher
frequency, the higher the pitch of the sound. The volume of sound is determined
sound strength, which in turn is determined by the amplitude
sound wave vibrations. The sound will be louder the more
amplitude of oscillation. Sounds coming from various sources
unequal in timbre, i.e. by color.
  For us, frequency is the frequency of throwing out a queue -
nobyte in AY. With all this, the frequency is already formed
during the sound of the sample (thus it is possible
playing a once digitized sample on different notes and
octaves).


                The beginning.


  Let's talk about working with AY(covoks are still so rare...). The most
the simplest thing you can think of is to output the sample into one
channel AY.
  By the way, the sample is a certain set of buy-
coms carrying information about the amplitude of sound.
  Let's continue. AY has only sixteen volume levels
ti (4 bits, 16 levels), and samples, as a rule, are
eight-bit (256 levels). It follows from this that they need
convert to four-bit format. But it's not that simple
since for AY, with an increase in volume by one, such
does not increase by 1/16. This sad fact brings us to
that for conversion you will have to create a special
table. It is not presented here, but I refer those interested
in ZX FORMAT 8.
  Here is the simplest procedure for playing one sample.
This assumes the sample is converted. If not, then
the sound will be of poor quality.


        DI ;disable interrupts
        LD HL,sample ;beginning of sound in memory
        LD DE,lenght ;its length
        LD BC,#FFFD ;port for writing register number AY
        LD A,8 ;volume register AU channel A
        OUT (C),A ;set
        LD B,#BF ;BC=#BFFD - port for writing to AY registers
   LOOP LD A,(HL) ;take a byte
        OUT (C),A ;throw it into the port
        INC HL;
        DEFS 20 ;delay for setting the frequency than
                     ;more - the lower the tone
        DEC DELD A,D
        OR E ;DE=0 ?
        JR NZ,LOOP ;continue the cycle
        EI ;enable interrupts
        RET


            Multichannel sound.


  Now let's get to the fun part. How could you observe
give, the sound frequency can be set using this method
only for one audio channel. How can we be, because in
AU there are three of them? And it’s very easy for us to be. True, for this it is necessary
will achieve one more register. For example like this:


        LD A,D ;register D is used as a transfer counter
LOW ADD A,0 ;fills. In HL the address of the tool.
        LD D,A ;As soon as register D overflows
        LD A,L ;HL will increase by one
HIGH ADC A,1 ;in addition to this,
        LD L,A ;increase HL by the amount of HIGH per
        ADC A,H ;each player pass
        SUB L
        LD H,A


  So we need a special table in which
will contain LOW and HIGH bytes for each note of each
octaves.


                Player.


  Now, in my opinion, everything is quite simple. So we have
somewhere in memory a table of notes, a table of sample addresses and,
in fact, a list of notes to play
melody. We also have the player itself as the mainmodule
program, and the interrupt procedure, which will be
swear by replacing the LOW and HIGH parameters, as well as
sample addresses for each audio channel.

  We set interrupts to the address of your procedure, which
paradise changes the LOW and HIGH parameters. In HL - the address of the tool.
How the intermediate counter is used D. Samples must be
converted. To each byte of the sample it is necessary to add
turn #A0, which is due to the decryption features, since
We will output the sound through the younger half of the AY port. In con-
The sample must contain a certain number of zeros, so
which determines the end of the sample. This amount is equal to
the highest HIGH value used in your player
+1. Here's roughly what it will look like:


BEGIN
        LD BC,#FFFD
A_CHAN LD A,8
        OUT (C),A ;channel A

     LD A,80 ;if 128th memory is used for samples
     OUT (#FD),A ;switch the memory page. Where 80 is zero
                 ;first page, 81 - first, etc.

     LD A,(HL) ;take sample byte
VOL SUB 1 ;with this command we catch two birds with one stone.
                 ;Firstly,
                 ;we define the end of the sample, and secondly,
                 ;here you can set the sound volume.
                 ;The higher the VOL, the quieter the sound, but not > 15

        JR C,NOT_SMP;bypass if sample runs out
        OUT(#FD),A};output sound
        LD A,D };frequency
LOW ADD A,0 }
        LD D,A }
        LD A,L }
HIGH ADC A,1 }
        LD L,A }
        ADC A,H }
        SUB L}
        LD H,A }
B_CHAN LD A,9 ;channel B
        OUT (C),A ;
        ............;etc. for all audio channels.
        ............;
        ............;
        JP BEGIN
NOT_SMP ;set the delay equal to execution }
                    ;what is necessary in order not to knock-
                    ;change the sound frequency in other channels,
                    ;if the tool runs out.
                    ;Similar for all channels
        JP B_CHAN


  The following is a procedure that works on interrupts and how I
I already said changing the parameters in the player. The pace at which
a melody will play, it is also very simple to set,
for example like this:



INT PUSH AF ;remember AF
TEMP LD A,10 ;tempo counter. 50 interrupts per second/10
        DEC A ;decrease
        JR Z,OK ;if zero, then run the procedure
        LD (TEMP+1),A;otherwise remember the counter
        POP AF
        RETI ;exit interrupt to player
OK LD A,10
        LD(TEMP+1),A
        ............;the procedure has begun


  It seems like I covered all the subtleties. Next is a matter of technology. A
write after thisyour digital radiator in my opinion - once
spit. The only thing I still have to tell you is that it is necessary
It is possible that the player and the program on interruptions work at maximum
very quickly. Experiment more and maybe
someday you will write the coolest digital editor on
Spectrum. Arivederchi.


                               Vishev Alex/MSD/20.12.99 18:4

Share your thoughts about the article