tschak909 Posted February 5, 2019 Share Posted February 5, 2019 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 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 5, 2019 Share Posted February 5, 2019 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) 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted February 5, 2019 Share Posted February 5, 2019 (edited) 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 February 6, 2019 by FarmerPotato 1 Quote Link to comment Share on other sites More sharing options...
tschak909 Posted February 6, 2019 Author Share Posted February 6, 2019 (edited) What's the format of that "sound list" ? Is this functionality something that is shoved into the GPL interpeter? -Thom Edited February 6, 2019 by tschak909 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted February 6, 2019 Share Posted February 6, 2019 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. Quote Link to comment Share on other sites More sharing options...
Tursi Posted February 6, 2019 Share Posted February 6, 2019 (edited) 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 February 6, 2019 by Tursi Quote Link to comment Share on other sites More sharing options...
+TheBF Posted February 6, 2019 Share Posted February 6, 2019 For a simple beep would it be possible to cast a volatile byte pointer at >8400 and write directly to it? Maybe GCC would complain? Just curious. Quote Link to comment Share on other sites More sharing options...
tschak909 Posted February 6, 2019 Author Share Posted February 6, 2019 (edited) 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) -Thom Edited February 6, 2019 by tschak909 Quote Link to comment Share on other sites More sharing options...
Tursi Posted February 6, 2019 Share Posted February 6, 2019 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; } 5 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.