/*
Name:
DRV_VOX.C
Description:
Mikmod driver for output on linux and FreeBSD Open Sound System (OSS)
(/dev/dsp)
Portability: VoxWare/SS/OSS land. Linux, FreeBSD (NetBSD & SCO?)
New fragment configuration code done by Rao:
============================================
You can use the environment variables 'MM_FRAGSIZE' and 'MM_NUMFRAGS' to
override the default size & number of audio buffer fragments. If you
experience crackles & pops, try experimenting with these values.
Read experimental.txt within the VoxWare package for information on these
options. They are _VERY_ important with relation to sound popping and smooth
playback.
In general, the slower your system, the higher these values need to be.
MM_NUMFRAGS is within the range 2 to 255 (decimal)
MM_FRAGSIZE is is within the range 7 to 17 (dec). The requested fragment size
will be 2^MM_FRAGSIZE
*/
package audio.jmikmod.MikMod.Drivers;
import persist.SimulatedRandomAccessFile;
import audio.jmikmod.MikMod.clDRIVER;
import audio.jmikmod.MikMod.clMain;
public class Native_Driver extends clDRIVER
{
static {
System.loadLibrary("jmikmod_drv");
}
protected int sndfd;
protected int fragmentsize;
protected byte audiobuffer[];
protected final int DEFAULT_FRAGSIZE = 17;
protected final int DEFAULT_NUMFRAGS = 2;
native int sysCheckAccess();
native int sysOpenSound(int iFreq, int iBitsNum, int iStereo, int iBlockSize, String szError);
native int sysCloseSound(int lHandle);
native int sysWriteBuffer(int lHandle, byte bBuffer[], int iLen);
public Native_Driver(clMain theMain)
{
super(theMain);
sndfd = 0;
fragmentsize = 0;
audiobuffer = null;
Name = new String("Native-API Sound Driver");
Version = new String("Native-API Sound Driver v1.0 - by Shlomi Fish");
}
public short SampleLoad(SimulatedRandomAccessFile fp,int size,int reppos,int repend,int flags)
{
return m_.Virtch.VC_SampleLoad(fp,size,reppos,repend,flags);
}
public void SampleUnLoad(short handle)
{
m_.Virtch.VC_SampleUnload(handle);
}
public boolean IsPresent()
{
//return (access("/dev/dsp",W_OK)==0);
return (sysCheckAccess() != 0);
}
public int Init()
{
//char *env;
int play_precision,play_stereo,play_rate;
int fragsize,numfrags;
//fragsize=(env=getenv("MM_FRAGSIZE")) ? atoi(env) : DEFAULT_FRAGSIZE;
fragsize = DEFAULT_FRAGSIZE;
//numfrags=(env=getenv("MM_NUMFRAGS")) ? atoi(env) : DEFAULT_NUMFRAGS;
numfrags = DEFAULT_NUMFRAGS;
if(fragsize<7 || fragsize>17) fragsize=DEFAULT_FRAGSIZE;
if(numfrags<2 || numfrags>255) numfrags=DEFAULT_NUMFRAGS;
fragmentsize=(numfrags<<16) | fragsize;
/*#ifndef __FreeBSD__
if(ioctl(sndfd, SNDCTL_DSP_SETFRAGMENT, &fragmentsize)<0){
*m_.mmIO.myerr = "Buffer fragment failed";
close(sndfd);
return 0;
}
#endif /* __FreeBSD__ */
play_precision = ((m_.MDriver.md_mode & m_.DMODE_16BITS) != 0) ? 16 : 8;
play_stereo= ((m_.MDriver.md_mode & m_.DMODE_STEREO) != 0) ? 1 : 0;
play_rate=m_.MDriver.md_mixfreq;
sndfd = sysOpenSound(play_rate, play_precision, play_stereo, fragmentsize, m_.mmIO.myerr);
if (sndfd == -1)
{
return 0;
}
/* Lose this for now - it will confuse ncurses etc...
printf("Fragment size is %ld\n",fragmentsize); */
if(!m_.Virtch.VC_Init()){
sysCloseSound(sndfd);
return 0;
}
audiobuffer = new byte[fragmentsize];
if(audiobuffer==null){
m_.Virtch.VC_Exit();
sysCloseSound(sndfd);
return 0;
}
return 1;
}
public void Exit()
{
//free(audiobuffer);
audiobuffer = null;
m_.Virtch.VC_Exit();
sysCloseSound(sndfd);
}
public void PlayStart()
{
m_.Virtch.VC_PlayStart();
}
public void PlayStop()
{
m_.Virtch.VC_PlayStop();
}
public void Update()
{
m_.Virtch.VC_WriteBytes(audiobuffer,fragmentsize);
sysWriteBuffer(sndfd, audiobuffer, fragmentsize);
}
public void VoiceSetVolume(short voice,short vol)
{
m_.Virtch.VC_VoiceSetVolume(voice, vol);
}
public void VoiceSetFrequency(short voice,int frq)
{
m_.Virtch.VC_VoiceSetFrequency(voice,frq);
}
public void VoiceSetPanning(short voice,short pan)
{
m_.Virtch.VC_VoiceSetPanning(voice,pan);
}
public void VoicePlay(short voice,short handle,int start,int size,int reppos,int repend,int flags)
{
m_.Virtch.VC_VoicePlay(voice,handle,start,size,reppos,repend,flags);
}
}