package com.whispercppdemo.whisper
+import android.os.Build
+import android.util.Log
import kotlinx.coroutines.*
+import java.io.File
import java.util.concurrent.Executors
+private const val LOG_TAG = "LibWhisper"
+
class WhisperContext private constructor(private var ptr: Long) {
// Meet Whisper C++ constraint: Don't access from more than one thread at a time.
private val scope: CoroutineScope = CoroutineScope(
private class WhisperLib {
companion object {
init {
- System.loadLibrary("whisper")
+ Log.d(LOG_TAG, "Primary ABI: ${Build.SUPPORTED_ABIS[0]}")
+ var loadVfpv4 = false
+ if (isArmEabiV7a()) {
+ // armeabi-v7a needs runtime detection support
+ val cpuInfo = cpuInfo()
+ cpuInfo?.let {
+ Log.d(LOG_TAG, "CPU info: $cpuInfo")
+ if (cpuInfo.contains("vfpv4")) {
+ Log.d(LOG_TAG, "CPU supports vfpv4")
+ loadVfpv4 = true
+ }
+ }
+ }
+
+ if (loadVfpv4) {
+ Log.d(LOG_TAG, "Loading libwhisper_vfpv4.so")
+ System.loadLibrary("whisper_vfpv4")
+ } else {
+ Log.d(LOG_TAG, "Loading libwhisper.so")
+ System.loadLibrary("whisper")
+ }
}
// JNI methods
}
}
+private fun isArmEabiV7a(): Boolean {
+ return Build.SUPPORTED_ABIS[0].equals("armeabi-v7a")
+}
+
+private fun cpuInfo(): String? {
+ return try {
+ File("/proc/cpuinfo").inputStream().bufferedReader().use {
+ it.readText()
+ }
+ } catch (e: Exception) {
+ Log.w(LOG_TAG, "Couldn't read /proc/cpuinfo", e)
+ null
+ }
+}
\ No newline at end of file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
-WHISPER_LIB_DIR := $(LOCAL_PATH)/../../../../../../../
-LOCAL_LDLIBS := -llog
LOCAL_MODULE := libwhisper
+include $(LOCAL_PATH)/Whisper.mk
+include $(BUILD_SHARED_LIBRARY)
-# Make the final output library smaller by only keeping the symbols referenced from the app.
-ifneq ($(APP_OPTIM),debug)
- LOCAL_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
- LOCAL_CFLAGS += -ffunction-sections -fdata-sections
- LOCAL_LDFLAGS += -Wl,--gc-sections
- LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
- LOCAL_LDFLAGS += -flto
-endif
-
-LOCAL_CFLAGS += -DSTDC_HEADERS -std=c11 -I $(WHISPER_LIB_DIR)
-LOCAL_CPPFLAGS += -std=c++11
-LOCAL_SRC_FILES := $(WHISPER_LIB_DIR)/ggml.c \
- $(WHISPER_LIB_DIR)/whisper.cpp \
- $(LOCAL_PATH)/jni.c
-
-include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
+ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ include $(CLEAR_VARS)
+ LOCAL_MODULE := libwhisper_vfpv4
+ include $(LOCAL_PATH)/Whisper.mk
+ # Allow building NEON FMA code.
+ # https://android.googlesource.com/platform/ndk/+/master/sources/android/cpufeatures/cpu-features.h
+ LOCAL_CFLAGS += -mfpu=neon-vfpv4
+ include $(BUILD_SHARED_LIBRARY)
+endif
\ No newline at end of file
--- /dev/null
+WHISPER_LIB_DIR := $(LOCAL_PATH)/../../../../../../../
+LOCAL_LDLIBS := -llog
+
+# Make the final output library smaller by only keeping the symbols referenced from the app.
+ifneq ($(APP_OPTIM),debug)
+ LOCAL_CFLAGS += -O3
+ LOCAL_CFLAGS += -fvisibility=hidden -fvisibility-inlines-hidden
+ LOCAL_CFLAGS += -ffunction-sections -fdata-sections
+ LOCAL_LDFLAGS += -Wl,--gc-sections
+ LOCAL_LDFLAGS += -Wl,--exclude-libs,ALL
+ LOCAL_LDFLAGS += -flto
+endif
+
+LOCAL_CFLAGS += -DSTDC_HEADERS -std=c11 -I $(WHISPER_LIB_DIR)
+LOCAL_CPPFLAGS += -std=c++11
+LOCAL_SRC_FILES := $(WHISPER_LIB_DIR)/ggml.c \
+ $(WHISPER_LIB_DIR)/whisper.cpp \
+ $(LOCAL_PATH)/jni.c
\ No newline at end of file