Jump to content

Photo

simple beeps with libti99?


8 replies to this topic

#1 tschak909 ONLINE  

tschak909

    River Patroller

  • 3,108 posts
  • Location:USA

Posted Tue Feb 5, 2019 4:07 PM

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



#2 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 921 posts
  • Location:The Great White North

Posted Tue Feb 5, 2019 4:23 PM

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)  



#3 FarmerPotato OFFLINE  

FarmerPotato

    Moonsweeper

  • 272 posts
  • Location:Austin, TX

Posted Tue Feb 5, 2019 5:49 PM

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, Tue Feb 5, 2019 6:35 PM.


#4 tschak909 ONLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,108 posts
  • Location:USA

Posted Tue Feb 5, 2019 6:04 PM

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

 

-Thom


Edited by tschak909, Tue Feb 5, 2019 6:05 PM.


#5 FarmerPotato OFFLINE  

FarmerPotato

    Moonsweeper

  • 272 posts
  • Location:Austin, TX

Posted Tue Feb 5, 2019 6:35 PM

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.



#6 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,499 posts
  • HarmlessLion
  • Location:BUR

Posted Tue Feb 5, 2019 6:56 PM

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, Tue Feb 5, 2019 6:57 PM.


#7 TheBF OFFLINE  

TheBF

    Dragonstomper

  • 921 posts
  • Location:The Great White North

Posted Tue Feb 5, 2019 8:08 PM

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.



#8 tschak909 ONLINE  

tschak909

    River Patroller

  • Topic Starter
  • 3,108 posts
  • Location:USA

Posted Tue Feb 5, 2019 8:35 PM

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 by tschak909, Tue Feb 5, 2019 8:38 PM.


#9 Tursi OFFLINE  

Tursi

    Quadrunner

  • 5,499 posts
  • HarmlessLion
  • Location:BUR

Posted Wed Feb 6, 2019 2:21 AM

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;
}





0 user(s) are browsing this forum

0 members, 0 guests, 0 anonymous users