01-23-2006, 10:17 AM
Hello red_Marvin you are the only that will help to make the Win and Lin soundlib true thx for this.
It seams to be that i have found the problem.
in 16 bit most of all cards are can pay with singned 16 bit
but in 8 bit the most can play with unsigned 8bit
Please test all lines (but only one in same time)
it works on my 3 linux boxes with difrent soundcards.
If you get any mode not working please tell me witch mode makes trouble. and what is your kernel 2.4.x or 2.6.x and the alsa version.
Details what goes wrong 8/16 Bit 1/2 Channels
if you post the plot or mp3 won't help i need the parameters
Again thank you very mutch.
Joshy
It seams to be that i have found the problem.
in 16 bit most of all cards are can pay with singned 16 bit
but in 8 bit the most can play with unsigned 8bit
Please test all lines (but only one in same time)
Code:
'Player=Alsa_Init(,22050, 8,1)
'Player=Alsa_Init(,22050, 8,2)
'Player=Alsa_Init(,22050,16,1)
'Player=Alsa_Init(,22050,16,1)
'Player=Alsa_Init(,44100, 8,2)
Player=Alsa_Init(,44100,16,2)
'Player=Alsa_Init(,48000,16,1)
'Player=Alsa_Init(,48000,16,1)
it works on my 3 linux boxes with difrent soundcards.
If you get any mode not working please tell me witch mode makes trouble. and what is your kernel 2.4.x or 2.6.x and the alsa version.
Details what goes wrong 8/16 Bit 1/2 Channels
if you post the plot or mp3 won't help i need the parameters
Again thank you very mutch.
Joshy
Code:
option explicit
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
type snd_pcm_t as _snd_pcm
type snd_pcm_hw_params_t as _snd_pcm_hw_params
' PCM
declare function snd_pcm_open cdecl alias "snd_pcm_open" ( _
byval pcm as snd_pcm_t ptr ptr, _
byval device as string, _
byval direction as integer, _
byval mode as integer) as integer
declare function snd_pcm_close cdecl alias "snd_pcm_close" ( _
byval pcm as snd_pcm_t ptr) as integer
declare function snd_pcm_hw_free cdecl alias "snd_pcm_hw_free" ( _
byval pcm as snd_pcm_t ptr) as integer
declare function snd_pcm_nonblock cdecl alias "snd_pcm_nonblock" ( _
byval pcm as snd_pcm_t ptr, _
byval nonblock as integer) as integer
declare function snd_pcm_prepare cdecl alias "snd_pcm_prepare" ( _
byval pcm as snd_pcm_t ptr) as integer
declare function snd_pcm_writei cdecl alias "snd_pcm_writei" ( _
byval pcm as snd_pcm_t ptr, _
byval buffer as any ptr, _
byval size as integer) as integer
declare function snd_pcm_resume cdecl alias "snd_pcm_resume" ( _
byval pcm as snd_pcm_t ptr) as integer
'hardware
declare function snd_pcm_hw_params_malloc cdecl alias "snd_pcm_hw_params_malloc" ( _
byval hw as snd_pcm_hw_params_t ptr ptr) as integer
declare function snd_pcm_hw_params_any cdecl alias "snd_pcm_hw_params_any" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr) as integer
declare function snd_pcm_hw_params_set_access cdecl alias "snd_pcm_hw_params_set_access" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr, _
byval mode as integer) as integer
declare function snd_pcm_hw_params_set_format cdecl alias "snd_pcm_hw_params_set_format" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr, _
byval fmt as integer) as integer
declare function snd_pcm_hw_params_set_channels cdecl alias "snd_pcm_hw_params_set_channels" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr, _
byval Channels as integer) as integer
declare function snd_pcm_hw_params_get_channels cdecl alias "snd_pcm_hw_params_get_channels" ( _
byval hw as snd_pcm_hw_params_t ptr, _
byval lpChannels as integer ptr) as integer
declare function snd_pcm_hw_params_set_rate_near cdecl alias "snd_pcm_hw_params_set_rate_near" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr, _
byval lpRate as integer ptr, _
byval lpDir as integer ptr) as integer
declare function snd_pcm_hw_params_set_periods_near cdecl alias "snd_pcm_hw_params_set_periods_near" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr, _
byval lpValue as integer ptr, _
byval lpDir as integer ptr) as integer
declare function snd_pcm_hw_params_get_period_size cdecl alias "snd_pcm_hw_params_get_period_size" ( _
byval params as snd_pcm_hw_params_t ptr, _
byval lpFrames as integer ptr, _
byval lpDir as integer ptr) as integer
declare function snd_pcm_hw_params_set_buffer_size_near cdecl alias "snd_pcm_hw_params_set_buffer_size_near" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr, _
byval lpFrames as integer ptr) as integer
declare function snd_pcm_hw_params_get_buffer_size cdecl alias "snd_pcm_hw_params_get_buffer_size" ( _
byval hw as snd_pcm_hw_params_t ptr, _
byval lpFrames as integer ptr) as integer
declare function snd_pcm_hw_params cdecl alias "snd_pcm_hw_params" ( _
byval pcm as snd_pcm_t ptr, _
byval hw as snd_pcm_hw_params_t ptr) as integer
declare sub snd_pcm_hw_params_free cdecl alias "snd_pcm_hw_params_free" ( _
byval hw as snd_pcm_hw_params_t ptr)
#inclib "asound"
'#define device "plughw:0,0"
'#define device "hw:0,0"
union uniptr
ptr8 as byte ptr ' -128 to +127
ptr16 as short ptr '-32768 to +32767
end union
type player_driver_t
handle as snd_pcm_t ptr 'NULL = Error
Speed as integer ' 11025 22050 44100
nChannels as integer ' 1 or 2
nBits as integer ' 8 or 16
nFrames as integer ' 512,1024,2048,4096 and so on
FrameSize as integer ' (nBits\8) * nChannels
nPeriods as integer ' try 2
PeriodSize as integer ' BufferSize / FrameSize
Buffer as uniptr
end type
function Alsa_Init(byval strDevice as string="hw:0,0", _
byval Speed as integer=44100, _
byval Bits as integer=16, _
byval Channels as integer=2, _
byval Frames as integer=4096) as player_driver_t ptr
Bits \=8
Frames\=256
' range of Speed
if Speed < 11025 then
Speed = 11025
elseif Speed>48000 then
Speed = 48000
end if
' range of Bits
if Bits<1 then
Bits=1
elseif Bits>2 then
Bits=2
end if
' range of Channels
if Channels<1 then
Channels=1
elseif Channels>2 then
Channels=2
end if
' range of frames
if Frames<2 then
Frames=2
elseif Frames>32 then
Frames=32
end if
Bits = Bits shl 3 ' * 8
Frames = Frames shl 7 ' * 256
dim as snd_pcm_t ptr htmp
dim as snd_pcm_hw_params_t ptr hw
dim as integer ret, direction,PeriodSize
dim as player_driver_t ptr tmp
dim as zstring ptr strRet
' open device in non blocking mode
ret = snd_pcm_open(@htmp, strDevice, SND_PCM_STREAM_PLAYBACK, NONBLOCK)
if (ret < 0) then ? "failed open":goto Alsa_Init_Error
' switch to blocking mode
ret=snd_pcm_nonblock(htmp,BLOCK)
if (ret < 0) then ? "failed block":goto Alsa_Init_Error
'alloc the player
tmp=callocate(sizeof(player_driver_t))
tmp->Speed = Speed
tmp->nChannels = Channels
tmp->nBits = Bits
tmp->FrameSize = (Bits \ 8) * Channels
tmp->nFrames = Frames
tmp->nPeriods = 2
tmp->PeriodSize = 0
' qwery param
snd_pcm_hw_params_malloc(@hw)
ret = snd_pcm_hw_params_any(htmp,hw)
if (ret < 0) then ? "failed hw_param_any":goto Alsa_Init_Error
' set read write access
ret = snd_pcm_hw_params_set_access(htmp, hw, SND_PCM_ACCESS_RW_INTERLEAVED)
if (ret < 0) then ? "failed set_access":goto Alsa_Init_Error
if tmp->nBits=8 then
ret = snd_pcm_hw_params_set_format(htmp,hw,1) 'set 8bit unsigned
'if (ret<0) then ret = snd_pcm_hw_params_set_format(htmp,hw,1) 'set 8bit signed
else
ret = snd_pcm_hw_params_set_format(htmp,hw,2) ' set 16bit unsigned
end if
if (ret < 0) then ? "failed set_format":goto Alsa_Init_Error
'set mono or stero
ret = snd_pcm_hw_params_set_channels(htmp,hw, tmp->nChannels)
if (ret < 0) then
snd_pcm_hw_params_get_channels(hw,@tmp->nChannels)
if (tmp->nChannels<>Channels) then ? "warning: use channels=";tmp->nChannels
end if
'set speed
ret = snd_pcm_hw_params_set_rate_near(htmp,hw,@tmp->Speed,0)
if (ret < 0) then
? "failed set_rate_near":goto Alsa_Init_Error
elseif (ret > 0) then
tmp->Speed=ret
end if
if tmp->Speed<>Speed then ? "warning: use speed";tmp->Speed
' set number of Frames
ret = snd_pcm_hw_params_set_buffer_size_near(htmp, hw, @tmp->nFrames)
if (ret < 0) then ? "failed set_buffer_size_near":goto Alsa_Init_Error
' Chunks of Frames
ret = snd_pcm_hw_params_set_periods_near(htmp, hw,@tmp->nPeriods, 0)
if (ret < 0) then ? "failed set_periods_near":goto Alsa_Init_Error
snd_pcm_hw_params_get_period_size(hw,@tmp->PeriodSize,@Direction)
' set the config
ret = snd_pcm_hw_params(htmp,hw)
if (ret < 0) then ? "failed hw_params":goto Alsa_Init_Error
ret = snd_pcm_prepare(htmp)
if (ret < 0) then ? "failed prepare":goto Alsa_Init_Error
Alsa_Init_Ok:
tmp->Handle=htmp
snd_pcm_hw_params_free hw
return tmp
Alsa_Init_Error:
if hw <>0 then snd_pcm_hw_params_free hw
if htmp<>0 then snd_pcm_close htmp
if tmp <>0 then deallocate tmp
return 0
end function
sub Alsa_Exit(byval pcm as snd_pcm_t ptr)
if pcm=0 then exit sub
? snd_pcm_close(pcm)
end sub
sub Alsa_Info(byval player as player_driver_t ptr)
? "Alsa_Info"
? "-------------------"
if player=0 then ? "not init":exit sub
? "speed :" ; player->Speed
? "bits :" ; player->nBits
? "channels :" ; player->nChannels
? "frames :" ; player->nFrames
? "framesize :" ; player->FrameSize
? "chunks :" ; player->nPeriods
? "chunksize :" ; player->PeriodSize
end sub
sub Alsa_Send(byval player as player_driver_t ptr,byval nBytes as integer)
dim as integer ret,nFrames
dim as any ptr lpStart,lpEnd
if player =0 then exit sub
if player->Handle =0 then exit sub
if player->Buffer.ptr8=0 then exit sub
if nBytes <1 then exit sub
nFrames = nBytes \ Player->FrameSize
lpStart=Player->Buffer.ptr8
lpEnd =Player->Buffer.ptr8+nBytes
while(lpStart<lpEnd)
ret = snd_pcm_writei(Player->Handle,lpStart,nFrames)
if (ret=-EAGAIN) then
' device busy
elseif (ret=-ESTRPIPE) then
ret=-EAGAIN
while ret=-EAGAIN:ret=snd_pcm_resume(Player->Handle):wend
elseif (ret=-EPIPE) then
else
if (ret<0) then ? "failed send audiodata"
if snd_pcm_prepare(Player->Handle) < 0 then exit sub
nFrames-=ret:lpStart+=ret*Player->FrameSize
endif
wend
end sub
sub Fill_Buffer(byval Player as player_driver_t ptr,byval freq as integer=440)
static as integer l,r
static as double w1,w2
dim as double pif,scale,scale2
dim as integer i
if Player=0 then exit sub
if Player->Buffer.ptr8=0 then exit sub
pif=(8.0*atn(1))/player->Speed
scale =pif*freq
scale2=pif*60
if Player->nBits=8 then
if Player->nChannels=1 then
for i=0 to Player->nFrames*Player->nPeriods-1
l=cubyte(sin(w1)*cos(w2)*64+64)
player->Buffer.ptr8[i ]=l
w1+=scale
next
else
for i=0 to Player->nFrames*Player->nPeriods*Player->nChannels - 1 step 2
l=cubyte(sin(w1) *cos(w2 )*64+64)
r=cubyte(sin(w1*2.01)*cos(w2*2)*64+64)
player->Buffer.ptr8[i ]=l
player->Buffer.ptr8[i+1]=r
w1+=scale:w2+=scale2
next
end if
else
if Player->nChannels=1 then
for i=0 to Player->nFrames*Player->nPeriods - 1
l=cushort(sin(w1)*cos(w2)*8000+8000)
player->Buffer.ptr16[i ]=l
w1+=scale
next
else
for i=0 to Player->nFrames*Player->nPeriods*Player->nChannels - 1 step 2
l=cshort(sin(w1) *cos(w2 )*8000+8000)
r=cshort(sin(w1*2.01)*cos(w2*2)*8000+8000)
player->Buffer.ptr16[i ]=l
player->Buffer.ptr16[i+1]=r
w1+=scale:w2+=scale2
next
end if
end if
end sub
'
' main
'
dim as player_driver_t ptr player
dim as integer f
'Player=Alsa_Init(,22050, 8,1)
'Player=Alsa_Init(,22050, 8,2)
'Player=Alsa_Init(,22050,16,1)
'Player=Alsa_Init(,22050,16,1)
'Player=Alsa_Init(,44100, 8,2)
Player=Alsa_Init(,44100,16,2)
'Player=Alsa_Init(,48000,16,1)
'Player=Alsa_Init(,48000,16,1)
if Player=0 then end 1
Alsa_Info Player
player->Buffer.ptr8=allocate(Player->nFrames*Player->FrameSize*Player->nPeriods)
sleep 1000,1
while inkey=""
f=int(rnd*880)
Fill_Buffer player,f
Alsa_Send player,Player->nFrames*Player->FrameSize*Player->nPeriods
wend
end
sorry about my english