Jump to content
IGNORED

simple beeps with libti99?


tschak909

Recommended Posts

I had to deal with this with my bare bones Forth kernel too.

Not sure this code will help but it shows how simple it is to get some sounds.

HEX 
: SND! ( c -- ) 8400 C! ;   \ write c to address >8400 as a byte

: BEEP       ( -- )
            80 SND! 5 SND!                 \ pre-calculated values for OSC1 1328Hz
            91 SND!                        \ turn on OSC1 at -2 dB level
            AA MS                          \ Delay ~ 170 mS
            9F SND! ;                      \ turn off OSC1 (-30dB)

\ We use the HONK sound for ABORT like TI-BASIC does on errors
: HONK       ( -- )
            81 SND! 20 SND!                \ precalculated values for OSC1 218Hz
            90 SND!                        \ turn on OSC1 at 0 dB level
            AA MS                          \ Delay ~ 170 mS
            9F SND! ;                      \ turn off OSC1 (-30dB)
 

All you need is a function snd() that writes a byte to address >8400, and a simple delay.

If you use the values in the above code you will get the TI-99 beep and honk sounds.

 

This should be pretty simple to replicate in C . (I think)

  • Like 1
Link to comment
Share on other sites

how am I supposed to use the sound functions in libti99? I just need to do a simple beep in response to receiving a bell command.

 

-Thom

 

I haven't tested this, except to check compile syntax. Disclaimer: I have never used libti99, I'm translating up to C from an assembly language sound player.

 

Here is a program to load an interrupt sound list.

I give you Munchman "gulp" sound, which is much more friendly than the BEEP (I didn't grab the actual console beep, just copied BF's)

 

Set vaddr to an address in VDP - the ISR needs to have the sound list in VDP (or GROM .. but)

#include "vdp.h"
#include "sound.h"

void sndplay(unsigned char* sndlst, int len)
{        
    int vaddr = 0x300; // address of a vdp buffer you know of, to put the sound list into

    vdpmemcpy(vaddr, sndlst, len);
    SET_SOUND_PTR(vaddr);
    SET_SOUND_VDP();
    START_SOUND();
}



int main()
{
    // 166 ms beep
    char beep[] = { 3, 0x80, 0x05, 0x91, 10, 
    	1, 0x9f, 0 
    };
    char honk[] = { 3, 0x81, 0x20, 0x90, 10, 
    	1, 0x9f, 0 
    };
    
    // Munchman eat energizer sound
    char energz[] = { 6,0x9F,0xDF,0xFF,0xA0,0x08,0xB2,1,
            1,0xB4,1,
            1,0xB6,1,
            1,0xBF,0
    };
    
    sndplay(&beep[0], sizeof(beep));
    sndplay(&honk[0], sizeof(honk));
    sndplay(&energz[0], sizeof(energz));
}


Edited by FarmerPotato
  • Like 1
Link to comment
Share on other sites

What's the format of that "sound list" ? Is this functionality something that is shoved into the GPL interpeter?

 

-Thom

it's the format used by the console rom interrupt routine.

Length N, sound bytes[N], duration (in 1/60s)

repeat until duration = 0

 

the sound bytes are 76489 command bytes.

You can get code that takes the sound list from cpu ram, and set a pointer to that in >83C4, the user interrupt hook.

Link to comment
Share on other sites

You'll need a little more in there - sndplay() will only set up the values for the interrupt routine, you still need to enable interrupts, and wait for the sound to finish.

 

Not tested either, but if you extend sndplay() like this, it should work:

 

void sndplay(unsigned char* sndlst, int len)
{        
    int vaddr = 0x1000; // address of a vdp buffer you know of, to put the sound list into

    vdpmemcpy(vaddr, sndlst, len);
    SET_SOUND_PTR(vaddr);
    SET_SOUND_VDP();
    START_SOUND();

    // run the interrupt and wait for the sound to stop
    while (SOUND_CNT) {
        VDP_INT_POLL;
    }
}

Also be aware of that 0x300 for storing the sound list in VDP RAM... make sure you aren't using it for anything else. I usually use higher addresses myself. ;)

 

If you're using my "set_graphics" function, then VDP looks like this:

 

0x0000 - 0x02ff - Screen Image Table

0x0300 - 0x037F - Sprite Attribute List

0x0380 - 0x039f - Color table

...

0x0800 - 0x0fff - Pattern descriptor table and Sprite descriptor table (overlapped)

...

 

So, in my version I've changed the address to 0x1000.

Edited by Tursi
Link to comment
Share on other sites

sounds good, but it looks like with 0x1000, there is some display corruption caused by the loading of the sound list, how high can I go? (i am using libti99's graphics ii (aka bitmap) mode)

Bitmap uses most of video RAM. If you set it up with my library, then your VDP map looks like this:

 

0x0000-0x17FF - Pattern table

0x1800-0x1FFF - Sprite descriptor table (sprite patterns, you can use this space if you aren't using all patterns)

0x2000-0x37FF - Color table

0x3800-0x3AFF - Screen image table

0x3B00-0x3B7F - Sprite attribute list

0x3B80-0x3FFF - free... ish, unless you want disk.

 

Normally the video memory from 0x37D8 to 0x3FFF is used for disk buffers. If you are using bitmap and you ever want to use disk, you need to use the files(1) call to reduce the number of buffers so that bitmap doesn't sit on top of it, then the disk data starts at 0x3BE4, giving you what, 100 bytes?

 

Fortunately, the sprite descriptor table is usually not full, even when you are using sprites, so you can use the memory at 0x1800 for other things.

 

For a simple beep would it be possible to cast a volatile byte pointer at >8400 and write directly to it?

Absolutely, sound.h declares it as 'SOUND', so you can write bytes as "SOUND=0x9f" (for instance). To play a tone, you would need to load the sound chip with the bytes needed to start the tone, delay so it's actually heard, and then send the bytes to turn the sound off again. For instance, this would resemble CALL SOUND in BASIC with a delay:

 

// plays a sound
// len - length in milliseconds
// freq - frequency in hz (110 or greater)
// vol - volume where 0=loudest, 30=silent, only even values are used
void callsound(int len, int freq, int vol) {
  // convert length from milliseconds to 60hz frames
  len/=16;
  // convert frequency from hertz to 9919 counts
  // this is normally 111861/hz, but 111861 won't fit in
  // 16 bits, so we'll just fudge it here...
  freq=(111861/16)/(freq>>4);
  // send the frequency into the sound chip
  // least significant nibble and command nibble first
  SOUND=(freq&0x0f) | 0x80;
  // send the two most significant nibbles
  SOUND=(freq>>4);
  // send the volume and the command nibble
  // sound is actually only 0-15, BASIC fudges it for some reason
  SOUND=(vol>>1) | 0x90;
  // now sleep for the required number of frames
  // using the CRU version, we don't need interrupts to be enabled
  while (len--) {
    VDP_WAIT_VBLANK_CRU;
  }
  // Finally, mute the audio
  SOUND = 0x0f | 0x90;
}
  • Like 5
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...