record with OpenAL

BlitzMax Forums/BlitzMax Programming/record with OpenAL

Hello !

I would like to know if there is a simple tutorial to record a sound in a buffer with OpenAL with Bmax.

I've found a tutorial in C++ on the web but nothing in Bmax.

Thanks a lot......................

There isn't. Satisfied?

Thanks again !!

Ok, no support for Bmax, i've lost my money... "je change de crèmerie !"

Is OpenAL fully wrapped in a BMax module?

I'll have max next week some time, I'll be porting my B3D openal code/knowledge over to max.

I don't understand your question, LarsG. Sorry.
(I'm from Corsica and my english speaking is poor)

My problem is simple : I'm working on A.I systems, and i must do some experiences sometime.
So, now, i try to make communicate two computers ( one with windows, one with linux) with a very simplified system via microphones and speakers. (like a human can do with ears and mouth)

When one of the computer will need to talk (with squares wav files), the other will have to recognise the frequency, etc...

This is not so hard but i can't record anything with Bmax for now.

A little help will be very appreciated.
If nothing is possible at this time, thanks to tell me it.

Thanks Tom ;-)

List input devices:
alcGetString(Null, ALC_CAPTURE_DEVICE_SPECIFIER)

Default input device:
alcGetString(Null, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER)

Open device:
alcCaptureOpenDevice(...)

Start recording:
alcCaptureStart(...)

Stop recording.
alcCaptureStop()

Get number of captured samples
alcGetIntegerv(Recorder, ALC_CAPTURE_SAMPLES, 4, Varptr(NumSamples))

Get samples:
alcCaptureSamples(...)

Very easy ^^
cu olli

Thanks a lot Vertex :-)

I've done that finally. It works a little but not perfectly.
Does someone see the problem, please ? (just test to listen what is the problem.)

'====================================
'          square reptile
'====================================

' record test

If OpenALInstalled()=False Then RuntimeError "You need to install OpenAL !"
EnableOpenALAudio()
SetAudioDriver("OpenAL")

Global Device
Global CaptureDevice
Device=alcOpenDevice(Null)

If Device=Null Then RuntimeError "No access to OpenAL Device !"

Local flag=InitCapture()
If flag=False Then  RuntimeError "No access to OpenAL capture Device !"


Graphics 640,480,0
SeedRnd MilliSecs()
SetClsColor 0,0,0
SetColor 255,255,255

Cls
DrawText "push [RETURN] to start 5 seconds of recording",0,0
Flip

Global sample:TAudioSample=CreateAudioSample(44100*5*2,44100,SF_MONO16LE)


Global NumSamples:Int
Global sound

While KeyDown(KEY_RETURN)=0
	If KeyDown(KEY_ESCAPE)=1
		ShutdownOpenAL()
		End
	EndIf
Wend
Cls
DrawText "RECORDING...",0,0
Flip

alcCaptureStart(CaptureDevice)
Delay 5000
alcCaptureStop(CaptureDevice)
alcGetIntegerv(CaptureDevice, ALC_CAPTURE_SAMPLES, 4, Varptr(NumSamples))
alcCaptureSamples(CaptureDevice, sample.Samples, NumSamples)

sound=LoadSound( sample,False )

Cls
DrawText "PLAYING...",0,0
Flip

PlaySound sound
Delay 5000

ShutdownOpenAL()

End

'============================================================================================

Function InitCapture()

    If (alcIsExtensionPresent(Device, "ALC_EXT_CAPTURE") = AL_FALSE) Then Return False

    CaptureDevice = alcCaptureOpenDevice(Null, 44100, AL_FORMAT_MONO16, 44100*5*2);
    If Not(CaptureDevice) Then Return False

    Return True
EndFunction


Function ShutdownOpenAL()
    alcCloseDevice(CaptureDevice)
    alcCloseDevice(Device)
EndFunction


My test:
SuperStrict

Framework Vertex.OpenAL

Const SECONDS : Int = 5

Global Specifiers       : String[], ..
       Specifier        : String, ..
       DefaultSpecifier : String, ..
       Index            : Int, ..
       Input            : String, ..
       Recorder         : Byte Ptr, ..
       Samples          : Byte Ptr, ..
       NumSamples       : Int

Global AudioDevice      : Byte Ptr, ..
       Context          : Byte Ptr, ..
       Source           : Int, ..
       Buffer           : Int, ..
       State            : Int

Try

TOpenAL.Init()

' Recorder
Specifiers = EnumDevices(ALC_CAPTURE_DEVICE_SPECIFIER)
If Not Specifiers Then Throw("No recorders where found")
DefaultSpecifier = String.FromCString(..
                    alcGetString(Null, ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER))

WriteStdout("Recorders~n")
For Index = 0 Until Specifiers.Length
	Specifier = Specifiers[Index]
	WriteStdout(" " + (Index + 1) + ") " + Specifier)
	If Specifier = DefaultSpecifier Then
		WriteStdout("(Default)~n")
	Else
		WriteStdout("~n")
	EndIf
Next

WriteStdout("Index: ") ; Input = ReadStdin()
If Input Then
	Index = Input.ToInt()
	If Index < 1 Or Index > Specifiers.Length Then ..
		Throw("Index out of range")
	Specifier = Specifiers[Index - 1]
Else
	Specifier = DefaultSpecifier
EndIf

Recorder = alcCaptureOpenDevice(Specifier, 44100, AL_FORMAT_MONO16, ..
                                SECONDS*44100*2)
If Not Recorder Then Throw("Unable to open recorder")

Samples = MemAlloc(SECONDS*44100*2)

' Audio Output
AudioDevice = alcOpenDevice(Null)
If Not AudioDevice Then Throw("Unable to open audio output device")

Context = alcCreateContext(AudioDevice, Null)
If Not Context Then Throw("Unable to create audio context")

If Not alcMakeContextCurrent(Context) Then ..
	Throw("unable to make context current")

alGenSources(1, Varptr(Source))
alGenBuffers(1, Varptr(Buffer))

' Start recording
alcCaptureStart(Recorder)
Repeat
	alcGetIntegerv(Recorder, ALC_CAPTURE_SAMPLES, 4, Varptr(NumSamples))
	WriteStdout(NumSamples + "/" + SECONDS*44100 + " Samples~n")
	Delay(100)
Until NumSamples >= SECONDS*44100
alcCaptureSamples(Recorder, Samples, NumSamples)

' Stop recording
alcCaptureStop(Recorder)

' Output
alBufferData(Buffer, AL_FORMAT_MONO16, Samples, NumSamples*2, 44100)
alSourcei(Source, AL_BUFFER, Buffer)

alSourcePlay(Source)
Repeat
	alGetSourcei(Source, AL_SOURCE_STATE, Varptr(State))
Until State <> AL_PLAYING

Catch Exception : Object
	WriteStdout("~nError:~n " + Exception.ToString())
End Try

alSourceStop(Source)
alDeleteSources(1, Varptr(Source))
alDeleteBuffers(1, Varptr(Buffer))
alcMakeContextCurrent(Null)
alcDestroyContext(Context)
alcCloseDevice(AudioDevice)
alcCaptureCloseDevice(Recorder)

WriteStdout("~nready~n")
End

Function EnumDevices:String[](Device:Int)
	Local Devices : Byte Ptr, ..
	      List    : String[]

	Devices = alcGetString(Null, Device)
	If Not Devices Then Return Null

	While Devices[0]
		List = List[..List.Length + 1]
		List[List.Length - 1] = String.FromCString(Devices)
		Devices :+ List[List.Length - 1].Length + 1
	Wend

	Return List
End Function


http://vertex.dreamfall.at/openal/openal103.zip
(Does only work on Windows and maybe Linux)

Thanks a lot Vertex ! :-)
You saved me ! ;-)

I am trying to record sounds for a project I am working on right now and this information is very useful. However, I'm unclear on why Vignoli's code was behaving odd, and I don't really want to use Vertex's special framework because I would like to run this on either Windows or Mac.

Could someone explain why that first example was giving weird results? Vertex appears to be using alSourcePlay for playing the recorded sound, but I don't understand how that works.

ADDITION: gah now my ears are ringing and I have a headache because I screwed with the audio format and had the volume all the way up