GNet Voip

BlitzMax Forums/BlitzMax Programming/GNet Voip

Arska(Posted 2015) [#1]
Found this mic recording code from forums and i am curious how can i send sound data over gnet networking? Is it possible?


SuperStrict

' from <a href="http://code.google.com/p/Max-edit/source/browse/#svn/trunk/Mod/axe.Mod/oggsaver.mod" target="_blank">http://code.google.com/p/Max-edit/source/browse/#svn/trunk/Mod/axe.Mod/oggsaver.mod</a>
'Import axe.oggsaver '<---- this is ok!

EnableOpenALAudio()
SetAudioDriver("OpenAL")
Graphics 500,30,0

' create the openal sampler
Local Sampler:TOpenALSampler = TOpenALSampler.Create(44100,SF_STEREO16LE)
Local AudioSample:TAudioSample
Local Sound:TSound 
Local Channel:TChannel
Local mode:Int

Repeat
	Cls
	Select mode
		Case 0 ' idle, wait to start recording
			DrawText("Idle... Press SPACE to start recording",10,10)
			If KeyHit(KEY_SPACE)
				Sampler.Start
				Mode:+1
			EndIf
		Case 1	' record
			DrawText("Recording..."+Sampler.Size+" bytes - Press SPACE to stop",10,10)
			If KeyHit(KEY_SPACE)
				AudioSample = Sampler.Stop()
				
				' if you have axe.oggsaver
				'SaveOGG(AudioSample,AppDir + "/recorded.ogg")
				
				Mode:+1
			EndIf
		Case 2	' idle, wait to playback recorded sound
			DrawText("Recorded "+AudioSample.length + " samples - Press SPACE to start playback",10,10)
						
			If KeyHit(KEY_SPACE)
				Sound = LoadSound(AudioSample)
				Channel = PlaySound(sound)
				Mode:+1
				
				
				
			EndIf
		Case 3	' playing
			DrawText("Playing... Press SPACE to stop playback",10,10)
			If ChannelPlaying(Channel)=False Or KeyHit(KEY_SPACE)
				StopChannel(Channel)
				Mode=0
			EndIf
	EndSelect
	Flip
Until AppTerminate() Or KeyHit(KEY_ESCAPE)

' ---------------------------------------------------------------------------------
' the sampler!

Type TOpenALSampler

	Field ChunkList:TList = New TList
	Field recordedsamplelength:Int
	Field DefaultSpecifier:String 
	Field CaptureDevice:Int
	Field oalFormat:Int
	Field Format:Int
	Field Hertz:Int
	Field Timer:TTimer
	Field Size:Int

	' create a recorder
	Function Create:TOpenALSampler(Hertz:Int=44100,Format:Int=SF_STEREO16LE)
		Local This:TOpenALSampler = New TOpenALSampler 
		This.DefaultSpecifier = String.FromCString(alcGetString(Null, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)) ; This.OpenALError
		This.Hertz = Hertz
		This.Format = Format
		Select format
			Case SF_MONO8		; This.oalFormat = AL_FORMAT_MONO8
			Case SF_MONO16LE 	; This.oalFormat = AL_FORMAT_MONO16
			Case SF_MONO16BE 	; This.oalFormat = AL_FORMAT_MONO16
			Case SF_STEREO8		; This.oalFormat = AL_FORMAT_STEREO8
			Case SF_STEREO16LE 	; This.oalFormat = AL_FORMAT_STEREO16
			Case SF_STEREO16BE 	; This.oalFormat = AL_FORMAT_STEREO16
		EndSelect
		This.CaptureDevice = alcCaptureOpenDevice(This.DefaultSpecifier,Hertz,This.oalFormat,44100*16) ; This.OpenALError
		Return This
	EndFunction
	
	' start recording
	Method Start()
		If Timer Return
		Timer = CreateTimer(60)
		AddHook EmitEventHook,eventhook,Self
		alcCaptureStart(CaptureDevice)	; OpenALError
	EndMethod

	' stop recording and return a TAudioSample
	Method Stop:TAudioSample()
		StopTimer Timer ; Timer = Null
		RemoveHook EmitEventHook,eventhook,Self
		alcCaptureStop(CaptureDevice) ; OpenALError
		' REMMED OUT because captures would get to long 'CaptureAudioChunk	' flush remaining audio
		Local samplesbank:TBank
		Local AudioSample:TAudioSample = CreateAudioSample((size/BytesPerSample[format]),hertz,format)
		Local bptr:Byte Ptr = AudioSample.samples
		
		'ChunkList.removelast()
		
		For samplesbank=EachIn ChunkList
			MemCopy(bptr,BankBuf(samplesbank),BankSize(samplesbank))
			bptr:+BankSize(samplesbank)
		Next
		ClearList(ChunkList)
		Size=0
		Return AudioSample
	EndMethod

	Function eventhook:Object(id:Int,data:Object,context:Object)
		Local Sampler:TOpenALSampler = TOpenALSampler(context)
		If Sampler
			Local event:TEvent = TEvent(data)
			If Event.ID=EVENT_TIMERTICK And Event.Source=Sampler.Timer
				Sampler.CaptureAudioChunk
			EndIf
		EndIf
		Return data
	EndFunction

	Method CaptureAudioChunk()
		Local recordedsamplelength:Int
		alcGetIntegerv(CaptureDevice,ALC_CAPTURE_SAMPLES,4,Varptr recordedsamplelength) ; OpenALError
		If recordedsamplelength
			Local samplesbank:TBank = CreateBank(recordedsamplelength*BytesPerSample[format])
			alcCaptureSamples(CaptureDevice,BankBuf(samplesbank),recordedsamplelength) ; OpenALError
			ListAddLast(ChunkList,samplesbank)
			Size:+BankSize(samplesbank)
		EndIf
	EndMethod

	Method OpenALError()
		Local result:Int = alcGetError(CaptureDevice)
		If result<>0 RuntimeError "Sampler OpenAL Error Code = "+result
	EndMethod

EndType



Derron(Posted 2015) [#2]
Dunno if it works with "gnet" (or if you need to directly send via "enet").

Idea is the following:
Save the microphone record into a databuffer (eg. X kilobytes long, then move along an "position" number).

With gnet/enet/... you send portions of this databuffer to others (as soon as filled data length > your desired "packet" size).

On the remote side you fill again this "record databuffer" (maybe call it remoteRecordDatabuffer). As soon as enough data is buffered you can start playing.

If one of the both connection sides does not send enough data - or does receive enough data you should stop playing the sound back (to avoid garbage sound output).


buffer length depends on sound quality (higher quality = less "speaking duration" in the same buffer).


bye
Ron