Platforms to show: All Mac Windows Linux Cross-Platform
Required plugins for this example: MBS Tools Plugin
Last modified Mon, 1st Jun 2025.
You find this example project in your MBS Xojo Plugin download as a Xojo project file within the examples folder: /Tools/Whisper
Download this example: Whisper.zip
Project "Whisper.xojo_binary_project"
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"
MenuItem WindowMenu = "Window"
MenuItem HelpMenu = "&Help"
End MenuBar
Class App Inherits DesktopApplication
Const kEditClear = "&Delete"
Const kFileQuit = "&Quit"
Const kFileQuitShortcut = ""
EventHandler Sub Opening()
#If True Then
// run directly
run
#Else
// run in a thread
Dim t As New MyThread
WorkThread = t
t.Start
#EndIf
End EventHandler
Sub Log(s as string)
System.DebugLog s
If Thread.Current = Nil Then
// main thread
MessageBox s
End If
End Sub
Sub run()
// 1. load the dylib for the whisper version you have.
Var appFile As FolderItem = app.ExecutableFile
Var macOSFolder As FolderItem = appfile.Parent
Var appContents As FolderItem = macOSFolder.parent
Var Frameworks As FolderItem = appContents.Child("Frameworks")
Var LibFile As FolderItem = Frameworks.Child("libwhisper.1.7.4.dylib")
If Not LibFile.Exists Then
Log LibFile.name + " file missing?"
Quit
ElseIf WhisperMBS.LoadLibrary(LibFile) Then
'Log "Okay"
Else
Log "Failed to load library: "+WhisperMBS.LoadErrorMessage
Quit
End If
// 2. Load sndfile library
// https://www.monkeybreadsoftware.de/xojo/download/plugin/Libs/
LibFile = Frameworks.Child("libsndfile.dylib")
If SoundFileMBS.LoadLibrary(LibFile) Then
'Log "Okay"
Else
Log "Failed to load library: "+SoundFileMBS.LoadErrorMessage
Quit
End If
// 3. Load audio file.
// Please change path!
Var f As FolderItem = GetFolderItem("ep306_16kHz_16bit.wav")
// SoundFileMBS is in our Tools plugin
Var s As SoundFileMBS = SoundFileMBS.Open(f)
If s = Nil Then
Log "Failed to open sound."
Quit
End If
Var info As SoundFileInfoMBS = s.Info
System.DebugLog Str(info.Frames)+" frames, "+Str(info.SampleRate)+" Hz."
Var samples As New MemoryBlock(info.Frames * 4)
Var SamplesCount As Integer = s.ReadSingleFrames(samples, info.Frames)
// 4. If needed, convert the audio to 16000 Hz as that is what our
If info.SampleRate <> 16000 Then
// we need 16 Khz
Const LibPath = "/opt/homebrew/Cellar/speexdsp/1.2.1/lib/libspeexdsp.1.dylib"
// SpeexResamplerState *speex_resampler_init(spx_uint32_t nb_channels, spx_uint32_t in_rate, spx_uint32_t out_rate, int quality, int *err);
Soft Declare Function speex_resampler_init Lib LibPath (Channels As UInt32, InRate As UInt32, OutRate As UInt32, Quality As Int32, ByRef error As Int32) As Ptr
Var inputRate As Integer = info.SampleRate
Var outputRate As Integer = 16000
Var InputLength As UInt32 = SamplesCount
Var OutputLength As UInt32 = InputLength * outputRate / inputRate
Var output As New MemoryBlock(OutputLength * 4)
Const SPEEX_RESAMPLER_QUALITY_BEST = 10
Var error As Int32
Var resampler As Ptr = speex_resampler_init(1, inputRate, outputRate, SPEEX_RESAMPLER_QUALITY_BEST, error)
If error <> 0 Then
Log "Speex resampler init failed"
Break
Return
End If
// int speex_resampler_process_float(SpeexResamplerState *st, spx_uint32_t channel_index, Const float *In, spx_uint32_t *in_len, float *out, spx_uint32_t *out_len);
Soft Declare Function speex_resampler_process_float Lib LibPath (resampler As Ptr, ChannelIndex As UInt32, Input As Ptr, ByRef InLen As UInt32, Output As Ptr, ByRef OutLen As UInt32) As Int32
Var SamplesPtr As Ptr = samples
Var outputPtr As Ptr = output
Call speex_resampler_process_float(resampler, 0, SamplesPtr, InputLength, outputPtr, OutputLength)
Soft Declare Sub speex_resampler_destroy Lib LibPath (resampler As Ptr)
// void speex_resampler_destroy(SpeexResamplerState *st);
speex_resampler_destroy(resampler)
// now use resampled data
samples = output
SamplesCount = OutputLength
end if
// 5. Use Whisper to convert audio to text
// now convert
System.DebugLog WhisperMBS.LangMaxID.ToString+" languages"
Var Resources As FolderItem = appContents.Child("Resources")
Var ModelFile As FolderItem = Resources.Child("ggml-base.en.bin") // you may need to change this to point to your file
Var cparams As New WhisperContextParamsMBS
Var wparams As New WhisperFullParamsMBS(WhisperFullParamsMBS.SamplingStrategyGreedy)
wparams.TdrzEnable = True
Var context As New WhisperContext(ModelFile, cparams)
Var samplesPtr As Ptr = samples
Var e As Integer = context.full(wparams, samplesPtr, SamplesCount)
If e <> 0 Then
Log "Failed to process audio. Error: "+e.ToString
Quit
Else
Log "Error: "+e.ToString
End If
Var segments As Integer = context.FullSegments
Var lines() As String
lines.add "Text: "
For SegmentIndex As Integer = 0 To Segments-1
Var tokenCount As Integer = context.FullTokens(SegmentIndex)
Var tokens() As WhisperTokenMBS = context.FullGetTokens(SegmentIndex)
Var tokenDatas() As WhisperTokenDataMBS = context.FullGetTokenDatas(SegmentIndex)
Var tokenTexts() As String = context.FullGetTokenTexts(SegmentIndex)
Var speakerHasTurned As Boolean = context.FullGetSegmentSpeakerTurnNext(SegmentIndex)
System.DebugLog "speakerHasTurned: "+speakerHasTurned.ToString
Var Text As String = context.FullSegmentText(SegmentIndex)
For TokenIndex As Integer = 0 To tokenCount -1
Var token As WhisperTokenMBS = context.FullGetToken(SegmentIndex, TokenIndex)
Var tokenData As WhisperTokenDataMBS = context.FullGetTokenData(SegmentIndex, TokenIndex)
objects.Add token
objects.Add tokenData
Next
System.DebugLog Text
lines.add Text
Next
Log "Finished: "+Join(lines, EndOfLine)
End Sub
Property objects() As Variant
End Class
Sign
End Sign
Class WhisperContext Inherits WhisperContextMBS
EventHandler Function Abort() As Boolean
System.DebugLog CurrentMethodName
Return False
End EventHandler
EventHandler Function EncoderBegin(State as WhisperStateMBS) As Boolean
System.DebugLog CurrentMethodName
End EventHandler
EventHandler Sub Log(Level as Integer, Text as String)
System.DebugLog CurrentMethodName+" "+Text
End EventHandler
EventHandler Sub NewSegment(State as WhisperStateMBS, n_new as Integer)
System.DebugLog CurrentMethodName
End EventHandler
EventHandler Sub Progress(State as WhisperStateMBS, progress as Integer)
System.DebugLog CurrentMethodName+" "+progress.ToString
End EventHandler
End Class
Class MyThread Inherits Thread
EventHandler Sub Run()
app.run
End EventHandler
End Class
End Project
Download this example: Whisper.zip
The items on this page are in the following plugins: MBS Tools Plugin.