Code: Select all
Dim shared As Any Ptr alsa
dim shared as integer OSS
'ALSA declarations
Const EAGAIN = -11 ' Try again
Const EPIPE = -32 ' Broken pipe
Const ESTRPIPE = -86 ' Streams pipe error
Const BLOCK = 0
Const NONBLOCK = 1
Const ASYNC = 2
Const SND_PCM_STREAM_PLAYBACK = 0
Const SND_PCM_STREAM_CAPTURE = 1
Const SND_PCM_FORMAT_S16_LE = 2
Const SND_PCM_ACCESS_RW_INTERLEAVED= 3
#ifndef NULL
#define NULL 0
#endif
Type snd_pcm_t As Any Ptr
Type snd_pcm_hw_params_t As Any Ptr
Type snd_output_t As Any Ptr
' PCM
Dim Shared snd_strerror as Function ( _
Byval ecode As LONG) As Zstring Ptr
Dim Shared snd_pcm_open as Function ( _
Byval pcm As snd_pcm_t Ptr, _
Byval device As Zstring Ptr, _
Byval direction As LONG, _
Byval mode As LONG) As LONG
Dim Shared snd_pcm_close as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_start as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_drain as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_hw_free as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_nonblock as Function ( _
Byval pcm As snd_pcm_t, _
Byval nonblock As LONG) As LONG
Dim Shared snd_pcm_prepare as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_writei as Function ( _
Byval pcm As snd_pcm_t, _
Byval buffer As Any Ptr, _
Byval size As LONG) As LONG
Dim Shared snd_pcm_recover as Function ( _
Byval pcm As snd_pcm_t, _
Byval err As LONG, _
Byval silent As LONG) As LONG
Dim Shared snd_pcm_avail_update as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_avail as Function ( _
Byval pcm As snd_pcm_t) As LONG
Dim Shared snd_pcm_delay as Function ( _
Byval pcm As snd_pcm_t, _
Byval delayp As snd_pcm_t) As LONG
Dim Shared snd_pcm_wait as Function ( _
Byval pcm As snd_pcm_t, _
Byval msec As LONG) As LONG
Dim Shared snd_pcm_resume as Function ( _
Byval pcm As snd_pcm_t) As LONG
'hardware
Dim Shared snd_pcm_hw_params_malloc as Function ( _
Byval hw As snd_pcm_hw_params_t Ptr) As LONG
Dim Shared snd_pcm_hw_params_any as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t) As LONG
Dim Shared snd_pcm_hw_params_set_access as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t, _
Byval mode As LONG) As LONG
Dim Shared snd_pcm_hw_params_set_format as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t, _
Byval fmt As LONG) As LONG
Dim Shared snd_pcm_hw_params_set_channels as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t, _
Byval Channels As LONG) As LONG
Dim Shared snd_pcm_hw_params_get_channels as Function ( _
Byval hw As snd_pcm_hw_params_t, _
Byval lpChannels As ULONG Ptr) As LONG
Dim Shared snd_pcm_hw_params_set_rate_near as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t, _
Byval lpRate As ULONG Ptr, _
Byval lpDir As LONG Ptr) As LONG
Dim Shared snd_pcm_hw_params_get_periods as Function ( _
Byval hw As snd_pcm_hw_params_t, _
Byval lpValue As ULONG Ptr, _
Byval lpDir As LONG Ptr) As LONG
Dim Shared snd_pcm_hw_params_set_periods_near as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t, _
Byval lpValue As ULONG Ptr, _
Byval lpDir As LONG Ptr) As LONG
Dim Shared snd_pcm_hw_params_get_period_size as Function ( _
Byval params As snd_pcm_hw_params_t, _
Byval lpFrames As Any Ptr, _
Byval lpDir As LONG Ptr) As LONG
Dim Shared snd_pcm_hw_params_set_period_size_near as Function ( _
Byval pcm As snd_pcm_t Ptr, _
Byval hw As snd_pcm_hw_params_t, _
Byval lpValue As Any Ptr, _
Byval lpDir As LONG Ptr) As LONG
Dim Shared snd_pcm_hw_params_set_buffer_size_near as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t, _
Byval lpFrames As Any Ptr) As LONG
Dim Shared snd_pcm_hw_params_get_buffer_size as Function ( _
Byval hw As snd_pcm_hw_params_t, _
Byval lpFrames As Any Ptr) As LONG
Dim Shared snd_pcm_hw_params as Function ( _
Byval pcm As snd_pcm_t, _
Byval hw As snd_pcm_hw_params_t) As LONG
Dim Shared snd_pcm_hw_params_free as Sub ( _
Byval hw As snd_pcm_hw_params_t)
Dim Shared As snd_pcm_t Ptr hDevice
Dim Shared As snd_pcm_hw_params_t Ptr hw
Dim Shared As LONG ret,value,direction,buffer_size,SampleSize
Dim Shared As Integer nFrames
Dim Shared As Zstring Ptr strRet
'OSS declarations
#include "file.bi"
declare function fileno cdecl alias "fileno" (byval as any ptr) as integer
declare function ioctl cdecl alias "ioctl" (byval hDevice as unsigned long,byval io_cmd as unsigned long,byval lpArg as long ptr) as long
#define _IOC_NRBITS 8
#define _IOC_TYPEBITS 8
#define _IOC_SIZEBITS 14
#define _IOC_DIRBITS 2
#define _IOC_NRMASK ((1 shl _IOC_NRBITS )-1)
#define _IOC_TYPEMASK ((1 shl _IOC_TYPEBITS)-1)
#define _IOC_SIZEMASK ((1 shl _IOC_SIZEBITS)-1)
#define _IOC_DIRMASK ((1 shl _IOC_DIRBITS )-1)
#define _IOC_NRSHIFT 0
#define _IOC_TYPESHIFT (_IOC_NRSHIFT + _IOC_NRBITS)
#define _IOC_SIZESHIFT (_IOC_TYPESHIFT + _IOC_TYPEBITS)
#define _IOC_DIRSHIFT (_IOC_SIZESHIFT + _IOC_SIZEBITS)
' Direction bits.
#define _IOC_NONE 0U
#define _IOC_WRITE 1U
#define _IOC_READ 2U
#define _IOC(dir,t,nr,size) (((dir) shl _IOC_DIRSHIFT) or ((t) shl _IOC_TYPESHIFT) or ((nr) shl _IOC_NRSHIFT) or ((size) shl _IOC_SIZESHIFT))
' used to create numbers
#define _IO(t,nr) _IOC(_IOC_NONE,(t),(nr),0)
#define _IOR(t,nr,size) _IOC(_IOC_READ,(t),(nr),sizeof(size))
#define _IOW(t,nr,size) _IOC(_IOC_WRITE,(t),(nr),sizeof(size))
#define _IOWR(t,nr,size) _IOC(_IOC_READ or _IOC_WRITE,(t),(nr),sizeof(size))
' used to decode ioctl numbers..
#define _IOC_DIR(nr) (((nr) shr _IOC_DIRSHIFT) and _IOC_DIRMASK)
#define _IOC_TYPE(nr) (((nr) shr _IOC_TYPESHIFT) and _IOC_TYPEMASK)
#define _IOC_NR(nr) (((nr) shr _IOC_NRSHIFT) and _IOC_NRMASK)
#define _IOC_SIZE(nr) (((nr) shr _IOC_SIZESHIFT) and _IOC_SIZEMASK)
' ...and for the drivers/sound files...
#define IOC_IN ( _IOC_WRITE shl _IOC_DIRSHIFT)
#define IOC_OUT ( _IOC_READ shl _IOC_DIRSHIFT)
#define IOC_INOUT ((_IOC_WRITE or _IOC_READ) shl _IOC_DIRSHIFT)
#define IOCSIZE_MASK ( _IOC_SIZEMASK shl _IOC_SIZESHIFT)
#define IOCSIZE_SHIFT ( _IOC_SIZESHIFT)
' IOCTL commands for /dev/dsp and /dev/audio
#define SNDCTL_DSP_RESET _IO (asc("P"), 0)
#define SNDCTL_DSP_SYNC _IO (asc("P"), 1)
#define SNDCTL_DSP_SPEED _IOWR(asc("P"), 2, LONG)
#define SNDCTL_DSP_STEREO _IOWR(asc("P"), 3, LONG)
#define SNDCTL_DSP_GETBLKSIZE _IOWR(asc("P"), 4, LONG)
#define SNDCTL_DSP_SETFMT _IOWR(asc("P"), 5, LONG) ' Selects ONE fmt
#define SNDCTL_DSP_CHANNELS _IOWR(asc("P"), 6, LONG)
#define SOUND_PCM_WRITE_CHANNELS SNDCTL_DSP_CHANNELS
#define SOUND_PCM_WRITE_FILTER _IOWR(asc("P"), 7, LONG)
#define SNDCTL_DSP_POST _IO (asc("P"), 8)
#define SNDCTL_DSP_SUBDIVIDE _IOWR(asc("P"), 9, LONG)
#define SNDCTL_DSP_SETFRAGMENT _IOWR(asc("P"),10, LONG)
#define SNDCTL_DSP_GETFMTS _IOR (asc("P"),11, LONG) ' Returns a mask
#define SNDCTL_DSP_SAMPLESIZE SNDCTL_DSP_SETFMT
#define SNDCTL_DSP_GETODELAY _IOR (asc("P"), 23, LONG)
'arg for SNDCTL_DSP_SETFMT cmd
const AFMT_MU_LAW = &H00000001
const AFMT_A_LAW = &H00000002
const AFMT_IMA_ADPCM = &H00000004
const AFMT_U8 = &H00000008
const AFMT_S16_LE = &H00000010 ' Little endian signed
const AFMT_S16_BE = &H00000020 ' Big endian signed 16
const AFMT_S8 = &H00000040
const AFMT_U16_LE = &H00000080 ' Little endian U16
const AFMT_U16_BE = &H00000100 ' Big endian U16
const AFMT_MPEG = &H00000200 ' MPEG (2) audio
const AFMT_AC3 = &H00000400 ' Dolby Digital AC3
sub dsp_init()
alsa = DyLibLoad("asound")
if alsa=0 then alsa = DyLibLoad("libasound.so.2")
if alsa<>0 then
snd_strerror= DyLibSymbol(alsa, "snd_strerror")
snd_pcm_open= DyLibSymbol(alsa, "snd_pcm_open")
snd_pcm_close= DyLibSymbol(alsa, "snd_pcm_close")
snd_pcm_start= DyLibSymbol(alsa, "snd_pcm_start")
snd_pcm_drain= DyLibSymbol(alsa, "snd_pcm_drain")
snd_pcm_hw_free= DyLibSymbol(alsa, "snd_pcm_hw_free")
snd_pcm_nonblock= DyLibSymbol(alsa, "snd_pcm_nonblock")
snd_pcm_prepare= DyLibSymbol(alsa, "snd_pcm_prepare")
snd_pcm_writei= DyLibSymbol(alsa, "snd_pcm_writei")
snd_pcm_recover= DyLibSymbol(alsa, "snd_pcm_recover")
snd_pcm_avail_update= DyLibSymbol(alsa, "snd_pcm_avail_update")
snd_pcm_avail= DyLibSymbol(alsa, "snd_pcm_avail")
snd_pcm_delay= DyLibSymbol(alsa, "snd_pcm_delay")
snd_pcm_wait= DyLibSymbol(alsa, "snd_pcm_wait")
snd_pcm_resume= DyLibSymbol(alsa, "snd_pcm_resume")
snd_pcm_hw_params_malloc= DyLibSymbol(alsa, "snd_pcm_hw_params_malloc")
snd_pcm_hw_params_any= DyLibSymbol(alsa, "snd_pcm_hw_params_any")
snd_pcm_hw_params_set_access= DyLibSymbol(alsa, "snd_pcm_hw_params_set_access")
snd_pcm_hw_params_set_format= DyLibSymbol(alsa, "snd_pcm_hw_params_set_format")
snd_pcm_hw_params_set_channels= DyLibSymbol(alsa, "snd_pcm_hw_params_set_channels")
snd_pcm_hw_params_get_channels= DyLibSymbol(alsa, "snd_pcm_hw_params_get_channels")
snd_pcm_hw_params_set_rate_near= DyLibSymbol(alsa, "snd_pcm_hw_params_set_rate_near")
snd_pcm_hw_params_get_periods= DyLibSymbol(alsa, "snd_pcm_hw_params_get_periods")
snd_pcm_hw_params_set_periods_near= DyLibSymbol(alsa, "snd_pcm_hw_params_set_periods_near")
snd_pcm_hw_params_get_period_size= DyLibSymbol(alsa, "snd_pcm_hw_params_get_period_size")
snd_pcm_hw_params_set_period_size_near= DyLibSymbol(alsa, "snd_pcm_hw_params_set_period_size_near")
snd_pcm_hw_params_set_buffer_size_near= DyLibSymbol(alsa, "snd_pcm_hw_params_set_buffer_size_near")
snd_pcm_hw_params_get_buffer_size= DyLibSymbol(alsa, "snd_pcm_hw_params_get_buffer_size")
snd_pcm_hw_params= DyLibSymbol(alsa, "snd_pcm_hw_params")
snd_pcm_hw_params_free= DyLibSymbol(alsa, "snd_pcm_hw_params_free")
end if
OSS=FileExists("/dev/dsp")
end sub
sub SoundSet(frequency as long, channels as long, bits as long)
if alsa=0 andalso OSS=0 then dsp_init
if alsa then
if bits=16 then SampleSize=2 else SampleSize=1
SampleSize*=channels
ret = snd_pcm_open(@hDevice,"default", SND_PCM_STREAM_PLAYBACK, BLOCK)
snd_pcm_hw_params_malloc(@hw)
ret = snd_pcm_hw_params_any(hDevice,hw)
ret = snd_pcm_hw_params_set_access(hDevice, hw, SND_PCM_ACCESS_RW_INTERLEAVED)
ret = snd_pcm_hw_params_set_format(hDevice,hw,IIF(bits=16,2,1))
ret = snd_pcm_hw_params_set_channels(hDevice,hw,channels)
value=frequency 'set speed
ret = snd_pcm_hw_params_set_rate_near(hDevice,hw,@value,@direction)
ret = snd_pcm_hw_params(hDevice,hw)
ret = snd_pcm_hw_params_get_buffer_size(hw, @nFrames)
nFrames/=SampleSize
snd_pcm_hw_params_free (hw)
snd_pcm_prepare(hDevice)
buffer_size=snd_pcm_avail(hDevice)
elseif OSS then
if OSS>0 then close OSS
OSS=FreeFile
open "/dev/dsp" for output as #1
dim as long arg
arg=IIF(bits=16, AFMT_S16_LE, AFMT_U8)
ioctl fileno(cast (any ptr,fileattr(1,2))), SNDCTL_DSP_SETFMT, @arg
arg=IIF(channels<>0, 1, 0)
ioctl fileno(cast (any ptr,fileattr(1,2))), SNDCTL_DSP_STEREO, @arg
arg=channels
ioctl fileno(cast (any ptr,fileattr(1,2))), SNDCTL_DSP_CHANNELS, @arg
arg=frequency
ioctl fileno(cast (any ptr,fileattr(1,2))), SNDCTL_DSP_SPEED, @arg
end if
end sub
sub playbuffer (soundBuffer as any ptr, buffersize as long)
if alsa then
dim Count as long
buffersize/=SampleSize
Count=buffersize
if buffersize>nFrames then buffersize=nFrames
do while Count>0
ret=snd_pcm_writei(hDevice, soundBuffer, buffersize)
if ret=EPIPE then
ret=snd_pcm_recover(hDevice, ret,1)
if ret=0 then ret=snd_pcm_writei(hDevice, soundBuffer, buffersize) else exit do
end if
count -=ret
soundBuffer += ret*SampleSize
loop
elseif OSS>0 then
put #OSS, ,*cast(ubyte ptr, soundBuffer), buffersize
end if
end sub
function SoundQueue() as integer
if alsa then
dim value as long
value=snd_pcm_avail(hDevice)
if value<0 then
return 0
else
return (buffer_size-value)*SampleSize
end if
'snd_pcm_delay(hDevice, @value)
'return value*SampleSize
elseif OSS>0 then
dim value as long
ioctl fileno(cast (any ptr,fileattr(1,2))), SNDCTL_DSP_GETODELAY, @value
return value
end if
end function
SoundSet 44100, 2, 16
dim as short Buffer(4096)
do
for i as integer=0 to 4094 step 2
Buffer(i)=(i mod 200) * 20
Buffer(i+1)=(i mod 200) * 20
next
PlayBuffer @Buffer(0),8192
do
sleep 1
loop until SoundQueue()<8192
loop until multikey(1)