Platforms to show: All Mac Windows Linux Cross-Platform

/AVFoundation/AVAudioEngine/Player with AudioUnit for Level Meter


Required plugins for this example: MBS MacBase Plugin, MBS Main Plugin, MBS AVFoundation Plugin

You find this example project in your Plugins Download as a Xojo project file within the examples folder: /AVFoundation/AVAudioEngine/Player with AudioUnit for Level Meter

This example is the version from Mon, 20th Sep 2015.

Project "Player with AudioUnit for Level Meter.xojo_binary_project"
Class App Inherits Application
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
End Class
Class Window1 Inherits Window
Control LoadButton Inherits PushButton
ControlInstance LoadButton Inherits PushButton
EventHandler Sub Action() dim f as FolderItem = GetOpenFolderItem("") if f = nil then Return dim error as NSErrorMBS dim a as new AVAudioFileMBS(f, error) if error <> nil then MsgBox error.LocalizedDescription return end if NoEvents = true dim ff as AVAudioFormatMBS = a.fileFormat dim d as Double = a.Length/a.fileFormat.sampleRate FileInfo.Text = f.DisplayName+": "+str(ff.sampleRate)+"Hz, "+str(ff.channelCount)+" channels, "+str(d, "0.00")+" seconds" self.fileFormat = ff self.AudioFile = a self.File = f PositionSlider.Value = 0 engine.reset engine.connect(player, audioUnit, nil) engine.connect(audioUnit, engine.mainMixerNode, nil) player.scheduleFile(a, nil) StartEngine if not player.Playing then player.play end if Finally NoEvents = false End EventHandler
End Control
Control FileInfo Inherits Label
ControlInstance FileInfo Inherits Label
End Control
Control PlayButton Inherits PushButton
ControlInstance PlayButton Inherits PushButton
EventHandler Sub Action() if player.Playing then player.pause else player.play end if End EventHandler
End Control
Control PlayStatus Inherits Label
ControlInstance PlayStatus Inherits Label
End Control
Control Timer1 Inherits Timer
ControlInstance Timer1 Inherits Timer
EventHandler Sub Action() NoEvents = true dim lines() as string if player.Playing then lines.Append "playing" else lines.Append "paused" end if if audiofile <> nil and fileFormat <> nil then lines.Append str(audiofile.FramePosition / fileFormat.sampleRate)+" seconds" end if PlayStatus.Text = Join(lines, ", ") if audiofile <> nil then dim nodetime as AVAudioTimeMBS = self.player.lastRenderTime if nodetime <> nil then dim playerTime as AVAudioTimeMBS = self.player.playerTimeForNodeTime(nodetime) if playerTime <> nil then PositionSlider.Value = 1000.0 * (StartPos + playerTime.sampleTime) / audiofile.Length end if end if end if LabelVolume.Text = str(player.volume, "-0.0%") Finally NoEvents = False End EventHandler
End Control
Control VolumeSlider Inherits Slider
ControlInstance VolumeSlider Inherits Slider
EventHandler Sub ValueChanged() if NoEvents then Return player.volume = me.Value / 100.0 End EventHandler
End Control
Control Label1 Inherits Label
ControlInstance Label1 Inherits Label
End Control
Control PositionSlider Inherits Slider
ControlInstance PositionSlider Inherits Slider
EventHandler Sub ValueChanged() if NoEvents then Return // restart at new position dim playing as Boolean = player.Playing player.stop dim l as Int64 = audiofile.Length dim x as Int64 = (me.Value * l) / 1000.0 dim r as int64 = audiofile.Length - x player.scheduleSegment(audiofile, nil, x, r) StartPos = x if Playing then player.play end if End EventHandler
End Control
Control LabelVolume Inherits Label
ControlInstance LabelVolume Inherits Label
End Control
Control LevelChannel0 Inherits ProgressBar
ControlInstance LevelChannel0 Inherits ProgressBar
End Control
Control LevelChannel1 Inherits ProgressBar
ControlInstance LevelChannel1 Inherits ProgressBar
End Control
Control LabelPan Inherits Label
ControlInstance LabelPan Inherits Label
End Control
EventHandler Sub Close() player.removeTapOnBus 0 End EventHandler
EventHandler Sub Open() NoEvents = true // Needs OS X 10.10 or newer Engine = new AVAudioEngineMBS player = new myAVAudioPlayerNodeMBS audioUnit = new AVAudioUnitTimePitchMBS Engine.attachNode player engine.attachNode audioUnit AddHandler audioUnit.LevelMonitor, WeakAddressOf LevelMonitorHandler audioUnit.installLevelMonitor 20 const kTimePitchParam_Pitch = 1 const kAudioUnitScope_Global = 0 const kAudioUnitProperty_SampleRate = 2 #if false then // try parameter dim pitchValue as single = audioUnit.GetParameter(kTimePitchParam_Pitch, kAudioUnitScope_Global, 0) audioUnit.SetParameter(kTimePitchParam_Pitch, kAudioUnitScope_Global, 0, 100) dim pitchValue2 as single = audioUnit.GetParameter(kTimePitchParam_Pitch, kAudioUnitScope_Global, 0) #endif #if false then // try property // 8 bytes and Writeable dim WriteAble as Boolean dim Size as integer = audioUnit.GetPropertyInfo(kAudioUnitProperty_SampleRate, kAudioUnitScope_Global, 0, WriteAble) // query it dim m as MemoryBlock = audioUnit.GetProperty(kAudioUnitProperty_SampleRate, kAudioUnitScope_Global, 0) dim SampleRate as Double = m.DoubleValue(0) #endif Finally NoEvents = false End EventHandler
Sub LevelMonitorHandler(v as AVAudioUnitTimeEffectMBS , Level0 as Double, Level1 as Double, Level2 as Double, Level3 as Double, Level4 as Double, Level5 as Double, Level6 as Double, Level7 as Double, tag as Variant) LevelChannel0.Value = level0 * 100.0 LevelChannel1.Value = level1 * 100.0 System.DebugLog str(level0, "0.00")+" "+str(Microseconds, "0") #pragma Unused v #pragma Unused Level2 #pragma Unused Level3 #pragma Unused Level4 #pragma Unused Level5 #pragma Unused Level6 #pragma Unused Level7 #pragma Unused tag End Sub
Sub OutputLevel(m as AVAudioNodeMBS, bus as integer, frameLength as Integer, Level0 as Double, Level1 as Double, Level2 as Double, Level3 as Double, Level4 as Double, Level5 as Double, Level6 as Double, Level7 as Double, tag as variant) LevelChannel0.Value = level0 * 100.0 LevelChannel1.Value = level1 * 100.0 #pragma Unused m #pragma Unused bus #pragma Unused frameLength #pragma Unused Level2 #pragma Unused Level3 #pragma Unused Level4 #pragma Unused Level5 #pragma Unused Level6 #pragma Unused Level7 #pragma Unused tag End Sub
Sub StartEngine() if not engine.running then dim e as NSErrorMBS if engine.startAndReturnError(e) then // ok else MsgBox "Failed: "+e.localizedDescription end if end if End Sub
Function StereoFormat() As AVAudioFormatMBS // stereo format with standard layout tag dim layout as new AVAudioChannelLayoutMBS(QTAudioChannelLayoutMBS.kAudioChannelLayoutTag_Stereo) dim pf as new AVAudioFormatMBS(44100, layout) Return pf End Function
Function StereoLeftFormat() As AVAudioFormatMBS // stereo format, left channel only dim qlayout as new QTAudioChannelLayoutMBS dim d1 as new QTAudioChannelDescriptionMBS dim d2 as new QTAudioChannelDescriptionMBS d1.ChannelFlags = QTAudioChannelDescriptionMBS.kAudioChannelFlags_AllOff d1.ChannelLabel = QTAudioChannelDescriptionMBS.kAudioChannelLabel_Discrete_3 d2.ChannelFlags = QTAudioChannelDescriptionMBS.kAudioChannelFlags_AllOff d2.ChannelLabel = QTAudioChannelDescriptionMBS.kAudioChannelLabel_Unused qlayout.ChannelLayoutTag = QTAudioChannelLayoutMBS.kAudioChannelLayoutTag_UseChannelDescriptions qlayout.NumberChannelDescriptions=2 qlayout.ChannelDescriptions(0)=d1 qlayout.ChannelDescriptions(1)=d2 dim layout as new AVAudioChannelLayoutMBS(qlayout) dim pf as new AVAudioFormatMBS(44100, layout) Return pf End Function
Function StereoRightFormat() As AVAudioFormatMBS // stereo format, left channel only dim qlayout as new QTAudioChannelLayoutMBS dim d1 as new QTAudioChannelDescriptionMBS dim d2 as new QTAudioChannelDescriptionMBS d1.ChannelFlags = QTAudioChannelDescriptionMBS.kAudioChannelFlags_AllOff d1.ChannelLabel = QTAudioChannelDescriptionMBS.kAudioChannelLabel_Unused d2.ChannelFlags = QTAudioChannelDescriptionMBS.kAudioChannelFlags_AllOff d2.ChannelLabel = QTAudioChannelDescriptionMBS.kAudioChannelLabel_Right qlayout.ChannelLayoutTag = QTAudioChannelLayoutMBS.kAudioChannelLayoutTag_UseChannelDescriptions qlayout.NumberChannelDescriptions=2 qlayout.ChannelDescriptions(0)=d1 qlayout.ChannelDescriptions(1)=d2 dim layout as new AVAudioChannelLayoutMBS(qlayout) dim pf as new AVAudioFormatMBS(44100, layout) Return pf End Function
Property Engine As AVAudioEngineMBS
Property NoEvents As Boolean
Property StartPos As int64
Property audioUnit As AVAudioUnitTimePitchMBS
Property audiofile As AVAudioFileMBS
Property file As FolderItem
Property fileFormat As AVAudioFormatMBS
Property player As AVAudioPlayerNodeMBS
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
Class MyAVAudioPlayerNodeMBS Inherits AVAudioPlayerNodeMBS
EventHandler Sub scheduleFileCompleted(file as AVAudioFileMBS, time as AVAudioTimeMBS, tag as Variant) MsgBox "Playing finished." #pragma Unused file #pragma Unused time #pragma Unused tag End EventHandler
End Class
End Project

See also:

The items on this page are in the following plugins: MBS AVFoundation Plugin.


The biggest plugin in space...