Platforms to show: All Mac Windows Linux Cross-Platform

/Tools/Whisper


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.


The biggest plugin in space...