Linux Sound - Alsa

Archives Forums/BlitzMax Bug Reports/Linux Sound - Alsa

ingenius(Posted 2010) [#1]
Hi,

In the last version of ubuntu, the OSS support is missing, I have tried to modify freeaudio.mod to support ALSA without results.

Does anyone have the same problem ?

Regards
Inge


jkrankie(Posted 2010) [#2]
Yep, it's pretty annoying. One of the users in my forum reckons this script works for him with Irukandji (one of my games):

sh -c "<path to Irukandji> && padsp ./Irukandji"

It's basically running the game with padsp.

Cheers
Charlie


ingenius(Posted 2010) [#3]
Yes, I did work with aoss ( ALSA wrapper for OSS applications ) , but I have a delay in sound which is annoying.


ingenius(Posted 2010) [#4]
I've done, BlitzMax working with alsa support. In a few minutes I will send the modifications.

We need test it thoroughly to see that everything works fine.


ingenius(Posted 2010) [#5]
Ok

Path - mod/pub.mod/freeaudio.mod

alsadevice.cpp
// alsadevice.cpp

#ifdef __linux

#include "freeaudio.h"

#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/soundcard.h>
#include <pthread.h>

#include <alsa/asoundlib.h>
#include <alsa/pcm.h>

extern "C" audiodevice *OpenALSADevice();

void *alsaaudiothread(void *dev);

#define LINUXFRAG 2048

struct alsaaudio:audiodevice{
	pthread_t	audiothread;
	int			threadid;
	int			running,playing;
	short		*buffer;
	int			buffersize;	//in bytes
	
	int reset(){
		running=1;
		playing=0;
		mix=new mixer(LINUXFRAG);
		mix->freq=44100;
		mix->channels=2;
		buffer=new short[LINUXFRAG];
		buffersize=LINUXFRAG*2;
		pthread_attr_t	attr;
		pthread_attr_init(&attr);
		threadid=pthread_create(&audiothread,&attr,alsaaudiothread,(void*)this);	
		return 0;
	}
	
	int close(){	
		int		timeout;
		running=0;
		timeout=5;
		while (timeout-- && playing) sleep(1);
		return 0;
	}
};


void *alsaaudiothread(void *v){
	int						policy;
	sched_param		sched;	
	int						err;
	alsaaudio 		*dev;
	
	pthread_getschedparam(pthread_self(),&policy,&sched);
	sched.sched_priority++;//policy=SCHED_RR;
	pthread_setschedparam(pthread_self(),policy,&sched);	
	dev=(alsaaudio*)v;

	unsigned int val;
	snd_pcm_t *fd;
	snd_pcm_uframes_t periodsize;
	snd_pcm_hw_params_t *hwparams;
	snd_pcm_hw_params_alloca(&hwparams);
	int output_rate;
	int channels;
	int fragment_size;
	int fragment_count;

	err=snd_pcm_open(&fd, strdup("default"), SND_PCM_STREAM_PLAYBACK, 0);
	if (err<0) return 0;

	fragment_size=LINUXFRAG;  //overall buffer size
	fragment_count=2; //2 - 16 fragment count - 2 minimum, the lower it is potentially the lower the latency

//configure device
	if (snd_pcm_hw_params_any(fd, hwparams) < 0) {
		//printf("linuxaudio failed at params any\n");
		return 0;
	}	
	if (snd_pcm_hw_params_set_access(fd, hwparams,SND_PCM_ACCESS_RW_INTERLEAVED) < 0) {
		//printf("linuxaudio failed at set access\n");
		return 0;
	}	
	
	if (snd_pcm_hw_params_set_format(fd, hwparams,SND_PCM_FORMAT_S16_LE) < 0) {
		//printf("linuxaudio failed at set format\n");
		return 0;
	}
	val = 44100;
	if (snd_pcm_hw_params_set_rate_near(fd, hwparams,&val, 0) < 0) {
		// Try 48KHZ too 
		//printf("linuxaudio - %d HZ not available, trying 48000HZ\n", output_rate);
		val = 48000;
		if (snd_pcm_hw_params_set_rate_near(fd, hwparams,&val, 0) < 0) {
			//printf("linuxaudio failed at setting output rate (%d)\n", output_rate);
			return 0;
		}
		dev->mix->freq=val;		
	}
	channels=2;
	if (snd_pcm_hw_params_set_channels(fd, hwparams, channels) < 0) {
		//printf("linuxaudio failed at set channels (%d)\n", channels);
		return 0;
	}
	periodsize = (fragment_size) / 4; // bytes -> frames for 16-bit,stereo - should be a minimum of 512
	if (snd_pcm_hw_params_set_period_size_near(fd, hwparams,&periodsize, 0) < 0) {
		//printf("linuxaudio failed at set period size (%d)\n", (int)periodsize);			
		return 0;
	}
	val = fragment_count;
	if (snd_pcm_hw_params_set_periods_near(fd, hwparams,&val, 0) < 0) {
		//printf("linuxaudio failed at set periods (%d)\n", val);			
		//should attempt a one by one period increase up to 16?
		return 0;
	}
	if (snd_pcm_hw_params(fd, hwparams) < 0) {
		//printf("linuxaudio failed at installing hw params\n");
		return 0;
	}
	//loop while playing sound
	dev->playing=1;
	while (dev->playing)
	{
		dev->mix->mix16(dev->buffer);
		if ((snd_pcm_writei (fd, dev->buffer,LINUXFRAG/2)) < 0) {	//Half buffer for two channels?
			//printf ("linuxaudio warning: buffer underrun occurred\n");
			if (snd_pcm_prepare(fd) < 0) {
				//printf ("linuxaudio failed at preparing pcm\n");
				dev->playing=0; //die gracefully
			}
		}	
	}
	snd_pcm_drop(fd);
	snd_pcm_close (fd);
	return 0;
}

audiodevice *OpenALSADevice(){
	return new alsaaudio();
}

#endif

freeaudio.bmx
Module Pub.FreeAudio

ModuleInfo "Version: 1.22"
ModuleInfo "Author: Simon Armstrong"
ModuleInfo "License: Public Domain"
ModuleInfo "Copyright: Blitz Research Ltd"
ModuleInfo "Modserver: BRL"

ModuleInfo "History: 1.22 Release"
ModuleInfo "History: Fixed leak with sound recycling"
ModuleInfo "History: 1.21 Release"
ModuleInfo "History: Fixed reference counting for brl.freeaudioaudio"
ModuleInfo "History: 1.20 Release"
ModuleInfo "History: Removed duplication of sample memory"
ModuleInfo "History: 1.19 Release"
ModuleInfo "History: Added DirectSound mode"
ModuleInfo "History: 1.18 Release"
ModuleInfo "History: added fa_ChannelPosition for live sample generation"
ModuleInfo "History: 1.17 Release"
ModuleInfo "History: added check for windows playback position overflow"
ModuleInfo "History: 1.15 Release"
ModuleInfo "History: added low latency windows98 fix"
ModuleInfo "History: 1.14 Release"
ModuleInfo "History: fixed 1.13 recycling of stopped channels fix"
ModuleInfo "History: 1.13 Release"
ModuleInfo "History: fixed recycling of stopped channels"
ModuleInfo "History: 1.12 Release"
ModuleInfo "History: Uses linear interpolation for improved fidelity at low rates"
ModuleInfo "History: 1.11 Release"
ModuleInfo "History: Fixed freepool sounds Not resetting parameters - thanks To Fetze"
ModuleInfo "History: 1.10 Release"
ModuleInfo "History: Added ALSA support for Linux courtesy Craig Kiesau"
ModuleInfo "History: 1.09 Release"
ModuleInfo "History: Improved channel playback timing"
ModuleInfo "History: 1.08 Release"
ModuleInfo "History: Fixed memory leak in fa_FreeSound()"
ModuleInfo "History: 1.07 Release"
ModuleInfo "History: Removed output transitions for queued/paused sounds"
ModuleInfo "History: 1.06 Release"
ModuleInfo "History: Windows device error now silently fails"
ModuleInfo "History: 1.05 Release"
ModuleInfo "History: Linux version now opens audio device on second thread"
ModuleInfo "History: 1.04 Release"
ModuleInfo "History: Removed Linux debug output"

Import "freeaudio.cpp"
Import "freeaudioglue.cpp"

?Win32
Import "dsounddevice.cpp"
Import "mmdevice.cpp"
Extern "C"
Function OpenMultiMediaDevice()
Function OpenDirectSoundDevice()
End Extern
?MacOS
Import "-framework AudioUnit"
Import "-framework AudioToolbox"
Import "coreaudiodevice.cpp"
Extern
Function OpenCoreAudioDevice()
End Extern
?Linux
Import "-lasound"
Import "alsadevice.cpp"
Import "ossdevice.cpp"
Extern "C"
Function OpenOSSDevice()
Function OpenALSADevice()
End Extern
?

Extern

Const FA_CHANNELSTATUS_FREE=0
Const FA_CHANNELSTATUS_STOPPED=1
Const FA_CHANNELSTATUS_SINGLESHOT=2
Const FA_CHANNELSTATUS_LOOPING=4
Const FA_CHANNELSTATUS_STREAMING=8
Const FA_CHANNELSTATUS_PAUSED=16

Function fa_Reset( audiodevice )
Function fa_Close()
Function fa_CreateSound( length,bits,channels,hertz,samples:Byte Ptr=Null,looping=False )
Function fa_WriteSound( sound,samples:Byte Ptr,length ) 'length really neceesary?
Function fa_FreeSound( sound )
Function fa_AllocChannel()
Function fa_FreeChannel( channel )
Function fa_PlaySound( sound,paused_flag,channel )

Function fa_StopChannel( channel )
Function fa_ChannelStatus( channel )
Function fa_ChannelPosition( channel )

Function fa_SetChannelPaused( channel,paused )
Function fa_SetChannelVolume( channel,volume# )
Function fa_SetChannelRate( channel,pitch# )
Function fa_SetChannelPan( channel,pan# )
Function fa_SetChannelDepth( channel,depth# )

End Extern

Function fa_Init( deviceid )
	Local device
?Win32
	If deviceid
		device=OpenDirectSoundDevice()
	Else
		device=OpenMultiMediaDevice()
	EndIf
?Linux
	Select deviceid
		Case 0
			device=OpenOSSDevice()
		Case 1
			device=OpenALSADevice()
	EndSelect
?MacOS
	device=OpenCoreAudioDevice()
?
	Local res=-1
	If device res=fa_Reset(device)
	Return res
End Function	



Path - mod/brl.mod/freeaudioaudio.mod

freeaudioaudio.bmx
Strict
Rem
bbdoc: Audio/FreeAudio audio
about:
The FreeAudio audio module provides FreeAudio drivers for use with the #audio module.
End Rem
Module BRL.FreeAudioAudio

ModuleInfo "Version: 1.13"
ModuleInfo "Author: Mark Sibly"
ModuleInfo "License: Blitz Shared Source Code"
ModuleInfo "Copyright: Blitz Research Ltd"
ModuleInfo "Modserver: BRL"

ModuleInfo "History: 1.13 Release"
ModuleInfo "History: Fixed bug in FreeChannel Playing()"
ModuleInfo "History: 1.12 Release"
ModuleInfo "History: Added call to fa_FreeChannel to TFreeAudioChannel destructor"
ModuleInfo "History: 1.11 Release"
ModuleInfo "History: Nudge"
ModuleInfo "History: 1.10 Release"
ModuleInfo "History: Bumped"
ModuleInfo "History: 1.08 Release"
ModuleInfo "History: Added src sample reference to TFreeAudioSound"
ModuleInfo "History: Channel playing now returns sample playback position"
ModuleInfo "History: 1.07 Release"
ModuleInfo "History: Added DirectSound driver"
ModuleInfo "History: 1.06 Release"
ModuleInfo "History: Added Method TFreeAudioChannel.Position"
ModuleInfo "History: 1.05 Release"
ModuleInfo "History: Mono and 8 bit sample support added"

Import BRL.Audio
Import Pub.FreeAudio
Import Pub.DirectX

Private

Const CLOG=False

Public

Type TFreeAudioSound Extends TSound

	Field fa_sound
	
	Method Delete()
		fa_FreeSound fa_sound
		If CLOG WriteStdout "Deleted FreeAudio sound "+fa_sound+"~n"
	End Method

	Method Play:TFreeAudioChannel( alloced_channel:TChannel )
		Local channel:TFreeAudioChannel,fa_channel
		If alloced_channel
			channel=TFreeAudioChannel( alloced_channel )
			If Not channel Return
			fa_channel=channel.fa_channel
		EndIf		
		fa_channel=fa_PlaySound(fa_sound,False,fa_channel)
		If Not fa_channel Return
		If channel And channel.fa_channel=fa_channel Return channel
		Return TFreeAudioChannel.CreateWithChannel( fa_channel )
	End Method
	
	Method Cue:TFreeAudioChannel( alloced_channel:TChannel )
		Local channel:TFreeAudioChannel,fa_channel
		If alloced_channel
			channel=TFreeAudioChannel( alloced_channel )
			If Not channel Return
			fa_channel=channel.fa_channel
		EndIf
		fa_channel=fa_PlaySound( fa_sound,True,fa_channel )
		If Not fa_channel Return
		If channel And channel.fa_channel=fa_channel Return channel
		Return TFreeAudioChannel.CreateWithChannel( fa_channel )
	End Method

	Function CreateWithSound:TFreeAudioSound( fa_sound,src:TAudioSample )
		Local t:TFreeAudioSound=New TFreeAudioSound
		t.fa_sound=fa_sound
'		t.src=src
		Return t
	End Function
	
End Type

Type TFreeAudioChannel Extends TChannel

	Field fa_channel
	
	Method Delete()
		If fa_channel fa_FreeChannel fa_channel
	End Method

	Method Stop()
		fa_StopChannel fa_channel
		fa_channel=0
	End Method
	
	Method SetPaused( paused )
		fa_SetChannelPaused fa_channel,paused
	End Method
	
	Method SetVolume( volume# )
		fa_SetChannelVolume fa_channel,volume
	End Method
	
	Method SetPan( pan# )
		fa_SetChannelPan fa_channel,pan
	End Method
	
	Method SetDepth( depth# )
		fa_SetChannelDepth fa_channel,depth
	End Method
	
	Method SetRate( rate# )
		fa_SetChannelRate fa_channel,rate
	End Method
	
	Method Playing()
		Local status=fa_ChannelStatus( fa_channel ) 
		If status=FA_CHANNELSTATUS_FREE Return False
		If status&FA_CHANNELSTATUS_STOPPED Return False
		If status&FA_CHANNELSTATUS_PAUSED Return False
		Return True
	End Method
	
	Method Position()
		Return fa_ChannelPosition( fa_channel )
	End Method
	
	Function CreateWithChannel:TFreeAudioChannel( fa_channel )
		Local t:TFreeAudioChannel=New TFreeAudioChannel
		t.fa_channel=fa_channel
		Return t
	End Function
	
End Type

Type TFreeAudioAudioDriver Extends TAudioDriver

	Method Name$()
		Return _name
	End Method
	
	Method Startup()
		If _mode<>-1 Return fa_Init( _mode )<>-1
		If fa_Init( 0 )<>-1 Return True
?Win32
		Return fa_Init( 1 )<>-1
?
	End Method
	
	Method Shutdown()
		fa_Close
	End Method

	Method CreateSound:TFreeAudioSound( sample:TAudioSample,flags )
		Local channels,bits

		Select sample.format
?BigEndian
		Case SF_MONO16LE
			sample=sample.Convert(SF_MONO16BE)
		Case SF_STEREO16LE
			sample=sample.Convert(SF_STEREO16BE)
?LittleEndian
		Case SF_MONO16BE
			sample=sample.Convert(SF_MONO16LE)
		Case SF_STEREO16BE
			sample=sample.Convert(SF_STEREO16LE)
?
		End Select
		Local loop_flag
		If (flags & 1) loop_flag=-1
		channels=ChannelsPerSample[sample.format]
		If Not channels Return
		bits=8*BytesPerSample[sample.format]/channels
		Local fa_sound=fa_CreateSound( sample.length,bits,channels,sample.hertz,sample.samples,loop_flag )
		If CLOG WriteStdout "Generated FreeAudio sound "+fa_sound+"~n"
		Return TFreeAudioSound.CreateWithSound( fa_sound,sample )
	End Method
	
	Method AllocChannel:TFreeAudioChannel()
		Local fa_channel=fa_AllocChannel()
		If fa_channel Return TFreeAudioChannel.CreateWithChannel( fa_channel )
	End Method
		
	Function Create:TFreeAudioAudioDriver( name$,mode )
		Local t:TFreeAudioAudioDriver=New TFreeAudioAudioDriver
		t._name=name
		t._mode=mode
		Return t
	End Function
	
	Field _name$,_mode
	
End Type

?Win32
If DirectSoundCreate TFreeAudioAudioDriver.Create "FreeAudio DirectSound",1
TFreeAudioAudioDriver.Create "FreeAudio Multimedia",0
?MacOS
TFreeAudioAudioDriver.Create "FreeAudio CoreAudio",0
?Linux
' TFreeAudioAudioDriver.Create "FreeAudio OpenSound System",0
TFreeAudioAudioDriver.Create "FreeAudio ALSA System",1
?
TFreeAudioAudioDriver.Create "FreeAudio",-1



jkrankie(Posted 2010) [#6]
Cool! I'll try to get a chance to look at this over the weekend.

What exactly were the changes?

Cheers
Charlie


oddchild(Posted 2011) [#7]
I have tried this and numerous other posts but still do not have sound with any of my blitzmax applications. I have ubuntu 10.10.

Maybe it is this computer? I had another computer with Ubuntu installed, and it worked fine. When I switched computers, it stopped working. I have tried installing all the packages, and this mod. Any other ideas?