Sound

Sound require headphones to plug in. Since nearly no one has these, generally do not include sound into a game. ONLY use sound if that is the main purpose of the program.

This page needs more info. Members of this site can edit pages.

(Note to readers : the first real addition to this page is by Zeda, and I am not very familiar with the finer points of making sound. I only experimented, took pointers from others and eventually used a routine in Axe (after optimising it slightly). Anyways, there are others that are much more versed in this topic!)

1-Channel Sound

The idea behind making sound on the calculators is to toggle a line on the link port at a given frequency. The link port has two lines making 1 and 2 channel sound relatively okay, but there are some who have made 4-channel sound work using clever masking. Here is a very simple routine for 1-channel sound (optimised from Axe) :

p_FreqOut:
;Inputs:
;     HL is the duration of the note
;     BC is the frequency
    xor    a
__FreqOutLoop1:
    push    bc
    xor     %00000011    ;this will toggle the lower two bits (the data being sent to the link port)
    ld    e,a
__FreqOutLoop2:
    ld    a,h
    or    l
    jr    z,__FreqOutDone
    cpd
    jp    pe,__FreqOutLoop2
    ld    a,e
        scf
__FreqOutDone:
    pop    bc
    out    (0),a
    jr    c,__FreqOutLoop1
    xor b
    out (0),a       ;reset the port, else the user will be really annoyed.
    ret

An example duration would be 4096 and frequencies can be made to correspond to certain notes. If Duration is shorter than Frequency, nothing is done to the link port. Here is an LUT (Lookup Table) of frequencies that correspond to 96 notes (starting with the lowest, going to highest):
FrequencyLUT:
 .dw 2100,1990,1870,1770,1670,1580,1490,1400,1320,1250,1180,1110
 .dw 1050, 996, 940, 887, 837, 790, 746, 704, 665, 627, 592, 559
 .dw  527, 498, 470, 444, 419, 395, 373, 352, 332, 314, 296, 279
 .dw  264, 249, 235, 222, 209, 198, 186, 176, 166, 157, 148, 140
 .dw  132, 124, 117, 111, 105,  99,  93,  88,  83,  78,  74,  70
 .dw   66,  62,  59,  55,  52,  49,  47,  44,  42,  39,  37,  35
 .dw   33,  31,  29,  28,  26,  25,  23,  22,  21,  20,  19,  18
 .dw   17,  16,  15,  14,  13,  12,  11,  10,  10,   9,   9,   8
 .dw    8,   7,   7,   7,   7,   6,   6,   5,   5,   5,   5,   4

So to play a given note A for a duration of D, your routine might look like this:
     ld hl,FrequencyLUT
     add a,l
     ld l,a
     jr nc,$+3
     inc h
     ld c,(hl)
     inc hl
     ld b,(hl)
;now BC is the frequency for the note
SoundLoop:
     push bc
     ld hl,4096
     call p_FreqOut
     pop bc
     dec bc
     ld a,b
     or c
     jr nz,SoundLoop
     ret

In this case, if input D is 16, the note will last a noticeable amount of time. This method allows you to make the duration up to 4096*256 (and a multiple of 4096), but there is a downside. If we look at the first value of the LUT, 2100, using a duration of 4096 means that the port is toggled only once (we need 2100*2 for the duration in order to toggle twice). The toggling is what creates the sound. If we had used a duration of 16384, the port would be toggled 7 times, but with this method, 16384=4*4096, so we would get it toggled only 4 times. This makes for choppy sound.

That is not to say that the above routine is bad— it is a great option for playing sound in games where you cannot devote the full processor time to sound and it allows you to extend duration beyond 16 bits. However, if the latter is what is sought, we can use a modified routine to have 24-bit durations:

p_FreqOut:
;Inputs:
;     DHL is the duration of the note
;     BC is the frequency
    xor    a
__FreqOutLoop1:
    push    bc
    xor     %00000011
    ld    e,a
__FreqOutLoop2:
    ld    a,h
    or    l
    jr    nz,$+6
    dec d
    jp    m,__FreqOutDone

    cpd
    jp    pe,__FreqOutLoop2
    ld    a,e
        scf
__FreqOutDone:
    pop    bc
    out    (0),a
    jr    c,__FreqOutLoop1
    xor b
    out (0),a
    ret

Now that should remove some of the choppiness from the sound for lower notes with longer durations, though the change might not be noticeable.
Unless otherwise stated, the content of this page is licensed under GNU Free Documentation License.