Platforms to show: All Mac Windows Linux Cross-Platform
/Audio/PortAudio Record and Play
Required plugins for this example: MBS Audio Plugin, MBS DataTypes Plugin
You find this example project in your Plugins Download as a Xojo project file within the examples folder: /Audio/PortAudio Record and Play
This example is the version from Tue, 28th Oct 2019.
Project "PortAudio Record and Play.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
End Class
Class MainWindow Inherits Window
Control InfoLabel Inherits Label
ControlInstance InfoLabel Inherits Label
End Control
Control RecordButton Inherits PushButton
ControlInstance RecordButton Inherits PushButton
EventHandler Sub Action()
StartRecording
End EventHandler
End Control
Control PlayButton Inherits PushButton
ControlInstance PlayButton Inherits PushButton
EventHandler Sub Action()
Play
End EventHandler
End Control
Control SaveButton Inherits PushButton
ControlInstance SaveButton Inherits PushButton
EventHandler Sub Action()
save
End EventHandler
End Control
Control Output Inherits Canvas
ControlInstance Output Inherits Canvas
EventHandler Sub Paint(g As Graphics, areas() As REALbasic.Rect)
#Pragma unused areas
If out <> Nil Then
g.DrawPicture out, 0, 0, g.Width, g.Height, 0, 0, out.Width, out.Height
End If
End EventHandler
End Control
Control StopButton Inherits PushButton
ControlInstance StopButton Inherits PushButton
EventHandler Sub Action()
StopRecording
End EventHandler
End Control
Control RecorderTimer Inherits Timer
ControlInstance RecorderTimer Inherits Timer
EventHandler Sub Action()
// we ask for samples in the buffer
Dim l As Integer = Recorder.ReadFrames(temp, temp.Size)
If l > 0 Then
RecordedData.Add temp, l*4 // 4 bytes per sample
// process the l frames we got
ProcessFrames temp, l
end if
End EventHandler
End Control
EventHandler Sub Open()
po = New PortAudioMBS
End EventHandler
Sub Play()
If RecordedData = Nil Then Return // no data
// get samples
Dim audioBuffer As MemoryBlock = RecordedData.CopyMemory
Dim c As New PortAudioStreamBufferedMBS
Dim e As Integer = c.OpenDefaultStream(1, SampleRate)
System.DebugLog "OpenDefaultStream: "+Str(e)
If e = 0 Then
Else
MsgBox "Host Error: "+Str(c.HostError)
Return
End If
If Not c.AddFloatAudio(audioBuffer) Then
MsgBox "Failed to play audio!"
Return
Else
System.DebugLog "AddFloatAudio ok"
e=c.Start
System.DebugLog "Start: "+Str(e)
e=c.IsStreamActive
System.DebugLog "Active: "+Str(e)
PlayStream = c
End If
End Sub
Sub ProcessFrames(m as MemoryBlock, l as integer)
// show In canvas
dim c as integer = l-1
// just find min and max and display it here
Dim b As Double = m.SingleValue(0)
Dim mi As Double = b
Dim ma As Double = b
For i As Integer = 0 To c
b = m.SingleValue(4*i)
If b > ma Then
ma = b
End If
If b < mi Then
mi = b
End If
next
// scale so we see more
'ma = ma * 2.0
'mi = mi * 2.0
ma = abs(ma)
mi = abs(mi)
// draw to the screen directly
Dim w As Integer = Output.width
Dim h As Integer = Output.Height
Dim h2 As Double = h/2
If out = Nil Or out.Width <> w Or out.Height <> h Then
out = New Picture(w, h, 32)
End If
Dim g As Graphics = out.Graphics
g.ForeColor=&cFFFFFF
g.DrawLine index, 0, index, h
g.ForeColor=&cFF0000
g.DrawLine index, h2, index, h2 - ma * h2
g.ForeColor=&c00FF00
g.DrawLine index, h2, index, h2 + mi * h2
Output.Invalidate
// move to the next line
index = index + 1
If index = w Then
index = 0
end if
End Sub
Sub Save()
// save as WAV
// for more options, please use SoundFileMBS class
Dim size As Integer=0
Dim f As FolderItem = GetSaveFolderItem(FileTypes1.AudioWav,"audio.wav")
If f <> Nil Then
Dim b As BinaryStream = f.CreateBinaryFile(FileTypes1.AudioWav)
If b = Nil Then
MsgBox "Failed to create file " + f.NativePath
Else
Dim buf As MemoryBlock = RecordedData.CopyMemory
Dim samples As Integer = buf.size \ 4
// convert to 16-bit data
Dim x As New MemoryBlock(samples*2)
x.LittleEndian=True
Dim p As Integer = 0
Dim q As Integer = 0
Dim c As Integer = samples-1
For i As Integer = 0 To c
x.Short(q) = buf.SingleValue(p) * 32767.0
p = p + 4
q = q + 2
Next
size = size + x.size
b.LittleEndian=True
b.Write "RIFF"
b.WriteInt32 6+4+16+4+Size // size of file
b.Write "WAVE"
b.Write "fmt "
b.WriteInt32 16 // size of following data
b.WriteInt16 1 // format, uncompressed
b.WriteInt16 1 // 1 Channel
b.WriteInt32 SampleRate // Samples per Second
b.WriteInt32 SampleRate * 2 // Bytes per Second
b.WriteInt16 2 // Block align, Size of Sample in Bytes
b.WriteInt16 16 // bits per sample
b.Write "data"
b.WriteInt32 Size
b.Write x
b.Close
End If
End If
End Sub
Sub StartRecording()
SampleRate = 48000 // Native Frequency of my Macbook
Dim defaultInputDevice As Integer = po.DefaultInputDeviceID
Dim deviceInfo As PortAudioDeviceInfoMBS = po.DeviceInfo(defaultInputDevice)
If deviceInfo <> Nil Then
SampleRate = deviceInfo.DefaultSampleRate
System.DebugLog "SampleRate: "+Str(SampleRate)
End If
Recorder = New PortAudioStreamRecorderMBS(1024 * 1024)
// read 1 second maximum per timer loop
temp = New MemoryBlock(4 * SampleRate)
RecordedData = New StringHandleMBS
If Recorder.OpenDefaultStream(1, SampleRate) = 0 Then
If Recorder.Start = 0 Then
RecorderTimer.Mode = RecorderTimer.ModeMultiple
PlayButton.Enabled = false
StopButton.Enabled = True
Else
MsgBox "Failed to start recording."
End If
Else
MsgBox "Failed to initialize."
End If
End Sub
Sub StopRecording()
RecorderTimer.Mode = timer.ModeOff
If Recorder <> Nil Then
Call Recorder.Close
Recorder = Nil
End If
temp = Nil
StopButton.Enabled = False
RecordButton.Enabled = True
PlayButton.Enabled = True
SaveButton.Enabled = True
End Sub
Property PlayStream As PortAudioStreamBufferedMBS
Property RecordedData As StringHandleMBS
Property Recorder As PortAudioStreamRecorderMBS
Property SampleRate As Integer = 44100
Property index As Integer
Property out As Picture
Property po As PortAudioMBS
Property temp As MemoryBlock
End Class
MenuBar MainMenuBar
MenuItem FileMenu = "&File"
MenuItem FileQuit = "#App.kFileQuit"
MenuItem EditMenu = "&Edit"
MenuItem EditUndo = "&Undo"
MenuItem EditSeparator1 = "-"
MenuItem EditCut = "Cu&t"
MenuItem EditCopy = "&Copy"
MenuItem EditPaste = "&Paste"
MenuItem EditClear = "#App.kEditClear"
MenuItem EditSeparator2 = "-"
MenuItem EditSelectAll = "Select &All"
End MenuBar
ExternalFile info
End ExternalFile
FileTypes1
Filetype audio/wav
End FileTypes1
End Project
See also:
The items on this page are in the following plugins: MBS Audio Plugin.