-*.o
-*.a
-.cache/
-.coreml/
-.test/
-.vs/
-.vscode/
-.DS_Store
-
-build/
-build-em/
-build-debug/
-build-release/
-build-static/
-build-cublas/
-build-no-accel/
-build-sanitize-addr/
-build-sanitize-thread/
-
-/main
-/stream
-/command
-/talk
-/talk-llama
-/bench
-/quantize
-
-arm_neon.h
-sync.sh
-libwhisper.a
-libwhisper.so
-compile_commands.json
-
-examples/arm_neon.h
-examples/whisper.objc/whisper.objc.xcodeproj/xcshareddata
-examples/whisper.objc/whisper.objc.xcodeproj/xcuserdata/
-examples/whisper.objc/whisper.objc.xcodeproj/project.xcworkspace/xcuserdata
-
-extra/bench-gg.txt
-
-models/*.mlmodel
-models/*.mlmodelc
-models/*.mlpackage
+*.o\r
+*.a\r
+.cache/\r
+.coreml/\r
+.test/\r
+.vs/\r
+.vscode/\r
+.DS_Store\r
+\r
+build/\r
+build-em/\r
+build-debug/\r
+build-release/\r
+build-static/\r
+build-cublas/\r
+build-no-accel/\r
+build-sanitize-addr/\r
+build-sanitize-thread/\r
+\r
+/main\r
+/stream\r
+/command\r
+/talk\r
+/talk-llama\r
+/bench\r
+/quantize\r
+\r
+arm_neon.h\r
+sync.sh\r
+libwhisper.a\r
+libwhisper.so\r
+compile_commands.json\r
+\r
+examples/arm_neon.h\r
+examples/whisper.objc/whisper.objc.xcodeproj/xcshareddata\r
+examples/whisper.objc/whisper.objc.xcodeproj/xcuserdata/\r
+examples/whisper.objc/whisper.objc.xcodeproj/project.xcworkspace/xcuserdata\r
+\r
+extra/bench-gg.txt\r
+\r
+models/*.mlmodel\r
+models/*.mlmodelc\r
+models/*.mlpackage\r
+bindings/java/.gradle/\r
+bindings/java/.idea/\r
+.idea/\r
- [x] Mac OS (Intel and Arm)
- [x] [iOS](examples/whisper.objc)
- [x] [Android](examples/whisper.android)
+- [x] [Java](bindings/java/README.md)
- [x] Linux / [FreeBSD](https://github.com/ggerganov/whisper.cpp/issues/56#issuecomment-1350920264)
- [x] [WebAssembly](examples/whisper.wasm)
- [x] Windows ([MSVC](https://github.com/ggerganov/whisper.cpp/blob/master/.github/workflows/build.yml#L117-L144) and [MinGW](https://github.com/ggerganov/whisper.cpp/issues/168)]
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<project version="4">\r
+ <component name="Palette2">\r
+ <group name="Swing">\r
+ <item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />\r
+ </item>\r
+ <item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />\r
+ </item>\r
+ <item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />\r
+ </item>\r
+ <item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">\r
+ <default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />\r
+ </item>\r
+ <item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />\r
+ <initial-values>\r
+ <property name="text" value="Button" />\r
+ </initial-values>\r
+ </item>\r
+ <item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />\r
+ <initial-values>\r
+ <property name="text" value="RadioButton" />\r
+ </initial-values>\r
+ </item>\r
+ <item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />\r
+ <initial-values>\r
+ <property name="text" value="CheckBox" />\r
+ </initial-values>\r
+ </item>\r
+ <item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />\r
+ <initial-values>\r
+ <property name="text" value="Label" />\r
+ </initial-values>\r
+ </item>\r
+ <item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">\r
+ <preferred-size width="150" height="-1" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">\r
+ <preferred-size width="150" height="-1" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">\r
+ <preferred-size width="150" height="-1" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">\r
+ <preferred-size width="150" height="50" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">\r
+ <preferred-size width="150" height="50" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">\r
+ <preferred-size width="150" height="50" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />\r
+ </item>\r
+ <item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">\r
+ <preferred-size width="150" height="50" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">\r
+ <preferred-size width="150" height="50" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">\r
+ <preferred-size width="150" height="50" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">\r
+ <preferred-size width="200" height="200" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">\r
+ <preferred-size width="200" height="200" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />\r
+ </item>\r
+ <item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />\r
+ </item>\r
+ <item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />\r
+ </item>\r
+ <item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />\r
+ </item>\r
+ <item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">\r
+ <preferred-size width="-1" height="20" />\r
+ </default-constraints>\r
+ </item>\r
+ <item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">\r
+ <default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />\r
+ </item>\r
+ <item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">\r
+ <default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />\r
+ </item>\r
+ </group>\r
+ </component>\r
+</project>
\ No newline at end of file
--- /dev/null
+cmake_minimum_required(VERSION 3.10)\r
+\r
+project(whisper_java VERSION 1.4.2)\r
+\r
+# Set the target name and source file/s\r
+set(TARGET_NAME whisper_java)\r
+set(SOURCES src/main/cpp/whisper_java.cpp)\r
+\r
+# include <whisper.h>\r
+include_directories(../../)\r
+\r
+# Set the output directory for the DLL/shared library based on the platform as required by JNA\r
+if(WIN32)\r
+ set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/resources/main/win32-x86-64)\r
+elseif(UNIX AND NOT APPLE)\r
+ set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/resources/main/linux-x86-64)\r
+elseif(APPLE)\r
+ set(OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/generated/resources/main/macos-x86-64)\r
+endif()\r
+\r
+set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${OUTPUT_DIR})\r
+set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${OUTPUT_DIR})\r
+\r
+# Create the whisper_java library\r
+add_library(${TARGET_NAME} SHARED ${SOURCES})\r
+\r
+# Link against ../../build/Release/whisper.dll (or so/dynlib)\r
+target_link_directories(${TARGET_NAME} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/../../../build/${CMAKE_BUILD_TYPE})\r
+target_link_libraries(${TARGET_NAME} PRIVATE whisper)\r
+\r
+# Set the appropriate compiler flags for Windows, Linux, and macOS\r
+if(WIN32)\r
+ target_compile_options(${TARGET_NAME} PRIVATE /W4 /D_CRT_SECURE_NO_WARNINGS)\r
+elseif(UNIX AND NOT APPLE)\r
+ target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra)\r
+elseif(APPLE)\r
+ target_compile_options(${TARGET_NAME} PRIVATE -Wall -Wextra)\r
+endif()\r
+\r
+target_compile_definitions(${TARGET_NAME} PRIVATE WHISPER_SHARED)\r
+# add_definitions(-DWHISPER_SHARED)\r
+\r
+# Force CMake to save the libs to build/generated/resources/main/${os}-${arch} as required by JNA\r
+foreach(OUTPUTCONFIG ${CMAKE_CONFIGURATION_TYPES})\r
+ string(TOUPPER ${OUTPUTCONFIG} OUTPUTCONFIG)\r
+ set_target_properties(${TARGET_NAME} PROPERTIES\r
+ RUNTIME_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${OUTPUT_DIR}\r
+ LIBRARY_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${OUTPUT_DIR}\r
+ ARCHIVE_OUTPUT_DIRECTORY_${OUTPUTCONFIG} ${OUTPUT_DIR})\r
+endforeach(OUTPUTCONFIG CMAKE_CONFIGURATION_TYPES)\r
--- /dev/null
+# Java JNI bindings for Whisper
+
+This package provides Java JNI bindings for whisper.cpp. They have been tested on:
+
+ * <strike>Darwin (OS X) 12.6 on x64_64</strike>
+ * Ubuntu on x86_64
+ * Windows on x86_64
+
+The "low level" bindings are in `WhisperCppJnaLibrary` and `WhisperJavaJnaLibrary` which caches `whisper_full_params` and `whisper_context` in `whisper_java.cpp`.
+
+There are a lot of classes in the `callbacks`, `ggml`, `model` and `params` directories but most of them have not been tested.
+
+The most simple usage is as follows:
+
+```java
+import io.github.ggerganov.whispercpp.WhisperCpp;
+
+public class Example {
+
+ public static void main(String[] args) {
+ String modelpath;
+ WhisperCpp whisper = new WhisperCpp();
+ // By default, models are loaded from ~/.cache/whisper/ and are usually named "ggml-${name}.bin"
+ // or you can provide the absolute path to the model file.
+ whisper.initContext("base.en");
+
+ long context = whisper.initContext(modelpath);
+ try {
+ whisper.fullTranscribe(context, samples);
+
+ int segmentCount = whisper.getTextSegmentCount(context);
+ for (int i = 0; i < segmentCount; i++) {
+ String text = whisper.getTextSegment(context, i);
+ System.out.println(segment.getText());
+ }
+ } finally {
+ whisper.freeContext(context);
+ }
+ }
+}
+```
+
+## Building & Testing
+
+In order to build, you need to have the JDK 8 or higher installed. Run the tests with:
+
+```bash
+git clone https://github.com/ggerganov/whisper.cpp.git
+cd whisper.cpp/bindings/java
+
+mkdir build
+pushd build
+cmake ..
+cmake --build .
+popd
+
+./gradlew build
+```
+
+## License
+
+The license for the Go bindings is the same as the license for the rest of the whisper.cpp project, which is the MIT License. See the `LICENSE` file for more details.
+
--- /dev/null
+plugins {\r
+ id 'java'\r
+ id 'java-library'\r
+ id 'maven-publish'\r
+}\r
+\r
+archivesBaseName = 'whispercpp'\r
+group = 'io.github.ggerganov'\r
+version = '1.4.0'\r
+\r
+sourceCompatibility = 1.8\r
+targetCompatibility = 1.8\r
+\r
+sourceSets {\r
+ main {\r
+ resources {\r
+ srcDirs = ['src/main/resources', 'build/generated/resources/main']\r
+ }\r
+ }\r
+ test {\r
+ runtimeClasspath += files('build/generated/resources/main')\r
+ }\r
+}\r
+\r
+tasks.register('copyLibwhisperSo', Copy) {\r
+ from '../../build'\r
+ include 'libwhisper.so'\r
+ into 'build/generated/resources/main/linux-x86-64'\r
+}\r
+\r
+tasks.register('copyWhisperDll', Copy) {\r
+ from '../../build/Release'\r
+ include 'whisper.dll'\r
+ into 'build/generated/resources/main/windows-x86-64'\r
+}\r
+\r
+tasks.build.dependsOn copyLibwhisperSo, copyWhisperDll\r
+\r
+test {\r
+ systemProperty 'jna.library.path', project.file('build/generated/resources/main').absolutePath\r
+}\r
+\r
+java {\r
+ withSourcesJar()\r
+ withJavadocJar()\r
+}\r
+\r
+jar {\r
+ exclude '**/whisper_java.exp', '**/whisper_java.lib'\r
+}\r
+\r
+javadoc {\r
+ options.addStringOption('Xdoclint:none', '-quiet')\r
+}\r
+\r
+tasks.withType(Test) {\r
+ useJUnitPlatform()\r
+}\r
+\r
+dependencies {\r
+ implementation "net.java.dev.jna:jna:5.13.0"\r
+ testImplementation "org.junit.jupiter:junit-jupiter:5.9.2"\r
+ testImplementation "org.assertj:assertj-core:3.24.2"\r
+}\r
+\r
+repositories {\r
+ mavenCentral()\r
+}\r
+\r
+publishing {\r
+ publications {\r
+ mavenJava(MavenPublication) {\r
+ artifactId = 'whispercpp'\r
+ from components.java\r
+ pom {\r
+ name = 'whispercpp'\r
+ description = "Java JNA bindings for OpenAI's Whisper model, implemented in C/C++"\r
+ url = 'https://github.com/ggerganov/whisper.cpp'\r
+ licenses {\r
+ license {\r
+ name = 'MIT licence'\r
+ url = 'https://raw.githubusercontent.com/ggerganov/whisper.cpp/master/LICENSE'\r
+ }\r
+ }\r
+ developers {\r
+ developer {\r
+ id = 'ggerganov'\r
+ name = 'Georgi Gerganov'\r
+ email = 'ggerganov@gmail.com'\r
+ }\r
+ developer {\r
+ id = 'nalbion'\r
+ name = 'Nicholas Albion'\r
+ email = 'nalbion@yahoo.com'\r
+ }\r
+ }\r
+ scm {\r
+ connection = 'scm:git:git://github.com/ggerganov/whisper.cpp.git'\r
+ url = 'https://github.com/ggerganov/whisper.cpp'\r
+ }\r
+ }\r
+ }\r
+ }\r
+}\r
--- /dev/null
+org.gradle.jvmargs=-Xms256m -Xmx1024m\r
+system.include.dir=/usr/include\r
+#system.local.include.dir=../../include\r
+system.local.include.dir=./build/generated/sources/headers/java/main\r
+jni.include.dir=/usr/lib/jvm/java-8-openjdk-amd64/include/\r
+jni.lib.dir=/usr/lib/jvm/java-8-openjdk-amd64/lib/\r
--- /dev/null
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.1-bin.zip
+networkTimeout=10000
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
--- /dev/null
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+# Collect all arguments for the java command;
+# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
+# shell script including quotes and variable substitutions, so put them in
+# double quotes to make sure that they get re-expanded; and
+# * put everything else in single quotes, so that it's not re-expanded.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
--- /dev/null
+@rem\r
+@rem Copyright 2015 the original author or authors.\r
+@rem\r
+@rem Licensed under the Apache License, Version 2.0 (the "License");\r
+@rem you may not use this file except in compliance with the License.\r
+@rem You may obtain a copy of the License at\r
+@rem\r
+@rem https://www.apache.org/licenses/LICENSE-2.0\r
+@rem\r
+@rem Unless required by applicable law or agreed to in writing, software\r
+@rem distributed under the License is distributed on an "AS IS" BASIS,\r
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+@rem See the License for the specific language governing permissions and\r
+@rem limitations under the License.\r
+@rem\r
+\r
+@if "%DEBUG%"=="" @echo off\r
+@rem ##########################################################################\r
+@rem\r
+@rem Gradle startup script for Windows\r
+@rem\r
+@rem ##########################################################################\r
+\r
+@rem Set local scope for the variables with windows NT shell\r
+if "%OS%"=="Windows_NT" setlocal\r
+\r
+set DIRNAME=%~dp0\r
+if "%DIRNAME%"=="" set DIRNAME=.\r
+@rem This is normally unused\r
+set APP_BASE_NAME=%~n0\r
+set APP_HOME=%DIRNAME%\r
+\r
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.\r
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi\r
+\r
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"\r
+\r
+@rem Find java.exe\r
+if defined JAVA_HOME goto findJavaFromJavaHome\r
+\r
+set JAVA_EXE=java.exe\r
+%JAVA_EXE% -version >NUL 2>&1\r
+if %ERRORLEVEL% equ 0 goto execute\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:findJavaFromJavaHome\r
+set JAVA_HOME=%JAVA_HOME:"=%\r
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe\r
+\r
+if exist "%JAVA_EXE%" goto execute\r
+\r
+echo.\r
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r
+echo.\r
+echo Please set the JAVA_HOME variable in your environment to match the\r
+echo location of your Java installation.\r
+\r
+goto fail\r
+\r
+:execute\r
+@rem Setup the command line\r
+\r
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar\r
+\r
+\r
+@rem Execute Gradle\r
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*\r
+\r
+:end\r
+@rem End local scope for the variables with windows NT shell\r
+if %ERRORLEVEL% equ 0 goto mainEnd\r
+\r
+:fail\r
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r
+rem the _cmd.exe /c_ return code!\r
+set EXIT_CODE=%ERRORLEVEL%\r
+if %EXIT_CODE% equ 0 set EXIT_CODE=1\r
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%\r
+exit /b %EXIT_CODE%\r
+\r
+:mainEnd\r
+if "%OS%"=="Windows_NT" endlocal\r
+\r
+:omega\r
--- /dev/null
+rootProject.name = "whispercpp"\r
--- /dev/null
+#include <stdio.h>\r
+#include "whisper_java.h"\r
+\r
+struct whisper_full_params default_params;\r
+struct whisper_context * whisper_ctx = nullptr;\r
+\r
+struct void whisper_java_default_params(enum whisper_sampling_strategy strategy) {\r
+ default_params = whisper_full_default_params(strategy);\r
+\r
+// struct whisper_java_params result = {};\r
+// return result;\r
+ return;\r
+}\r
+\r
+void whisper_java_init_from_file(const char * path_model) {\r
+ whisper_ctx = whisper_init_from_file(path_model);\r
+ if (0 == default_params.n_threads) {\r
+ whisper_java_default_params(WHISPER_SAMPLING_GREEDY);\r
+ }\r
+}\r
+\r
+/** Delegates to whisper_full, but without having to pass `whisper_full_params` */\r
+int whisper_java_full(\r
+ struct whisper_context * ctx,\r
+// struct whisper_java_params params,\r
+ const float * samples,\r
+ int n_samples) {\r
+ return whisper_full(ctx, default_params, samples, n_samples);\r
+}\r
+\r
+void whisper_java_free() {\r
+// free(default_params);\r
+}\r
--- /dev/null
+#define WHISPER_BUILD\r
+#include <whisper.h>\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+struct whisper_java_params {\r
+};\r
+\r
+WHISPER_API void whisper_java_default_params(enum whisper_sampling_strategy strategy);\r
+\r
+WHISPER_API void whisper_java_init_from_file(const char * path_model);\r
+\r
+WHISPER_API int whisper_java_full(\r
+ struct whisper_context * ctx,\r
+// struct whisper_java_params params,\r
+ const float * samples,\r
+ int n_samples);\r
+\r
+\r
+#ifdef __cplusplus\r
+}\r
+#endif\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import com.sun.jna.Structure;\r
+import com.sun.jna.ptr.PointerByReference;\r
+import io.github.ggerganov.whispercpp.ggml.GgmlType;\r
+import io.github.ggerganov.whispercpp.WhisperModel;\r
+\r
+import java.util.List;\r
+\r
+public class WhisperContext extends Structure {\r
+ int t_load_us = 0;\r
+ int t_start_us = 0;\r
+\r
+ /** weight type (FP32 / FP16 / QX) */\r
+ GgmlType wtype = GgmlType.GGML_TYPE_F16;\r
+ /** intermediate type (FP32 or FP16) */\r
+ GgmlType itype = GgmlType.GGML_TYPE_F16;\r
+\r
+// WhisperModel model;\r
+ public PointerByReference model;\r
+// whisper_vocab vocab;\r
+// whisper_state * state = nullptr;\r
+ public PointerByReference vocab;\r
+ public PointerByReference state;\r
+\r
+ /** populated by whisper_init_from_file() */\r
+ String path_model;\r
+\r
+// public static class ByReference extends WhisperContext implements Structure.ByReference {\r
+// }\r
+//\r
+// public static class ByValue extends WhisperContext implements Structure.ByValue {\r
+// }\r
+//\r
+// @Override\r
+// protected List<String> getFieldOrder() {\r
+// return List.of("t_load_us", "t_start_us", "wtype", "itype", "model", "vocab", "state", "path_model");\r
+// }\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.params.WhisperJavaParams;\r
+import io.github.ggerganov.whispercpp.params.WhisperSamplingStrategy;\r
+\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * Before calling most methods, you must call `initContext(modelPath)` to initialise the `ctx` Pointer.\r
+ */\r
+public class WhisperCpp implements AutoCloseable {\r
+ private WhisperCppJnaLibrary lib = WhisperCppJnaLibrary.instance;\r
+ private WhisperJavaJnaLibrary javaLib = WhisperJavaJnaLibrary.instance;\r
+ private Pointer ctx = null;\r
+\r
+ public File modelDir() {\r
+ String modelDirPath = System.getenv("XDG_CACHE_HOME");\r
+ if (modelDirPath == null) {\r
+ modelDirPath = System.getProperty("user.home") + "/.cache";\r
+ }\r
+\r
+ return new File(modelDirPath, "whisper");\r
+ }\r
+\r
+ /**\r
+ * @param modelPath - absolute path, or just the name (eg: "base", "base-en" or "base.en")\r
+ * @return a Pointer to the WhisperContext\r
+ */\r
+ void initContext(String modelPath) throws FileNotFoundException {\r
+ if (ctx != null) {\r
+ lib.whisper_free(ctx);\r
+ }\r
+\r
+ if (!modelPath.contains("/") && !modelPath.contains("\\")) {\r
+ if (!modelPath.endsWith(".bin")) {\r
+ modelPath = "ggml-" + modelPath.replace("-", ".") + ".bin";\r
+ }\r
+\r
+ modelPath = new File(modelDir(), modelPath).getAbsolutePath();\r
+ }\r
+\r
+ javaLib.whisper_java_init_from_file(modelPath);\r
+ ctx = lib.whisper_init_from_file(modelPath);\r
+\r
+ if (ctx == null) {\r
+ throw new FileNotFoundException(modelPath);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Initialises `whisper_full_params` internally in whisper_java.cpp so JNA doesn't have to map everything.\r
+ * `whisper_java_init_from_file()` calls `whisper_java_default_params(WHISPER_SAMPLING_GREEDY)` for convenience.\r
+ */\r
+ public void getDefaultJavaParams(WhisperSamplingStrategy strategy) {\r
+ javaLib.whisper_java_default_params(strategy.ordinal());\r
+// return lib.whisper_full_default_params(strategy.value)\r
+ }\r
+\r
+// whisper_full_default_params was too hard to integrate with, so for now we use javaLib.whisper_java_default_params\r
+// fun getDefaultParams(strategy: WhisperSamplingStrategy): WhisperFullParams {\r
+// return lib.whisper_full_default_params(strategy.value)\r
+// }\r
+\r
+ @Override\r
+ public void close() {\r
+ freeContext();\r
+ System.out.println("Whisper closed");\r
+ }\r
+\r
+ private void freeContext() {\r
+ if (ctx != null) {\r
+ lib.whisper_free(ctx);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text.\r
+ * Not thread safe for same context\r
+ * Uses the specified decoding strategy to obtain the text.\r
+ */\r
+ public String fullTranscribe(/*WhisperJavaParams whisperParams,*/ float[] audioData) throws IOException {\r
+ if (ctx == null) {\r
+ throw new IllegalStateException("Model not initialised");\r
+ }\r
+\r
+ if (javaLib.whisper_java_full(ctx, /*whisperParams,*/ audioData, audioData.length) != 0) {\r
+ throw new IOException("Failed to process audio");\r
+ }\r
+\r
+ int nSegments = lib.whisper_full_n_segments(ctx);\r
+\r
+ StringBuilder str = new StringBuilder();\r
+\r
+ for (int i = 0; i < nSegments; i++) {\r
+ String text = lib.whisper_full_get_segment_text(ctx, i);\r
+ System.out.println("Segment:" + text);\r
+ str.append(text);\r
+ }\r
+\r
+ return str.toString().trim();\r
+ }\r
+\r
+// public int getTextSegmentCount(Pointer ctx) {\r
+// return lib.whisper_full_n_segments(ctx);\r
+// }\r
+// public String getTextSegment(Pointer ctx, int index) {\r
+// return lib.whisper_full_get_segment_text(ctx, index);\r
+// }\r
+\r
+ public String getSystemInfo() {\r
+ return lib.whisper_print_system_info();\r
+ }\r
+\r
+ public int benchMemcpy(int nthread) {\r
+ return lib.whisper_bench_memcpy(nthread);\r
+ }\r
+\r
+ public int benchGgmlMulMat(int nthread) {\r
+ return lib.whisper_bench_ggml_mul_mat(nthread);\r
+ }\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import com.sun.jna.Library;\r
+import com.sun.jna.Native;\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.model.WhisperModelLoader;\r
+import io.github.ggerganov.whispercpp.model.WhisperTokenData;\r
+import io.github.ggerganov.whispercpp.params.WhisperFullParams;\r
+\r
+public interface WhisperCppJnaLibrary extends Library {\r
+ WhisperCppJnaLibrary instance = Native.load("whisper", WhisperCppJnaLibrary.class);\r
+\r
+ String whisper_print_system_info();\r
+\r
+ /**\r
+ * Allocate (almost) all memory needed for the model by loading from a file.\r
+ *\r
+ * @param path_model Path to the model file\r
+ * @return Whisper context on success, null on failure\r
+ */\r
+ Pointer whisper_init_from_file(String path_model);\r
+\r
+ /**\r
+ * Allocate (almost) all memory needed for the model by loading from a buffer.\r
+ *\r
+ * @param buffer Model buffer\r
+ * @param buffer_size Size of the model buffer\r
+ * @return Whisper context on success, null on failure\r
+ */\r
+ Pointer whisper_init_from_buffer(Pointer buffer, int buffer_size);\r
+\r
+ /**\r
+ * Allocate (almost) all memory needed for the model using a model loader.\r
+ *\r
+ * @param loader Model loader\r
+ * @return Whisper context on success, null on failure\r
+ */\r
+ Pointer whisper_init(WhisperModelLoader loader);\r
+\r
+ /**\r
+ * Allocate (almost) all memory needed for the model by loading from a file without allocating the state.\r
+ *\r
+ * @param path_model Path to the model file\r
+ * @return Whisper context on success, null on failure\r
+ */\r
+ Pointer whisper_init_from_file_no_state(String path_model);\r
+\r
+ /**\r
+ * Allocate (almost) all memory needed for the model by loading from a buffer without allocating the state.\r
+ *\r
+ * @param buffer Model buffer\r
+ * @param buffer_size Size of the model buffer\r
+ * @return Whisper context on success, null on failure\r
+ */\r
+ Pointer whisper_init_from_buffer_no_state(Pointer buffer, int buffer_size);\r
+\r
+// Pointer whisper_init_from_buffer_no_state(Pointer buffer, long buffer_size);\r
+\r
+ /**\r
+ * Allocate (almost) all memory needed for the model using a model loader without allocating the state.\r
+ *\r
+ * @param loader Model loader\r
+ * @return Whisper context on success, null on failure\r
+ */\r
+ Pointer whisper_init_no_state(WhisperModelLoader loader);\r
+\r
+ /**\r
+ * Allocate memory for the Whisper state.\r
+ *\r
+ * @param ctx Whisper context\r
+ * @return Whisper state on success, null on failure\r
+ */\r
+ Pointer whisper_init_state(Pointer ctx);\r
+\r
+ /**\r
+ * Free all allocated memory associated with the Whisper context.\r
+ *\r
+ * @param ctx Whisper context\r
+ */\r
+ void whisper_free(Pointer ctx);\r
+\r
+ /**\r
+ * Free all allocated memory associated with the Whisper state.\r
+ *\r
+ * @param state Whisper state\r
+ */\r
+ void whisper_free_state(Pointer state);\r
+\r
+\r
+ /**\r
+ * Convert RAW PCM audio to log mel spectrogram.\r
+ * The resulting spectrogram is stored inside the default state of the provided whisper context.\r
+ *\r
+ * @param ctx - Pointer to a WhisperContext\r
+ * @return 0 on success\r
+ */\r
+ int whisper_pcm_to_mel(Pointer ctx, final float[] samples, int n_samples, int n_threads);\r
+\r
+ /**\r
+ * @param ctx Pointer to a WhisperContext\r
+ * @param state Pointer to WhisperState\r
+ * @param n_samples\r
+ * @param n_threads\r
+ * @return 0 on success\r
+ */\r
+ int whisper_pcm_to_mel_with_state(Pointer ctx, Pointer state, final float[] samples, int n_samples, int n_threads);\r
+\r
+ /**\r
+ * This can be used to set a custom log mel spectrogram inside the default state of the provided whisper context.\r
+ * Use this instead of whisper_pcm_to_mel() if you want to provide your own log mel spectrogram.\r
+ * n_mel must be 80\r
+ * @return 0 on success\r
+ */\r
+ int whisper_set_mel(Pointer ctx, final float[] data, int n_len, int n_mel);\r
+ int whisper_set_mel_with_state(Pointer ctx, Pointer state, final float[] data, int n_len, int n_mel);\r
+\r
+ /**\r
+ * Run the Whisper encoder on the log mel spectrogram stored inside the default state in the provided whisper context.\r
+ * Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first.\r
+ * Offset can be used to specify the offset of the first frame in the spectrogram.\r
+ * @return 0 on success\r
+ */\r
+ int whisper_encode(Pointer ctx, int offset, int n_threads);\r
+\r
+ int whisper_encode_with_state(Pointer ctx, Pointer state, int offset, int n_threads);\r
+\r
+ /**\r
+ * Run the Whisper decoder to obtain the logits and probabilities for the next token.\r
+ * Make sure to call whisper_encode() first.\r
+ * tokens + n_tokens is the provided context for the decoder.\r
+ * n_past is the number of tokens to use from previous decoder calls.\r
+ * Returns 0 on success\r
+ * TODO: add support for multiple decoders\r
+ */\r
+ int whisper_decode(Pointer ctx, Pointer tokens, int n_tokens, int n_past, int n_threads);\r
+\r
+ /**\r
+ * @param ctx\r
+ * @param state\r
+ * @param tokens Pointer to int tokens\r
+ * @param n_tokens\r
+ * @param n_past\r
+ * @param n_threads\r
+ * @return\r
+ */\r
+ int whisper_decode_with_state(Pointer ctx, Pointer state, Pointer tokens, int n_tokens, int n_past, int n_threads);\r
+\r
+ /**\r
+ * Convert the provided text into tokens.\r
+ * The tokens pointer must be large enough to hold the resulting tokens.\r
+ * Returns the number of tokens on success, no more than n_max_tokens\r
+ * Returns -1 on failure\r
+ * TODO: not sure if correct\r
+ */\r
+ int whisper_tokenize(Pointer ctx, String text, Pointer tokens, int n_max_tokens);\r
+\r
+ /** Largest language id (i.e. number of available languages - 1) */\r
+ int whisper_lang_max_id();\r
+\r
+ /**\r
+ * @return the id of the specified language, returns -1 if not found.\r
+ * Examples:\r
+ * "de" -> 2\r
+ * "german" -> 2\r
+ */\r
+ int whisper_lang_id(String lang);\r
+\r
+ /** @return the short string of the specified language id (e.g. 2 -> "de"), returns nullptr if not found */\r
+ String whisper_lang_str(int id);\r
+\r
+ /**\r
+ * Use mel data at offset_ms to try and auto-detect the spoken language.\r
+ * Make sure to call whisper_pcm_to_mel() or whisper_set_mel() first\r
+ * Returns the top language id or negative on failure\r
+ * If not null, fills the lang_probs array with the probabilities of all languages\r
+ * The array must be whisper_lang_max_id() + 1 in size\r
+ *\r
+ * ref: https://github.com/openai/whisper/blob/main/whisper/decoding.py#L18-L69\r
+ */\r
+ int whisper_lang_auto_detect(Pointer ctx, int offset_ms, int n_threads, float[] lang_probs);\r
+\r
+ int whisper_lang_auto_detect_with_state(Pointer ctx, Pointer state, int offset_ms, int n_threads, float[] lang_probs);\r
+\r
+ int whisper_n_len (Pointer ctx); // mel length\r
+ int whisper_n_len_from_state(Pointer state); // mel length\r
+ int whisper_n_vocab (Pointer ctx);\r
+ int whisper_n_text_ctx (Pointer ctx);\r
+ int whisper_n_audio_ctx (Pointer ctx);\r
+ int whisper_is_multilingual (Pointer ctx);\r
+\r
+ int whisper_model_n_vocab (Pointer ctx);\r
+ int whisper_model_n_audio_ctx (Pointer ctx);\r
+ int whisper_model_n_audio_state(Pointer ctx);\r
+ int whisper_model_n_audio_head (Pointer ctx);\r
+ int whisper_model_n_audio_layer(Pointer ctx);\r
+ int whisper_model_n_text_ctx (Pointer ctx);\r
+ int whisper_model_n_text_state (Pointer ctx);\r
+ int whisper_model_n_text_head (Pointer ctx);\r
+ int whisper_model_n_text_layer (Pointer ctx);\r
+ int whisper_model_n_mels (Pointer ctx);\r
+ int whisper_model_ftype (Pointer ctx);\r
+ int whisper_model_type (Pointer ctx);\r
+\r
+ /**\r
+ * Token logits obtained from the last call to whisper_decode().\r
+ * The logits for the last token are stored in the last row\r
+ * Rows: n_tokens\r
+ * Cols: n_vocab\r
+ */\r
+ float[] whisper_get_logits (Pointer ctx);\r
+ float[] whisper_get_logits_from_state(Pointer state);\r
+\r
+ // Token Id -> String. Uses the vocabulary in the provided context\r
+ String whisper_token_to_str(Pointer ctx, int token);\r
+ String whisper_model_type_readable(Pointer ctx);\r
+\r
+ // Special tokens\r
+ int whisper_token_eot (Pointer ctx);\r
+ int whisper_token_sot (Pointer ctx);\r
+ int whisper_token_prev(Pointer ctx);\r
+ int whisper_token_solm(Pointer ctx);\r
+ int whisper_token_not (Pointer ctx);\r
+ int whisper_token_beg (Pointer ctx);\r
+ int whisper_token_lang(Pointer ctx, int lang_id);\r
+\r
+ // Task tokens\r
+ int whisper_token_translate();\r
+ int whisper_token_transcribe();\r
+\r
+ // Performance information from the default state.\r
+ void whisper_print_timings(Pointer ctx);\r
+ void whisper_reset_timings(Pointer ctx);\r
+\r
+ /**\r
+ * @param strategy - WhisperSamplingStrategy.value\r
+ */\r
+ WhisperFullParams whisper_full_default_params(int strategy);\r
+\r
+ /**\r
+ * Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text\r
+ * Not thread safe for same context\r
+ * Uses the specified decoding strategy to obtain the text.\r
+ */\r
+ int whisper_full(Pointer ctx, WhisperFullParams params, final float[] samples, int n_samples);\r
+\r
+ int whisper_full_with_state(Pointer ctx, Pointer state, WhisperFullParams params, final float[] samples, int n_samples);\r
+\r
+ // Split the input audio in chunks and process each chunk separately using whisper_full_with_state()\r
+ // Result is stored in the default state of the context\r
+ // Not thread safe if executed in parallel on the same context.\r
+ // It seems this approach can offer some speedup in some cases.\r
+ // However, the transcription accuracy can be worse at the beginning and end of each chunk.\r
+ int whisper_full_parallel(Pointer ctx, WhisperFullParams params, final float[] samples, int n_samples, int n_processors);\r
+\r
+ /**\r
+ * Number of generated text segments.\r
+ * A segment can be a few words, a sentence, or even a paragraph.\r
+ * @param ctx Pointer to WhisperContext\r
+ */\r
+ int whisper_full_n_segments (Pointer ctx);\r
+\r
+ /**\r
+ * @param state Pointer to WhisperState\r
+ */\r
+ int whisper_full_n_segments_from_state(Pointer state);\r
+\r
+ /**\r
+ * Language id associated with the context's default state.\r
+ * @param ctx Pointer to WhisperContext\r
+ */\r
+ int whisper_full_lang_id(Pointer ctx);\r
+\r
+ /** Language id associated with the provided state */\r
+ int whisper_full_lang_id_from_state(Pointer state);\r
+\r
+ /**\r
+ * Convert RAW PCM audio to log mel spectrogram but applies a Phase Vocoder to speed up the audio x2.\r
+ * The resulting spectrogram is stored inside the default state of the provided whisper context.\r
+ * @return 0 on success\r
+ */\r
+ int whisper_pcm_to_mel_phase_vocoder(Pointer ctx, final float[] samples, int n_samples, int n_threads);\r
+\r
+ int whisper_pcm_to_mel_phase_vocoder_with_state(Pointer ctx, Pointer state, final float[] samples, int n_samples, int n_threads);\r
+\r
+ /** Get the start time of the specified segment. */\r
+ long whisper_full_get_segment_t0(Pointer ctx, int i_segment);\r
+\r
+ /** Get the start time of the specified segment from the state. */\r
+ long whisper_full_get_segment_t0_from_state(Pointer state, int i_segment);\r
+\r
+ /** Get the end time of the specified segment. */\r
+ long whisper_full_get_segment_t1(Pointer ctx, int i_segment);\r
+\r
+ /** Get the end time of the specified segment from the state. */\r
+ long whisper_full_get_segment_t1_from_state(Pointer state, int i_segment);\r
+\r
+ /** Get the text of the specified segment. */\r
+ String whisper_full_get_segment_text(Pointer ctx, int i_segment);\r
+\r
+ /** Get the text of the specified segment from the state. */\r
+ String whisper_full_get_segment_text_from_state(Pointer state, int i_segment);\r
+\r
+ /** Get the number of tokens in the specified segment. */\r
+ int whisper_full_n_tokens(Pointer ctx, int i_segment);\r
+\r
+ /** Get the number of tokens in the specified segment from the state. */\r
+ int whisper_full_n_tokens_from_state(Pointer state, int i_segment);\r
+\r
+ /** Get the token text of the specified token in the specified segment. */\r
+ String whisper_full_get_token_text(Pointer ctx, int i_segment, int i_token);\r
+\r
+\r
+ /** Get the token text of the specified token in the specified segment from the state. */\r
+ String whisper_full_get_token_text_from_state(Pointer ctx, Pointer state, int i_segment, int i_token);\r
+\r
+ /** Get the token ID of the specified token in the specified segment. */\r
+ int whisper_full_get_token_id(Pointer ctx, int i_segment, int i_token);\r
+\r
+ /** Get the token ID of the specified token in the specified segment from the state. */\r
+ int whisper_full_get_token_id_from_state(Pointer state, int i_segment, int i_token);\r
+\r
+ /** Get token data for the specified token in the specified segment. */\r
+ WhisperTokenData whisper_full_get_token_data(Pointer ctx, int i_segment, int i_token);\r
+\r
+ /** Get token data for the specified token in the specified segment from the state. */\r
+ WhisperTokenData whisper_full_get_token_data_from_state(Pointer state, int i_segment, int i_token);\r
+\r
+ /** Get the probability of the specified token in the specified segment. */\r
+ float whisper_full_get_token_p(Pointer ctx, int i_segment, int i_token);\r
+\r
+ /** Get the probability of the specified token in the specified segment from the state. */\r
+ float whisper_full_get_token_p_from_state(Pointer state, int i_segment, int i_token);\r
+\r
+ /**\r
+ * Benchmark function for memcpy.\r
+ *\r
+ * @param nThreads Number of threads to use for the benchmark.\r
+ * @return The result of the benchmark.\r
+ */\r
+ int whisper_bench_memcpy(int nThreads);\r
+\r
+ /**\r
+ * Benchmark function for memcpy as a string.\r
+ *\r
+ * @param nThreads Number of threads to use for the benchmark.\r
+ * @return The result of the benchmark as a string.\r
+ */\r
+ String whisper_bench_memcpy_str(int nThreads);\r
+\r
+ /**\r
+ * Benchmark function for ggml_mul_mat.\r
+ *\r
+ * @param nThreads Number of threads to use for the benchmark.\r
+ * @return The result of the benchmark.\r
+ */\r
+ int whisper_bench_ggml_mul_mat(int nThreads);\r
+\r
+ /**\r
+ * Benchmark function for ggml_mul_mat as a string.\r
+ *\r
+ * @param nThreads Number of threads to use for the benchmark.\r
+ * @return The result of the benchmark as a string.\r
+ */\r
+ String whisper_bench_ggml_mul_mat_str(int nThreads);\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import com.sun.jna.Library;\r
+import com.sun.jna.Native;\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.params.WhisperJavaParams;\r
+\r
+interface WhisperJavaJnaLibrary extends Library {\r
+ WhisperJavaJnaLibrary instance = Native.load("whisper_java", WhisperJavaJnaLibrary.class);\r
+\r
+ void whisper_java_default_params(int strategy);\r
+\r
+ void whisper_java_free();\r
+\r
+ void whisper_java_init_from_file(String modelPath);\r
+\r
+ /**\r
+ * Run the entire model: PCM -> log mel spectrogram -> encoder -> decoder -> text.\r
+ * Not thread safe for same context\r
+ * Uses the specified decoding strategy to obtain the text.\r
+ */\r
+ int whisper_java_full(Pointer ctx, /*WhisperJavaParams params, */float[] samples, int nSamples);\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.callbacks;\r
+\r
+import com.sun.jna.Callback;\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.WhisperContext;\r
+import io.github.ggerganov.whispercpp.model.WhisperState;\r
+\r
+/**\r
+ * Callback before the encoder starts.\r
+ * If not null, called before the encoder starts.\r
+ * If it returns false, the computation is aborted.\r
+ */\r
+public interface WhisperEncoderBeginCallback extends Callback {\r
+\r
+ /**\r
+ * Callback method before the encoder starts.\r
+ *\r
+ * @param ctx The whisper context.\r
+ * @param state The whisper state.\r
+ * @param user_data User data.\r
+ * @return True if the computation should proceed, false otherwise.\r
+ */\r
+ boolean callback(WhisperContext ctx, WhisperState state, Pointer user_data);\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.callbacks;\r
+\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.WhisperContext;\r
+import io.github.ggerganov.whispercpp.model.WhisperState;\r
+import io.github.ggerganov.whispercpp.model.WhisperTokenData;\r
+\r
+import javax.security.auth.callback.Callback;\r
+\r
+/**\r
+ * Callback to filter logits.\r
+ * Can be used to modify the logits before sampling.\r
+ * If not null, called after applying temperature to logits.\r
+ */\r
+public interface WhisperLogitsFilterCallback extends Callback {\r
+\r
+ /**\r
+ * Callback method to filter logits.\r
+ *\r
+ * @param ctx The whisper context.\r
+ * @param state The whisper state.\r
+ * @param tokens The array of whisper_token_data.\r
+ * @param n_tokens The number of tokens.\r
+ * @param logits The array of logits.\r
+ * @param user_data User data.\r
+ */\r
+ void callback(WhisperContext ctx, WhisperState state, WhisperTokenData[] tokens, int n_tokens, float[] logits, Pointer user_data);\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.callbacks;\r
+\r
+import com.sun.jna.Callback;\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.WhisperContext;\r
+import io.github.ggerganov.whispercpp.model.WhisperState;\r
+\r
+/**\r
+ * Callback for the text segment.\r
+ * Called on every newly generated text segment.\r
+ * Use the whisper_full_...() functions to obtain the text segments.\r
+ */\r
+public interface WhisperNewSegmentCallback extends Callback {\r
+\r
+ /**\r
+ * Callback method for the text segment.\r
+ *\r
+ * @param ctx The whisper context.\r
+ * @param state The whisper state.\r
+ * @param n_new The number of newly generated text segments.\r
+ * @param user_data User data.\r
+ */\r
+ void callback(WhisperContext ctx, WhisperState state, int n_new, Pointer user_data);\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.callbacks;\r
+\r
+import com.sun.jna.Pointer;\r
+import io.github.ggerganov.whispercpp.WhisperContext;\r
+import io.github.ggerganov.whispercpp.model.WhisperState;\r
+\r
+import javax.security.auth.callback.Callback;\r
+\r
+/**\r
+ * Callback for progress updates.\r
+ */\r
+public interface WhisperProgressCallback extends Callback {\r
+\r
+ /**\r
+ * Callback method for progress updates.\r
+ *\r
+ * @param ctx The whisper context.\r
+ * @param state The whisper state.\r
+ * @param progress The progress value.\r
+ * @param user_data User data.\r
+ */\r
+ void callback(WhisperContext ctx, WhisperState state, int progress, Pointer user_data);\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.ggml;\r
+\r
+public class GgmlTensor {\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.ggml;\r
+\r
+public enum GgmlType {\r
+ GGML_TYPE_F32,\r
+ GGML_TYPE_F16,\r
+ GGML_TYPE_Q4_0,\r
+ GGML_TYPE_Q4_1,\r
+ REMOVED_GGML_TYPE_Q4_2, // support has been removed\r
+ REMOVED_GGML_TYPE_Q4_3, // support has been removed\r
+ GGML_TYPE_Q5_0,\r
+ GGML_TYPE_Q5_1,\r
+ GGML_TYPE_Q8_0,\r
+ GGML_TYPE_Q8_1,\r
+ GGML_TYPE_I8,\r
+ GGML_TYPE_I16,\r
+ GGML_TYPE_I32,\r
+ GGML_TYPE_COUNT,\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.model;\r
+\r
+public enum EModel {\r
+ MODEL_UNKNOWN,\r
+ MODEL_TINY,\r
+ MODEL_BASE,\r
+ MODEL_SMALL,\r
+ MODEL_MEDIUM,\r
+ MODEL_LARGE,\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import io.github.ggerganov.whispercpp.ggml.GgmlTensor;\r
+import io.github.ggerganov.whispercpp.model.EModel;\r
+\r
+public class WhisperModel {\r
+// EModel type = EModel.MODEL_UNKNOWN;\r
+//\r
+// WhisperHParams hparams;\r
+// WhisperFilters filters;\r
+//\r
+// // encoder.positional_embedding\r
+// GgmlTensor e_pe;\r
+//\r
+// // encoder.conv1\r
+// GgmlTensor e_conv_1_w;\r
+// GgmlTensor e_conv_1_b;\r
+//\r
+// // encoder.conv2\r
+// GgmlTensor e_conv_2_w;\r
+// GgmlTensor e_conv_2_b;\r
+//\r
+// // encoder.ln_post\r
+// GgmlTensor e_ln_w;\r
+// GgmlTensor e_ln_b;\r
+//\r
+// // decoder.positional_embedding\r
+// GgmlTensor d_pe;\r
+//\r
+// // decoder.token_embedding\r
+// GgmlTensor d_te;\r
+//\r
+// // decoder.ln\r
+// GgmlTensor d_ln_w;\r
+// GgmlTensor d_ln_b;\r
+//\r
+// std::vector<whisper_layer_encoder> layers_encoder;\r
+// std::vector<whisper_layer_decoder> layers_decoder;\r
+//\r
+// // context\r
+// struct ggml_context * ctx;\r
+//\r
+// // the model memory buffer is read-only and can be shared between processors\r
+// std::vector<uint8_t> * buf;\r
+//\r
+// // tensors\r
+// int n_loaded;\r
+// Map<String, GgmlTensor> tensors;\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.model;\r
+\r
+import com.sun.jna.Callback;\r
+import com.sun.jna.Pointer;\r
+import com.sun.jna.Structure;\r
+\r
+\r
+public class WhisperModelLoader extends Structure {\r
+ public Pointer context;\r
+ public ReadFunction read;\r
+ public EOFFunction eof;\r
+ public CloseFunction close;\r
+\r
+ public static class ReadFunction implements Callback {\r
+ public Pointer invoke(Pointer ctx, Pointer output, int readSize) {\r
+ // TODO\r
+ return ctx;\r
+ }\r
+ }\r
+\r
+ public static class EOFFunction implements Callback {\r
+ public boolean invoke(Pointer ctx) {\r
+ // TODO\r
+ return false;\r
+ }\r
+ }\r
+\r
+ public static class CloseFunction implements Callback {\r
+ public void invoke(Pointer ctx) {\r
+ // TODO\r
+ }\r
+ }\r
+\r
+// public WhisperModelLoader(Pointer p) {\r
+// super(p);\r
+// read = new ReadFunction();\r
+// eof = new EOFFunction();\r
+// close = new CloseFunction();\r
+// read.setCallback(this);\r
+// eof.setCallback(this);\r
+// close.setCallback(this);\r
+// read.write();\r
+// eof.write();\r
+// close.write();\r
+// }\r
+\r
+ public WhisperModelLoader() {\r
+ super();\r
+ }\r
+\r
+ public interface ReadCallback extends Callback {\r
+ Pointer invoke(Pointer ctx, Pointer output, int readSize);\r
+ }\r
+\r
+ public interface EOFCallback extends Callback {\r
+ boolean invoke(Pointer ctx);\r
+ }\r
+\r
+ public interface CloseCallback extends Callback {\r
+ void invoke(Pointer ctx);\r
+ }\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.model;\r
+\r
+public class WhisperState {\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.model;\r
+\r
+import com.sun.jna.Structure;\r
+\r
+import java.util.Arrays;\r
+import java.util.List;\r
+\r
+/**\r
+ * Structure representing token data.\r
+ */\r
+public class WhisperTokenData extends Structure {\r
+\r
+ /** Token ID. */\r
+ public int id;\r
+\r
+ /** Forced timestamp token ID. */\r
+ public int tid;\r
+\r
+ /** Probability of the token. */\r
+ public float p;\r
+\r
+ /** Log probability of the token. */\r
+ public float plog;\r
+\r
+ /** Probability of the timestamp token. */\r
+ public float pt;\r
+\r
+ /** Sum of probabilities of all timestamp tokens. */\r
+ public float ptsum;\r
+\r
+ /**\r
+ * Start time of the token (token-level timestamp data).\r
+ * Do not use if you haven't computed token-level timestamps.\r
+ */\r
+ public long t0;\r
+\r
+ /**\r
+ * End time of the token (token-level timestamp data).\r
+ * Do not use if you haven't computed token-level timestamps.\r
+ */\r
+ public long t1;\r
+\r
+ /** Voice length of the token. */\r
+ public float vlen;\r
+\r
+ @Override\r
+ protected List<String> getFieldOrder() {\r
+ return Arrays.asList("id", "tid", "p", "plog", "pt", "ptsum", "t0", "t1", "vlen");\r
+ }\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.params;\r
+\r
+import java.util.List;\r
+\r
+public class WhisperFilters {\r
+ int n_mel;\r
+ int n_fft;\r
+\r
+ List<Float> data;\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.params;\r
+\r
+import com.sun.jna.Callback;\r
+import com.sun.jna.Pointer;\r
+import com.sun.jna.Structure;\r
+import io.github.ggerganov.whispercpp.callbacks.WhisperEncoderBeginCallback;\r
+import io.github.ggerganov.whispercpp.callbacks.WhisperLogitsFilterCallback;\r
+import io.github.ggerganov.whispercpp.callbacks.WhisperNewSegmentCallback;\r
+import io.github.ggerganov.whispercpp.callbacks.WhisperProgressCallback;\r
+\r
+/**\r
+ * Parameters for the whisper_full() function.\r
+ * If you change the order or add new parameters, make sure to update the default values in whisper.cpp:\r
+ * whisper_full_default_params()\r
+ */\r
+public class WhisperFullParams extends Structure {\r
+\r
+ /** Sampling strategy for whisper_full() function. */\r
+ public int strategy;\r
+\r
+ /** Number of threads. */\r
+ public int n_threads;\r
+\r
+ /** Maximum tokens to use from past text as a prompt for the decoder. */\r
+ public int n_max_text_ctx;\r
+\r
+ /** Start offset in milliseconds. */\r
+ public int offset_ms;\r
+\r
+ /** Audio duration to process in milliseconds. */\r
+ public int duration_ms;\r
+\r
+ /** Translate flag. */\r
+ public boolean translate;\r
+\r
+ /** Flag to indicate whether to use past transcription (if any) as an initial prompt for the decoder. */\r
+ public boolean no_context;\r
+\r
+ /** Flag to force single segment output (useful for streaming). */\r
+ public boolean single_segment;\r
+\r
+ /** Flag to print special tokens (e.g., <SOT>, <EOT>, <BEG>, etc.). */\r
+ public boolean print_special;\r
+\r
+ /** Flag to print progress information. */\r
+ public boolean print_progress;\r
+\r
+ /** Flag to print results from within whisper.cpp (avoid it, use callback instead). */\r
+ public boolean print_realtime;\r
+\r
+ /** Flag to print timestamps for each text segment when printing realtime. */\r
+ public boolean print_timestamps;\r
+\r
+ /** [EXPERIMENTAL] Flag to enable token-level timestamps. */\r
+ public boolean token_timestamps;\r
+\r
+ /** [EXPERIMENTAL] Timestamp token probability threshold (~0.01). */\r
+ public float thold_pt;\r
+\r
+ /** [EXPERIMENTAL] Timestamp token sum probability threshold (~0.01). */\r
+ public float thold_ptsum;\r
+\r
+ /** Maximum segment length in characters. */\r
+ public int max_len;\r
+\r
+ /** Flag to split on word rather than on token (when used with max_len). */\r
+ public boolean split_on_word;\r
+\r
+ /** Maximum tokens per segment (0 = no limit). */\r
+ public int max_tokens;\r
+\r
+ /** Flag to speed up the audio by 2x using Phase Vocoder. */\r
+ public boolean speed_up;\r
+\r
+ /** Overwrite the audio context size (0 = use default). */\r
+ public int audio_ctx;\r
+\r
+ /** Tokens to provide to the whisper decoder as an initial prompt.\r
+ * These are prepended to any existing text context from a previous call. */\r
+ public String initial_prompt;\r
+\r
+ /** Prompt tokens. */\r
+ public Pointer prompt_tokens;\r
+\r
+ /** Number of prompt tokens. */\r
+ public int prompt_n_tokens;\r
+\r
+ /** Language for auto-detection.\r
+ * For auto-detection, set to `null`, `""`, or "auto". */\r
+ public String language;\r
+\r
+ /** Flag to indicate whether to detect language automatically. */\r
+ public boolean detect_language;\r
+\r
+ /** Common decoding parameters. */\r
+\r
+ /** Flag to suppress blank tokens. */\r
+ public boolean suppress_blank;\r
+\r
+ /** Flag to suppress non-speech tokens. */\r
+ public boolean suppress_non_speech_tokens;\r
+\r
+ /** Initial decoding temperature. */\r
+ public float temperature;\r
+\r
+ /** Maximum initial timestamp. */\r
+ public float max_initial_ts;\r
+\r
+ /** Length penalty. */\r
+ public float length_penalty;\r
+\r
+ /** Fallback parameters. */\r
+\r
+ /** Temperature increment. */\r
+ public float temperature_inc;\r
+\r
+ /** Entropy threshold (similar to OpenAI's "compression_ratio_threshold"). */\r
+ public float entropy_thold;\r
+\r
+ /** Log probability threshold. */\r
+ public float logprob_thold;\r
+\r
+ /** No speech threshold. */\r
+ public float no_speech_thold;\r
+\r
+ class GreedyParams extends Structure {\r
+ /** https://github.com/openai/whisper/blob/f82bc59f5ea234d4b97fb2860842ed38519f7e65/whisper/transcribe.py#L264 */\r
+ public int best_of;\r
+ }\r
+\r
+ /** Greedy decoding parameters. */\r
+ public GreedyParams greedy;\r
+\r
+ class BeamSearchParams extends Structure {\r
+ /** ref: https://github.com/openai/whisper/blob/f82bc59f5ea234d4b97fb2860842ed38519f7e65/whisper/transcribe.py#L265 */\r
+ int beam_size;\r
+\r
+ /** ref: https://arxiv.org/pdf/2204.05424.pdf */\r
+ float patience;\r
+ }\r
+\r
+ /**\r
+ * Beam search decoding parameters.\r
+ */\r
+ public BeamSearchParams beam_search;\r
+\r
+ /**\r
+ * Callback for every newly generated text segment.\r
+ */\r
+ public WhisperNewSegmentCallback new_segment_callback;\r
+\r
+ /**\r
+ * User data for the new_segment_callback.\r
+ */\r
+ public Pointer new_segment_callback_user_data;\r
+\r
+ /**\r
+ * Callback on each progress update.\r
+ */\r
+ public WhisperProgressCallback progress_callback;\r
+\r
+ /**\r
+ * User data for the progress_callback.\r
+ */\r
+ public Pointer progress_callback_user_data;\r
+\r
+ /**\r
+ * Callback each time before the encoder starts.\r
+ */\r
+ public WhisperEncoderBeginCallback encoder_begin_callback;\r
+\r
+ /**\r
+ * User data for the encoder_begin_callback.\r
+ */\r
+ public Pointer encoder_begin_callback_user_data;\r
+\r
+ /**\r
+ * Callback by each decoder to filter obtained logits.\r
+ */\r
+ public WhisperLogitsFilterCallback logits_filter_callback;\r
+\r
+ /**\r
+ * User data for the logits_filter_callback.\r
+ */\r
+ public Pointer logits_filter_callback_user_data;\r
+}\r
+\r
--- /dev/null
+package io.github.ggerganov.whispercpp.params;\r
+\r
+public class WhisperHParams {\r
+ int n_vocab = 51864;\r
+ int n_audio_ctx = 1500;\r
+ int n_audio_state = 384;\r
+ int n_audio_head = 6;\r
+ int n_audio_layer = 4;\r
+ int n_text_ctx = 448;\r
+ int n_text_state = 384;\r
+ int n_text_head = 6;\r
+ int n_text_layer = 4;\r
+ int n_mels = 80;\r
+ int ftype = 1;\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.params;\r
+\r
+import com.sun.jna.Structure;\r
+\r
+public class WhisperJavaParams extends Structure {\r
+\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp.params;\r
+\r
+/** Available sampling strategies */\r
+public enum WhisperSamplingStrategy {\r
+ /** similar to OpenAI's GreedyDecoder */\r
+ WHISPER_SAMPLING_GREEDY,\r
+\r
+ /** similar to OpenAI's BeamSearchDecoder */\r
+ WHISPER_SAMPLING_BEAM_SEARCH\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import static org.junit.jupiter.api.Assertions.*;\r
+\r
+import io.github.ggerganov.whispercpp.params.WhisperJavaParams;\r
+import io.github.ggerganov.whispercpp.params.WhisperSamplingStrategy;\r
+import org.junit.jupiter.api.BeforeAll;\r
+import org.junit.jupiter.api.Test;\r
+import javax.sound.sampled.AudioInputStream;\r
+import javax.sound.sampled.AudioSystem;\r
+import java.io.File;\r
+import java.io.FileNotFoundException;\r
+\r
+class WhisperCppTest {\r
+ private static WhisperCpp whisper = new WhisperCpp();\r
+ private static boolean modelInitialised = false;\r
+\r
+ @BeforeAll\r
+ static void init() throws FileNotFoundException {\r
+ // By default, models are loaded from ~/.cache/whisper/ and are usually named "ggml-${name}.bin"\r
+ // or you can provide the absolute path to the model file.\r
+ String modelName = "base.en";\r
+ try {\r
+ whisper.initContext(modelName);\r
+ whisper.getDefaultJavaParams(WhisperSamplingStrategy.WHISPER_SAMPLING_GREEDY);\r
+// whisper.getDefaultJavaParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH);\r
+ modelInitialised = true;\r
+ } catch (FileNotFoundException ex) {\r
+ System.out.println("Model " + modelName + " not found");\r
+ }\r
+ }\r
+\r
+ @Test\r
+ void testGetDefaultJavaParams() {\r
+ // When\r
+ whisper.getDefaultJavaParams(WhisperSamplingStrategy.WHISPER_SAMPLING_BEAM_SEARCH);\r
+\r
+ // Then if it doesn't throw we've connected to whisper.cpp\r
+ }\r
+\r
+ @Test\r
+ void testFullTranscribe() throws Exception {\r
+ if (!modelInitialised) {\r
+ System.out.println("Model not initialised, skipping test");\r
+ return;\r
+ }\r
+\r
+ // Given\r
+ File file = new File(System.getProperty("user.dir"), "../../samples/jfk.wav");\r
+ AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(file);\r
+\r
+ byte[] b = new byte[audioInputStream.available()];\r
+ float[] floats = new float[b.length / 2];\r
+\r
+ try {\r
+ audioInputStream.read(b);\r
+\r
+ for (int i = 0, j = 0; i < b.length; i += 2, j++) {\r
+ int intSample = (int) (b[i + 1]) << 8 | (int) (b[i]) & 0xFF;\r
+ floats[j] = intSample / 32767.0f;\r
+ }\r
+\r
+ // When\r
+ String result = whisper.fullTranscribe(/*params,*/ floats);\r
+\r
+ // Then\r
+ System.out.println(result);\r
+ assertEquals("And so my fellow Americans, ask not what your country can do for you, " +\r
+ "ask what you can do for your country.",\r
+ result);\r
+ } finally {\r
+ audioInputStream.close();\r
+ }\r
+ }\r
+}\r
--- /dev/null
+package io.github.ggerganov.whispercpp;\r
+\r
+import static org.junit.jupiter.api.Assertions.*;\r
+\r
+import org.junit.jupiter.api.Test;\r
+\r
+class WhisperJnaLibraryTest {\r
+\r
+ @Test\r
+ void testWhisperPrint_system_info() {\r
+ String systemInfo = WhisperCppJnaLibrary.instance.whisper_print_system_info();\r
+ // eg: "AVX = 1 | AVX2 = 1 | AVX512 = 0 | FMA = 1 | NEON = 0 | ARM_FMA = 0 | F16C = 1 | FP16_VA = 0\r
+ // | WASM_SIMD = 0 | BLAS = 0 | SSE3 = 1 | VSX = 0 | COREML = 0 | "\r
+ System.out.println("System info: " + systemInfo);\r
+ assertTrue(systemInfo.length() > 10);\r
+ }\r
+}\r