2023-04-30 17:51:57 +02:00
default : main bench quantize
2023-04-30 11:14:33 +02:00
2022-11-02 07:46:49 +01:00
i f n d e f U N A M E _ S
2022-10-05 19:41:35 +02:00
UNAME_S := $( shell uname -s)
2022-11-02 07:46:49 +01:00
e n d i f
i f n d e f U N A M E _ P
2022-10-05 19:41:35 +02:00
UNAME_P := $( shell uname -p)
2022-11-02 07:46:49 +01:00
e n d i f
i f n d e f U N A M E _ M
2022-10-05 19:41:35 +02:00
UNAME_M := $( shell uname -m)
2022-11-02 07:46:49 +01:00
e n d i f
2022-10-05 19:41:35 +02:00
2023-07-25 18:10:54 +02:00
i f n d e f N V C C _ V E R S I O N
ifeq ( $( call,$( shell which nvcc) ) $( .SHELLSTATUS) ,0)
NVCC_VERSION := $( shell nvcc --version | egrep -o "V[0-9]+.[0-9]+.[0-9]+" | cut -c2-)
endif
e n d i f
2023-09-15 11:18:18 +02:00
CCV := $( shell $( CC) --version | head -n 1)
2023-01-02 12:35:26 +01:00
CXXV := $( shell $( CXX) --version | head -n 1)
2022-10-19 01:01:53 +02:00
# Mac OS + Arm can report x86_64
# ref: https://github.com/ggerganov/whisper.cpp/issues/66#issuecomment-1282546789
i f e q ( $( UNAME_S ) , D a r w i n )
ifneq ( $( UNAME_P) ,arm)
SYSCTL_M := $( shell sysctl -n hw.optional.arm64)
ifeq ( $( SYSCTL_M) ,1)
2022-11-02 17:00:19 +01:00
# UNAME_P := arm
# UNAME_M := arm64
2022-10-19 01:01:53 +02:00
warn := $( warning Your arch is announced as x86_64, but it seems to actually be ARM64. Not fixing that can lead to bad performance. For more info see: https://github.com/ggerganov/whisper.cpp/issues/66\# issuecomment-1282546789)
endif
endif
e n d i f
2022-10-05 19:41:35 +02:00
#
# Compile flags
#
2023-02-28 22:27:54 +01:00
CFLAGS = -I. -O3 -DNDEBUG -std= c11 -fPIC
CXXFLAGS = -I. -I./examples -O3 -DNDEBUG -std= c++11 -fPIC
2022-10-17 20:44:16 +02:00
LDFLAGS =
2022-10-05 19:41:35 +02:00
2023-09-07 11:36:14 +02:00
# clock_gettime came in POSIX.1b (1993)
# CLOCK_MONOTONIC came in POSIX.1-2001 / SUSv3 as optional
# posix_memalign came in POSIX.1-2001 / SUSv3
# M_PI is an XSI extension since POSIX.1-2001 / SUSv3, came in XPG1 (1985)
CFLAGS += -D_XOPEN_SOURCE= 600
CXXFLAGS += -D_XOPEN_SOURCE= 600
# Somehow in OpenBSD whenever POSIX conformance is specified
# some string functions rely on locale_t availability,
# which was introduced in POSIX.1-2008, forcing us to go higher
i f e q ( $( UNAME_S ) , O p e n B S D )
CFLAGS += -U_XOPEN_SOURCE -D_XOPEN_SOURCE= 700
CXXFLAGS += -U_XOPEN_SOURCE -D_XOPEN_SOURCE= 700
e n d i f
# Data types, macros and functions related to controlling CPU affinity
# are available on Linux through GNU extensions in libc
i f e q ( $( UNAME_S ) , L i n u x )
CFLAGS += -D_GNU_SOURCE
CXXFLAGS += -D_GNU_SOURCE
2023-07-02 20:53:52 +02:00
e n d i f
2023-03-22 19:51:42 +01:00
2023-06-28 21:34:50 +02:00
# RLIMIT_MEMLOCK came in BSD, is not specified in POSIX.1,
# and on macOS its availability depends on enabling Darwin extensions
2023-09-07 11:36:14 +02:00
# similarly on DragonFly, enabling BSD extensions is necessary
2023-06-28 21:34:50 +02:00
i f e q ( $( UNAME_S ) , D a r w i n )
CFLAGS += -D_DARWIN_C_SOURCE
CXXFLAGS += -D_DARWIN_C_SOURCE
e n d i f
2023-09-07 11:36:14 +02:00
i f e q ( $( UNAME_S ) , D r a g o n F l y )
CFLAGS += -D__BSD_VISIBLE
CXXFLAGS += -D__BSD_VISIBLE
e n d i f
# alloca is a non-standard interface that is not visible on BSDs when
# POSIX conformance is specified, but not all of them provide a clean way
# to enable it in such cases
i f e q ( $( UNAME_S ) , F r e e B S D )
CFLAGS += -D__BSD_VISIBLE
CXXFLAGS += -D__BSD_VISIBLE
e n d i f
i f e q ( $( UNAME_S ) , N e t B S D )
CFLAGS += -D_NETBSD_SOURCE
CXXFLAGS += -D_NETBSD_SOURCE
e n d i f
i f e q ( $( UNAME_S ) , O p e n B S D )
CFLAGS += -D_BSD_SOURCE
CXXFLAGS += -D_BSD_SOURCE
e n d i f
2023-06-28 21:34:50 +02:00
2022-10-05 19:41:35 +02:00
# OS specific
# TODO: support Windows
2023-08-27 20:38:46 +02:00
i f e q ( $( filter $ ( UNAME_S ) ,Linux Darwin DragonFly FreeBSD NetBSD OpenBSD Haiku ) , $( UNAME_S ) )
2022-12-08 06:34:19 +01:00
CFLAGS += -pthread
CXXFLAGS += -pthread
e n d i f
2022-10-05 19:41:35 +02:00
# Architecture specific
2022-10-08 16:35:55 +02:00
# TODO: probably these flags need to be tweaked on some architectures
2022-10-17 17:09:17 +02:00
# feel free to update the Makefile for your architecture and send a pull request or issue
2023-09-05 13:58:47 +02:00
i f e q ( $( UNAME_M ) , $( filter $ ( UNAME_M ) ,x 86_ 64 i 686 amd 64) )
2022-11-09 01:28:36 +01:00
ifeq ( $( UNAME_S) ,Darwin)
2023-09-06 17:22:21 +02:00
CPUINFO_CMD := sysctl machdep.cpu.features machdep.cpu.leaf7_features
2022-11-29 08:29:34 +01:00
else ifeq ( $( UNAME_S) ,Linux)
2023-08-25 14:20:44 +02:00
CPUINFO_CMD := cat /proc/cpuinfo
2023-08-28 12:28:26 +02:00
else ifneq ( ,$( filter MINGW32_NT% MINGW64_NT%,$( UNAME_S) ) )
CPUINFO_CMD := cat /proc/cpuinfo
2023-09-05 13:58:47 +02:00
else ifneq ( ,$( filter DragonFly FreeBSD,$( UNAME_S) ) )
CPUINFO_CMD := grep Features /var/run/dmesg.boot
2023-08-25 14:20:44 +02:00
else ifeq ( $( UNAME_S) ,Haiku)
CPUINFO_CMD := sysinfo -cpu
endif
2023-09-05 13:58:47 +02:00
ifdef CPUINFO_CMD
AVX_M := $( shell $( CPUINFO_CMD) | grep -iwE 'AVX|AVX1.0' )
ifneq ( ,$( AVX_M) )
CFLAGS += -mavx
CXXFLAGS += -mavx
2022-11-23 12:23:35 +01:00
endif
2023-08-25 14:20:44 +02:00
2023-09-05 13:58:47 +02:00
AVX2_M := $( shell $( CPUINFO_CMD) | grep -iw 'AVX2' )
ifneq ( ,$( AVX2_M) )
CFLAGS += -mavx2
CXXFLAGS += -mavx2
2022-11-23 12:23:35 +01:00
endif
2023-08-25 14:20:44 +02:00
2023-09-05 13:58:47 +02:00
FMA_M := $( shell $( CPUINFO_CMD) | grep -iw 'FMA' )
ifneq ( ,$( FMA_M) )
CFLAGS += -mfma
CXXFLAGS += -mfma
endif
2023-04-14 18:31:51 +02:00
2023-09-05 13:58:47 +02:00
F16C_M := $( shell $( CPUINFO_CMD) | grep -iw 'F16C' )
ifneq ( ,$( F16C_M) )
CFLAGS += -mf16c
CXXFLAGS += -mf16c
2022-12-08 06:34:19 +01:00
endif
2023-08-25 14:20:44 +02:00
2023-09-05 13:58:47 +02:00
SSE3_M := $( shell $( CPUINFO_CMD) | grep -iwE 'PNI|SSE3' )
ifneq ( ,$( SSE3_M) )
CFLAGS += -msse3
CXXFLAGS += -msse3
2023-01-06 17:45:59 +01:00
endif
2023-08-27 20:36:41 +02:00
2023-09-05 13:58:47 +02:00
SSSE3_M := $( shell $( CPUINFO_CMD) | grep -iw 'SSSE3' )
ifneq ( ,$( SSSE3_M) )
CFLAGS += -mssse3
CXXFLAGS += -mssse3
2023-08-27 20:36:41 +02:00
endif
2022-11-09 01:28:36 +01:00
endif
2022-10-05 19:41:35 +02:00
e n d i f
2023-04-29 09:55:24 +02:00
2023-01-23 19:48:10 +01:00
i f n e q ( $( filter ppc 64%,$ ( UNAME_M ) ) , )
2022-12-23 07:19:19 +01:00
POWER9_M := $( shell grep "POWER9" /proc/cpuinfo)
ifneq ( ,$( findstring POWER9,$( POWER9_M) ) )
CFLAGS += -mpower9-vector
endif
2023-01-23 19:48:10 +01:00
# Require c++23's std::byteswap for big-endian support.
ifeq ( $( UNAME_M) ,ppc64)
CXXFLAGS += -std= c++23 -DGGML_BIG_ENDIAN
endif
2022-12-23 07:19:19 +01:00
e n d i f
2023-04-29 09:55:24 +02:00
2022-11-02 17:00:19 +01:00
i f n d e f W H I S P E R _ N O _ A C C E L E R A T E
2022-10-17 20:44:16 +02:00
# Mac M1 - include Accelerate framework
ifeq ( $( UNAME_S) ,Darwin)
CFLAGS += -DGGML_USE_ACCELERATE
LDFLAGS += -framework Accelerate
endif
2022-10-05 19:41:35 +02:00
e n d i f
2023-04-29 09:55:24 +02:00
2023-04-15 12:21:27 +02:00
i f d e f W H I S P E R _ C O R E M L
CXXFLAGS += -DWHISPER_USE_COREML
LDFLAGS += -framework Foundation -framework CoreML
2023-04-29 09:55:24 +02:00
i f d e f W H I S P E R _ C O R E M L _ A L L O W _ F A L L B A C K
CXXFLAGS += -DWHISPER_COREML_ALLOW_FALLBACK
e n d i f
2023-04-15 12:21:27 +02:00
e n d i f
2023-04-29 09:55:24 +02:00
2023-09-15 11:18:18 +02:00
i f n d e f W H I S P E R _ N O _ M E T A L
ifeq ( $( UNAME_S) ,Darwin)
WHISPER_METAL := 1
CXXFLAGS += -DGGML_USE_METAL
LDFLAGS += -framework Foundation -framework Metal -framework MetalKit
endif
e n d i f
2022-11-23 12:23:35 +01:00
i f d e f W H I S P E R _ O P E N B L A S
2023-08-25 18:26:34 +02:00
CFLAGS += -DGGML_USE_OPENBLAS -I/usr/local/include/openblas -I/usr/include/openblas
2022-11-23 12:23:35 +01:00
LDFLAGS += -lopenblas
e n d i f
2023-04-29 09:55:24 +02:00
2023-04-30 11:14:33 +02:00
i f d e f W H I S P E R _ C U B L A S
2023-07-25 18:10:54 +02:00
ifeq ( $( shell expr $( NVCC_VERSION) \> = 11.6) , 1)
CUDA_ARCH_FLAG = native
else
CUDA_ARCH_FLAG = all
endif
2023-06-25 12:59:48 +02:00
CFLAGS += -DGGML_USE_CUBLAS -I/usr/local/cuda/include -I/opt/cuda/include -I$( CUDA_PATH) /targets/$( UNAME_M) -linux/include
CXXFLAGS += -DGGML_USE_CUBLAS -I/usr/local/cuda/include -I/opt/cuda/include -I$( CUDA_PATH) /targets/$( UNAME_M) -linux/include
LDFLAGS += -lcublas -lculibos -lcudart -lcublasLt -lpthread -ldl -lrt -L/usr/local/cuda/lib64 -L/opt/cuda/lib64 -L$( CUDA_PATH) /targets/$( UNAME_M) -linux/lib
2023-04-30 11:14:33 +02:00
WHISPER_OBJ += ggml-cuda.o
NVCC = nvcc
2023-07-25 18:10:54 +02:00
NVCCFLAGS = --forward-unknown-to-host-compiler -arch= $( CUDA_ARCH_FLAG)
2023-04-30 11:14:33 +02:00
ggml-cuda.o : ggml -cuda .cu ggml -cuda .h
$( NVCC) $( NVCCFLAGS) $( CXXFLAGS) -Wno-pedantic -c $< -o $@
e n d i f
2023-08-27 19:03:58 +02:00
i f d e f W H I S P E R _ H I P B L A S
ROCM_PATH ?= /opt/rocm
HIPCC ?= $( ROCM_PATH) /bin/hipcc
GPU_TARGETS ?= $( shell $( ROCM_PATH) /llvm/bin/amdgpu-arch)
CFLAGS += -DGGML_USE_HIPBLAS -DGGML_USE_CUBLAS
CXXFLAGS += -DGGML_USE_HIPBLAS -DGGML_USE_CUBLAS
LDFLAGS += -L$( ROCM_PATH) /lib -Wl,-rpath= $( ROCM_PATH) /lib
LDFLAGS += -lhipblas -lamdhip64 -lrocblas
HIPFLAGS += $( addprefix --offload-arch= ,$( GPU_TARGETS) )
WHISPER_OBJ += ggml-cuda.o
ggml-cuda.o : ggml -cuda .cu ggml -cuda .h
$( HIPCC) $( CXXFLAGS) $( HIPFLAGS) -x hip -c -o $@ $<
e n d i f
2023-05-02 21:50:32 +02:00
i f d e f W H I S P E R _ C L B L A S T
CFLAGS += -DGGML_USE_CLBLAST
2023-07-25 18:12:03 +02:00
CXXFLAGS += -DGGML_USE_CLBLAST
LDFLAGS += -lclblast
ifeq ( $( UNAME_S) ,Darwin)
LDFLAGS += -framework OpenCL
else
LDFLAGS += -lOpenCL
endif
2023-05-02 21:50:32 +02:00
WHISPER_OBJ += ggml-opencl.o
2023-06-25 14:38:12 +02:00
ggml-opencl.o : ggml -opencl .cpp ggml -opencl .h
2023-07-25 18:12:03 +02:00
$( CXX) $( CXXFLAGS) -c $< -o $@
2023-05-02 21:50:32 +02:00
e n d i f
2022-11-23 13:31:05 +01:00
i f d e f W H I S P E R _ G P R O F
2023-01-18 19:31:46 +01:00
CFLAGS += -pg
CXXFLAGS += -pg
2022-11-23 13:31:05 +01:00
e n d i f
2023-04-29 09:55:24 +02:00
2022-10-08 16:35:55 +02:00
i f n e q ( $( filter aarch 64%,$ ( UNAME_M ) ) , )
2023-05-02 20:47:12 +02:00
CFLAGS += -mcpu= native
2023-02-27 20:04:16 +01:00
CXXFLAGS += -mcpu= native
2022-10-08 16:35:55 +02:00
e n d i f
2023-04-29 09:55:24 +02:00
2022-10-08 16:35:55 +02:00
i f n e q ( $( filter armv 6%,$ ( UNAME_M ) ) , )
2023-03-29 22:11:35 +02:00
# 32-bit Raspberry Pi 1, 2, 3
CFLAGS += -mfpu= neon -mfp16-format= ieee -mno-unaligned-access
2022-10-05 19:41:35 +02:00
e n d i f
2023-04-29 09:55:24 +02:00
2022-10-05 20:34:41 +02:00
i f n e q ( $( filter armv 7%,$ ( UNAME_M ) ) , )
2023-03-29 22:11:35 +02:00
# 32-bit ARM, for example on Armbian or possibly raspbian
2023-05-02 20:47:12 +02:00
#CFLAGS += -mfpu=neon -mfp16-format=ieee -funsafe-math-optimizations -mno-unaligned-access
#CXXFLAGS += -mfpu=neon -mfp16-format=ieee -funsafe-math-optimizations -mno-unaligned-access
2023-04-13 17:53:44 +02:00
2023-05-02 20:47:12 +02:00
# 64-bit ARM on 32-bit OS, use these (TODO: auto-detect 64-bit)
CFLAGS += -mfpu= neon-fp-armv8 -mfp16-format= ieee -funsafe-math-optimizations -mno-unaligned-access
CXXFLAGS += -mfpu= neon-fp-armv8 -mfp16-format= ieee -funsafe-math-optimizations -mno-unaligned-access
2022-10-05 20:34:41 +02:00
e n d i f
2023-04-29 09:55:24 +02:00
2022-10-05 20:34:41 +02:00
i f n e q ( $( filter armv 8%,$ ( UNAME_M ) ) , )
# Raspberry Pi 4
2023-05-02 20:47:12 +02:00
CFLAGS += -mfpu= neon-fp-armv8 -mfp16-format= ieee -funsafe-math-optimizations -mno-unaligned-access
CXXFLAGS += -mfpu= neon-fp-armv8 -mfp16-format= ieee -funsafe-math-optimizations -mno-unaligned-access
2022-10-05 19:41:35 +02:00
e n d i f
2023-01-02 12:35:26 +01:00
#
# Print build information
#
$(info I whisper.cpp build info : )
$(info I UNAME_S : $( UNAME_S ) )
$(info I UNAME_P : $( UNAME_P ) )
$(info I UNAME_M : $( UNAME_M ) )
$(info I CFLAGS : $( CFLAGS ) )
$(info I CXXFLAGS : $( CXXFLAGS ) )
$(info I LDFLAGS : $( LDFLAGS ) )
2023-01-05 20:35:04 +01:00
$(info I CC : $( CCV ) )
$(info I CXX : $( CXXV ) )
2023-01-02 12:35:26 +01:00
$( info )
2022-10-05 19:41:35 +02:00
#
2022-11-13 08:08:33 +01:00
# Build library
2022-10-05 19:41:35 +02:00
#
2022-10-02 16:55:45 +02:00
2023-04-30 11:14:33 +02:00
ggml.o : ggml .c ggml .h ggml -cuda .h
$( CC) $( CFLAGS) -c $< -o $@
2022-09-25 20:23:15 +02:00
2023-09-15 11:18:18 +02:00
ggml-alloc.o : ggml -alloc .c ggml .h ggml -alloc .h
$( CC) $( CFLAGS) -c $< -o $@
WHISPER_OBJ += ggml-alloc.o
2023-04-30 11:14:33 +02:00
whisper.o : whisper .cpp whisper .h ggml .h ggml -cuda .h
$( CXX) $( CXXFLAGS) -c $< -o $@
2022-10-04 19:35:01 +02:00
2023-04-15 12:21:27 +02:00
i f n d e f W H I S P E R _ C O R E M L
2023-04-30 11:14:33 +02:00
WHISPER_OBJ += whisper.o
2023-04-15 12:21:27 +02:00
e l s e
whisper-encoder.o : coreml /whisper -encoder .mm coreml /whisper -encoder .h
2023-05-14 08:47:02 +02:00
$( CXX) -O3 -I . -fobjc-arc -c coreml/whisper-encoder.mm -o whisper-encoder.o
2023-04-15 12:21:27 +02:00
whisper-encoder-impl.o : coreml /whisper -encoder -impl .m coreml /whisper -encoder -impl .h
$( CXX) -O3 -I . -fobjc-arc -c coreml/whisper-encoder-impl.m -o whisper-encoder-impl.o
2023-04-30 11:14:33 +02:00
WHISPER_OBJ += whisper.o whisper-encoder.o whisper-encoder-impl.o
2023-04-15 12:21:27 +02:00
e n d i f
2023-09-15 11:18:18 +02:00
i f d e f W H I S P E R _ M E T A L
ggml-metal.o : ggml -metal .m ggml -metal .h
$( CC) $( CFLAGS) -c $< -o $@
WHISPER_OBJ += ggml-metal.o
e n d i f
2023-04-15 12:21:27 +02:00
libwhisper.a : ggml .o $( WHISPER_OBJ )
$( AR) rcs libwhisper.a ggml.o $( WHISPER_OBJ)
2022-10-10 03:16:42 +02:00
2023-04-15 12:21:27 +02:00
libwhisper.so : ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) -shared -o libwhisper.so ggml.o $( WHISPER_OBJ) $( LDFLAGS)
2022-11-13 08:08:33 +01:00
2022-09-25 20:23:15 +02:00
clean :
examples : vim plugin and LSP server (#1144)
* Initial proof of concept Vim plugin
At present, this is likely only slightly better than feature parity with
the existing whisper.nvim
Known issues:
Trailing whitespace
Up to an existing length(5 seconds) of speech may be processed when
listening is enabled
CPU cycles are spent processing speech even when not listening.
Fixing these issues is likely dependent upon future efforts to create a
dedicated library instead of wrapping examples/stream
* Support $WHISPER_CPP_HOME environment variable
A minor misunderstanding of the whisper.nvim implementation resulted in
a plugin that was functional, but not a drop in replacement as it should
be now.
* Initial progress on LSP implementation
Libcall is nonviable because the library is immediately freed after a
call is made. Further investigation has shown Language Server Protocol as
a promising alternative that both simplifies the required logic on the
vimscript side and increases the ease with which plugins for other
editors could be made in the future. This is a very large undertaking
and my progress has slowed substantially.
Work is far from being in a usable state, but I wish to keep track of
major refactors for organizational purposes.
* Rewrite audio windowing of guided transcription
One of the defining goals of this venture is allowing consecutive
commands to be rattled off without the existing deadzones of the current
implementation.
* Add unguided_transcription. Cleanup.
The unguided transcription implantation heavily borrows from existing
example implementations and the guided_transcription logic.
A high level pass was done to check that method arguments are accurate
to what inputs are actually required.
A first attempt at cancellation support was added for record keeping,
but will be deleted in a future commit.
* Fix compilation.
Resolves a large number of compilation errors.
No testing has been done yet for execution errors.
Update Makefile and .gitignore
* Functional unguided_transcription
* Functional guided_transcription
Fix commandset_list being passed by value
Properly register the first token of a multitoken command
* Minor changes before time fix
I've apparently made an awfully major mistake in thinking that unix time
was in milliseconds and will be changing all timekeeping code to use
standardized methods.
In preparation for this is a number of minor bugfixes.
Output is manually flushed.
An echo method has been added.
registerCommandset now wraps the returned index
* Swap timekeeping to use std::chrono
* Add work in progress lsp backed whisper.vim plugin
Current progress blockers are
Adding modality awareness to the command processing
(specifically, motion prompting)
Improving the VAD to be a little more responsive
(testing start of activity)
* Reworked vim plugin command loop
* Fix change inside
Multiple bug fixes that, crucially, bring the plugin to the point where a
demonstration video is possible
Add better echo messaging so whisper_log isn't required
Add loading complete message as indicator when listening has started
Insert/append are actually included in command sets
Some more heavy handed corrections to prevent a double exit when leaving
insert mode
As a somewhat hacky fix, the very first space is removed when inserting.
This cleans up most use cases, but leaves me unsatisfied with the few
cases it would be desired.
* Forcibly set commandset_index to 0 after subinsert
Also remove unnecessary ! to use builtin vim command
* Fix upper
A minor scope mistake was causing upper'd inputs to be eaten.
This was fixed and echoing was slightly improved for clarity.
* Fix formatting
Corrects indentation to 4 spaces as project standard
Slightly better error support for malformed json input
* Remove obsolete vim plugin
* Add json.hpp library
The same library that is used for the llama.cpp server
* Minor cleanups
add lsp to the make clean directive.
remove a redundant params definition.
reorder whisper.vim logging for subtranscriptions
Corrections to unlets (variables of argument scope appear immutable)
* Fix indentation. Fallback for subTranscription
Indentation has been changed to 4 spaces.
Unit testing has been set up, I'm opting not to include it in the
repository for now.
It however, has revealed a bug in the state logic where a
subtranscription can be initiated without having a saved command
When this occurs, append is added as a fallback
* Move audio polling logic to a subfunction
While work on the improved vad will continue, It's grown to be a little
out of scope. Instead, a future commit will perform multiple detection
passes at substretches of audio when a backlog of audio exists.
To facilitate this, and prevent code duplication, the vad code has been
moved into a subfunction shared by both the unguided and guided
transcription functions.
* Test for voice over subchunks if backlog > 1s
As the existing VAD implementation only checks for a falling edge at the
end of an audio chunk. It fails to detect voice in cases where the
recorded voice is only at the beginning of the audio.
To ameliorate this, when the timestamp would cause analysis of audio
over a second in length, it is split into 1 second length subchunks
which are individually tested.
Results are promising, but there seems to be a remaining bug with
unguided transcription likely related to saving context
* Limit the maximum length of audio input.
This existing VAD implementation only detects falling edges, which
means any gap in the users speaking is processed for transcription.
This simply establishes a constant maximum length depending on the type
of transcription. Uguided gets a generous 10 seconds and guided, 2.
While quick testing showed that commands are generally around a half a
second to a second, limiting commands to an even second resulted in
extreme degradation of quality. (Seemingly always the same output for a
given commandset)
* Unguided timestamp tracking, cleanup
Unguided transcriptions where not setup to allow for passing of
timestamp data forward, but have been corrected.
No_context is now always set to false. While conceptually desirable for
the quality of guided transcription, It was seemingly responsible for
prior command inputs ghosting in unguided transcription.
Save and Run are now tracked by command number instead of command text.
While command_text was provided for convenience, I wish to keep command
index authoritative. This gives greater consistency and potentially
allows for end users to rename or even translate the spoken versions of
these commands
* By default, maintain mode.
Previously, mode was reset to 0 unless otherwise set.
In addition to causing some edge cases, this was didn't mesh well with
the existing approach to visual mode.
With this change, initial tests indicate visual mode is functional.
* Add undo breaks before subtranscriptions
Subtranscriptions use undo as a hack to allow for partial responses to
be displayed. However, scripts don't cause an undo break mid execution
unless specifically instructed to. This meant that multiple
unguided transcriptions from a single session would cause a latter to
undo a former.
This is now fixed and undo should be reasonably usable as a command.
* Append instead of insert for new undo sequence
When entering and leavening insert mode with `i`, the cursor shifts one
column to the left. This is remedied by using append instead of insert
for setting these breaks in the undo sequence
`-` was also added to the pronunciation dictionary to be pronounced as
minus as it was causing a particularly high failure rate.
* Move undo sequence breaks to command execution
Previously, undo sequence breaks were triggered when there was a command
that caused a move to insert mode. This caused commands that changed
state (like delete or paste) to be bundled together with into the last
command that caused text to be entered.
* Fix repeat. Add space, carrot, dollar commands
Repeat (.) wasn't being tracked properly just like undo and is being
manually tracked now.
While efforts have been made to properly handle spaces, it was
particularly finicky to add a single space when one is needed. A
special 'space' command has been added to insert a single space and move
the cursor after it.
Carrot and Dollar commands have been added for start of line and end of
line respectively. These are both simple to implement, and just a
matter of defining a pronunciation.
* Return error on duplicate in commandset
Not every command in the commandset tokenizes to a single token.
Because of this, it's possible for that two commands could resolve to
the same single token after subsequent tokens are discarded.
This commit adds a simple check for duplicates when a commandset is
registered and returns an error if so.
Additional code will be required later on the vim side to actually
process this error.
* Add support for user-defined commands
This adds a user definable dictionary from spoken keys to strings or
funcrefs. All keys are added to the commandlist and when spoken, trigger
the corresponding function.
Like "save" and "run", these user commands are only available when the
command buffer is empty.
* Add readme, update cmake
* Add area commandset. Refactor spoken_dict
Area commands (inside word, around sentence...) have been given a
commandset as considered earlier.
Verbose definitions for spoken_dict entries now use dicts instead of
lists. This shortens the definition for most keys that require it and
scales better with the addition of further commandsets
* Add mark, jump. Fix change under visual.
Mark (m) and jump (') have been added.
When a visual selection was executed upon a command that initiated a
subtranscription (change) the area of the visual selection is not
properly tracked which causes the attempt to stream in partial response
to fail. This is solved by disabling partial transcriptions from being
streamed when a subtranscription is started while in visual mode.
* Accommodate ignorecase. Fix change.
From testing on older different versions of vim, the test for
distinguishing an 'R' replace all from an 'r' replace could fail if
ignorecase was set. The comparison has been changed to explicitly
require case matching
Change detection has been moved to the execution section as it was missing the
change+motion case.
* Support registers. Fix README typo
There's no logic to prevent doubled register entry, but the functional
result is equivalent to if the same key order was typed into vim.
A minor typo in the readme. I've mismemorized the mnemonic for 't' as 'to'
instead of till., but 'to' can't be used as it's a homophone with '2'.
While there was no mistake in the actual logic, it was misleading to use
'to' in the readme.
2023-08-27 20:35:06 +02:00
rm -f *.o main stream command talk talk-llama bench quantize lsp libwhisper.a libwhisper.so
2022-09-25 20:23:15 +02:00
2022-10-05 19:41:35 +02:00
#
# Examples
#
CC_SDL = ` sdl2-config --cflags --libs`
2023-04-30 17:51:57 +02:00
SRC_COMMON = examples/common.cpp examples/common-ggml.cpp
2023-02-15 18:28:10 +01:00
SRC_COMMON_SDL = examples/common-sdl.cpp
2023-04-15 12:21:27 +02:00
main : examples /main /main .cpp $( SRC_COMMON ) ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/main/main.cpp $( SRC_COMMON) ggml.o $( WHISPER_OBJ) -o main $( LDFLAGS)
2022-11-13 08:08:33 +01:00
./main -h
2023-04-15 12:21:27 +02:00
bench : examples /bench /bench .cpp ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/bench/bench.cpp ggml.o $( WHISPER_OBJ) -o bench $( LDFLAGS)
2023-03-27 20:00:32 +02:00
2023-04-30 17:51:57 +02:00
quantize : examples /quantize /quantize .cpp ggml .o $( WHISPER_OBJ ) $( SRC_COMMON )
$( CXX) $( CXXFLAGS) examples/quantize/quantize.cpp $( SRC_COMMON) ggml.o $( WHISPER_OBJ) -o quantize $( LDFLAGS)
2023-04-15 12:21:27 +02:00
stream : examples /stream /stream .cpp $( SRC_COMMON ) $( SRC_COMMON_SDL ) ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/stream/stream.cpp $( SRC_COMMON) $( SRC_COMMON_SDL) ggml.o $( WHISPER_OBJ) -o stream $( CC_SDL) $( LDFLAGS)
2022-10-25 18:13:08 +02:00
2023-04-15 12:21:27 +02:00
command : examples /command /command .cpp $( SRC_COMMON ) $( SRC_COMMON_SDL ) ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/command/command.cpp $( SRC_COMMON) $( SRC_COMMON_SDL) ggml.o $( WHISPER_OBJ) -o command $( CC_SDL) $( LDFLAGS)
2022-11-25 18:06:56 +01:00
examples : vim plugin and LSP server (#1144)
* Initial proof of concept Vim plugin
At present, this is likely only slightly better than feature parity with
the existing whisper.nvim
Known issues:
Trailing whitespace
Up to an existing length(5 seconds) of speech may be processed when
listening is enabled
CPU cycles are spent processing speech even when not listening.
Fixing these issues is likely dependent upon future efforts to create a
dedicated library instead of wrapping examples/stream
* Support $WHISPER_CPP_HOME environment variable
A minor misunderstanding of the whisper.nvim implementation resulted in
a plugin that was functional, but not a drop in replacement as it should
be now.
* Initial progress on LSP implementation
Libcall is nonviable because the library is immediately freed after a
call is made. Further investigation has shown Language Server Protocol as
a promising alternative that both simplifies the required logic on the
vimscript side and increases the ease with which plugins for other
editors could be made in the future. This is a very large undertaking
and my progress has slowed substantially.
Work is far from being in a usable state, but I wish to keep track of
major refactors for organizational purposes.
* Rewrite audio windowing of guided transcription
One of the defining goals of this venture is allowing consecutive
commands to be rattled off without the existing deadzones of the current
implementation.
* Add unguided_transcription. Cleanup.
The unguided transcription implantation heavily borrows from existing
example implementations and the guided_transcription logic.
A high level pass was done to check that method arguments are accurate
to what inputs are actually required.
A first attempt at cancellation support was added for record keeping,
but will be deleted in a future commit.
* Fix compilation.
Resolves a large number of compilation errors.
No testing has been done yet for execution errors.
Update Makefile and .gitignore
* Functional unguided_transcription
* Functional guided_transcription
Fix commandset_list being passed by value
Properly register the first token of a multitoken command
* Minor changes before time fix
I've apparently made an awfully major mistake in thinking that unix time
was in milliseconds and will be changing all timekeeping code to use
standardized methods.
In preparation for this is a number of minor bugfixes.
Output is manually flushed.
An echo method has been added.
registerCommandset now wraps the returned index
* Swap timekeeping to use std::chrono
* Add work in progress lsp backed whisper.vim plugin
Current progress blockers are
Adding modality awareness to the command processing
(specifically, motion prompting)
Improving the VAD to be a little more responsive
(testing start of activity)
* Reworked vim plugin command loop
* Fix change inside
Multiple bug fixes that, crucially, bring the plugin to the point where a
demonstration video is possible
Add better echo messaging so whisper_log isn't required
Add loading complete message as indicator when listening has started
Insert/append are actually included in command sets
Some more heavy handed corrections to prevent a double exit when leaving
insert mode
As a somewhat hacky fix, the very first space is removed when inserting.
This cleans up most use cases, but leaves me unsatisfied with the few
cases it would be desired.
* Forcibly set commandset_index to 0 after subinsert
Also remove unnecessary ! to use builtin vim command
* Fix upper
A minor scope mistake was causing upper'd inputs to be eaten.
This was fixed and echoing was slightly improved for clarity.
* Fix formatting
Corrects indentation to 4 spaces as project standard
Slightly better error support for malformed json input
* Remove obsolete vim plugin
* Add json.hpp library
The same library that is used for the llama.cpp server
* Minor cleanups
add lsp to the make clean directive.
remove a redundant params definition.
reorder whisper.vim logging for subtranscriptions
Corrections to unlets (variables of argument scope appear immutable)
* Fix indentation. Fallback for subTranscription
Indentation has been changed to 4 spaces.
Unit testing has been set up, I'm opting not to include it in the
repository for now.
It however, has revealed a bug in the state logic where a
subtranscription can be initiated without having a saved command
When this occurs, append is added as a fallback
* Move audio polling logic to a subfunction
While work on the improved vad will continue, It's grown to be a little
out of scope. Instead, a future commit will perform multiple detection
passes at substretches of audio when a backlog of audio exists.
To facilitate this, and prevent code duplication, the vad code has been
moved into a subfunction shared by both the unguided and guided
transcription functions.
* Test for voice over subchunks if backlog > 1s
As the existing VAD implementation only checks for a falling edge at the
end of an audio chunk. It fails to detect voice in cases where the
recorded voice is only at the beginning of the audio.
To ameliorate this, when the timestamp would cause analysis of audio
over a second in length, it is split into 1 second length subchunks
which are individually tested.
Results are promising, but there seems to be a remaining bug with
unguided transcription likely related to saving context
* Limit the maximum length of audio input.
This existing VAD implementation only detects falling edges, which
means any gap in the users speaking is processed for transcription.
This simply establishes a constant maximum length depending on the type
of transcription. Uguided gets a generous 10 seconds and guided, 2.
While quick testing showed that commands are generally around a half a
second to a second, limiting commands to an even second resulted in
extreme degradation of quality. (Seemingly always the same output for a
given commandset)
* Unguided timestamp tracking, cleanup
Unguided transcriptions where not setup to allow for passing of
timestamp data forward, but have been corrected.
No_context is now always set to false. While conceptually desirable for
the quality of guided transcription, It was seemingly responsible for
prior command inputs ghosting in unguided transcription.
Save and Run are now tracked by command number instead of command text.
While command_text was provided for convenience, I wish to keep command
index authoritative. This gives greater consistency and potentially
allows for end users to rename or even translate the spoken versions of
these commands
* By default, maintain mode.
Previously, mode was reset to 0 unless otherwise set.
In addition to causing some edge cases, this was didn't mesh well with
the existing approach to visual mode.
With this change, initial tests indicate visual mode is functional.
* Add undo breaks before subtranscriptions
Subtranscriptions use undo as a hack to allow for partial responses to
be displayed. However, scripts don't cause an undo break mid execution
unless specifically instructed to. This meant that multiple
unguided transcriptions from a single session would cause a latter to
undo a former.
This is now fixed and undo should be reasonably usable as a command.
* Append instead of insert for new undo sequence
When entering and leavening insert mode with `i`, the cursor shifts one
column to the left. This is remedied by using append instead of insert
for setting these breaks in the undo sequence
`-` was also added to the pronunciation dictionary to be pronounced as
minus as it was causing a particularly high failure rate.
* Move undo sequence breaks to command execution
Previously, undo sequence breaks were triggered when there was a command
that caused a move to insert mode. This caused commands that changed
state (like delete or paste) to be bundled together with into the last
command that caused text to be entered.
* Fix repeat. Add space, carrot, dollar commands
Repeat (.) wasn't being tracked properly just like undo and is being
manually tracked now.
While efforts have been made to properly handle spaces, it was
particularly finicky to add a single space when one is needed. A
special 'space' command has been added to insert a single space and move
the cursor after it.
Carrot and Dollar commands have been added for start of line and end of
line respectively. These are both simple to implement, and just a
matter of defining a pronunciation.
* Return error on duplicate in commandset
Not every command in the commandset tokenizes to a single token.
Because of this, it's possible for that two commands could resolve to
the same single token after subsequent tokens are discarded.
This commit adds a simple check for duplicates when a commandset is
registered and returns an error if so.
Additional code will be required later on the vim side to actually
process this error.
* Add support for user-defined commands
This adds a user definable dictionary from spoken keys to strings or
funcrefs. All keys are added to the commandlist and when spoken, trigger
the corresponding function.
Like "save" and "run", these user commands are only available when the
command buffer is empty.
* Add readme, update cmake
* Add area commandset. Refactor spoken_dict
Area commands (inside word, around sentence...) have been given a
commandset as considered earlier.
Verbose definitions for spoken_dict entries now use dicts instead of
lists. This shortens the definition for most keys that require it and
scales better with the addition of further commandsets
* Add mark, jump. Fix change under visual.
Mark (m) and jump (') have been added.
When a visual selection was executed upon a command that initiated a
subtranscription (change) the area of the visual selection is not
properly tracked which causes the attempt to stream in partial response
to fail. This is solved by disabling partial transcriptions from being
streamed when a subtranscription is started while in visual mode.
* Accommodate ignorecase. Fix change.
From testing on older different versions of vim, the test for
distinguishing an 'R' replace all from an 'r' replace could fail if
ignorecase was set. The comparison has been changed to explicitly
require case matching
Change detection has been moved to the execution section as it was missing the
change+motion case.
* Support registers. Fix README typo
There's no logic to prevent doubled register entry, but the functional
result is equivalent to if the same key order was typed into vim.
A minor typo in the readme. I've mismemorized the mnemonic for 't' as 'to'
instead of till., but 'to' can't be used as it's a homophone with '2'.
While there was no mistake in the actual logic, it was misleading to use
'to' in the readme.
2023-08-27 20:35:06 +02:00
lsp : examples /lsp /lsp .cpp $( SRC_COMMON ) $( SRC_COMMON_SDL ) ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/lsp/lsp.cpp $( SRC_COMMON) $( SRC_COMMON_SDL) ggml.o $( WHISPER_OBJ) -o lsp $( CC_SDL) $( LDFLAGS)
2023-04-15 12:21:27 +02:00
talk : examples /talk /talk .cpp examples /talk /gpt -2.cpp $( SRC_COMMON ) $( SRC_COMMON_SDL ) ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/talk/talk.cpp examples/talk/gpt-2.cpp $( SRC_COMMON) $( SRC_COMMON_SDL) ggml.o $( WHISPER_OBJ) -o talk $( CC_SDL) $( LDFLAGS)
2022-12-09 19:38:10 +01:00
2023-04-15 12:21:27 +02:00
talk-llama : examples /talk -llama /talk -llama .cpp examples /talk -llama /llama .cpp $( SRC_COMMON ) $( SRC_COMMON_SDL ) ggml .o $( WHISPER_OBJ )
$( CXX) $( CXXFLAGS) examples/talk-llama/talk-llama.cpp examples/talk-llama/llama.cpp $( SRC_COMMON) $( SRC_COMMON_SDL) ggml.o $( WHISPER_OBJ) -o talk-llama $( CC_SDL) $( LDFLAGS)
2022-10-05 19:41:35 +02:00
#
# Audio samples
#
2022-09-26 08:36:51 +02:00
# download a few audio samples into folder "./samples":
2022-09-25 20:23:15 +02:00
.PHONY : samples
samples :
@echo "Downloading samples..."
2022-09-25 21:35:26 +02:00
@mkdir -p samples
2022-09-25 20:23:15 +02:00
@wget --quiet --show-progress -O samples/gb0.ogg https://upload.wikimedia.org/wikipedia/commons/2/22/George_W._Bush%27s_weekly_radio_address_%28November_1%2C_2008%29.oga
@wget --quiet --show-progress -O samples/gb1.ogg https://upload.wikimedia.org/wikipedia/commons/1/1f/George_W_Bush_Columbia_FINAL.ogg
@wget --quiet --show-progress -O samples/hp0.ogg https://upload.wikimedia.org/wikipedia/en/d/d4/En.henryfphillips.ogg
2022-09-30 18:33:09 +02:00
@wget --quiet --show-progress -O samples/mm1.wav https://cdn.openai.com/whisper/draft-20220913a/micro-machines.wav
2023-07-04 08:45:00 +02:00
@wget --quiet --show-progress -O samples/a13.mp3 https://upload.wikimedia.org/wikipedia/commons/transcoded/6/6f/Apollo13-wehaveaproblem.ogg/Apollo13-wehaveaproblem.ogg.mp3
2023-07-25 18:00:45 +02:00
@wget --quiet --show-progress -O samples/diffusion2023-07-03.flac https://archive.org/download/diffusion2023-07-03/diffusion2023-07-03.flac
2022-09-25 20:23:15 +02:00
@echo "Converting to 16-bit WAV ..."
@ffmpeg -loglevel -0 -y -i samples/gb0.ogg -ar 16000 -ac 1 -c:a pcm_s16le samples/gb0.wav
@ffmpeg -loglevel -0 -y -i samples/gb1.ogg -ar 16000 -ac 1 -c:a pcm_s16le samples/gb1.wav
@ffmpeg -loglevel -0 -y -i samples/hp0.ogg -ar 16000 -ac 1 -c:a pcm_s16le samples/hp0.wav
2023-07-04 08:45:00 +02:00
@rm samples/*.ogg
2022-09-30 18:33:09 +02:00
@ffmpeg -loglevel -0 -y -i samples/mm1.wav -ar 16000 -ac 1 -c:a pcm_s16le samples/mm0.wav
@rm samples/mm1.wav
2023-07-04 08:45:00 +02:00
@ffmpeg -loglevel -0 -y -i samples/a13.mp3 -ar 16000 -ac 1 -c:a pcm_s16le -ss 00:00:00 -to 00:00:30 samples/a13.wav
@rm samples/a13.mp3
2023-07-25 18:00:45 +02:00
@ffmpeg -loglevel -0 -y -i samples/diffusion2023-07-03.flac -ar 16000 -ac 1 -c:a pcm_s16le samples/diffusion2023-07-03.wav
@rm samples/diffusion2023-07-03.flac
2022-09-25 20:23:15 +02:00
2022-10-05 19:41:35 +02:00
#
# Models
#
2022-09-25 20:23:15 +02:00
2022-09-26 08:36:51 +02:00
# if not already downloaded, the following targets download the specified model and
# runs it on all samples in the folder "./samples":
2022-09-25 20:23:15 +02:00
2022-09-26 08:36:51 +02:00
.PHONY : tiny .en
2022-09-28 19:46:05 +02:00
.PHONY : tiny
2022-09-26 08:36:51 +02:00
.PHONY : base .en
2022-09-28 19:46:05 +02:00
.PHONY : base
2022-09-25 20:23:15 +02:00
.PHONY : small .en
2022-09-28 19:46:05 +02:00
.PHONY : small
.PHONY : medium .en
.PHONY : medium
2022-12-06 17:48:57 +01:00
.PHONY : large -v 1
2022-09-28 19:46:05 +02:00
.PHONY : large
2022-09-25 20:23:15 +02:00
2022-12-06 17:48:57 +01:00
tiny.en tiny base.en base small.en small medium.en medium large-v1 large : main
2022-10-25 18:13:08 +02:00
bash ./models/download-ggml-model.sh $@
2022-09-25 21:35:26 +02:00
@echo ""
2022-09-25 20:23:15 +02:00
@echo "==============================================="
2022-09-26 08:36:51 +02:00
@echo " Running $@ on all samples in ./samples ... "
2022-09-25 20:23:15 +02:00
@echo "==============================================="
@echo ""
@for f in samples/*.wav; do \
echo "----------------------------------------------" ; \
2022-11-25 04:24:08 +01:00
echo " [+] Running $@ on $$ f ... (run 'ffplay $$ f' to listen) " ; \
2022-09-25 20:23:15 +02:00
echo "----------------------------------------------" ; \
echo "" ; \
2022-09-26 08:36:51 +02:00
./main -m models/ggml-$@ .bin -f $$ f ; \
2022-09-25 20:23:15 +02:00
echo "" ; \
done
2022-11-28 21:44:01 +01:00
#
# Tests
#
.PHONY : tests
tests :
2023-07-25 18:09:38 +02:00
bash ./tests/run-tests.sh $( word 2, $( MAKECMDGOALS) )