Skip to content

Commit 3cd6731

Browse files
committed
make it windows compatible, sigh
1 parent ce63f9e commit 3cd6731

14 files changed

+132
-56
lines changed

CMakeLists.txt

100644100755
+98-26
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@ cmake_minimum_required(VERSION 3.1...3.14)
22

33
project(Lowwi VERSION 3.11.5 LANGUAGES CXX)
44

5-
set(MAIN_PROJECT OFF)
6-
7-
85
# Optionally build the examples
96
option(CLFML_LOWWI_BUILD_EXAMPLE_PROJECTS "Build example projects" ON)
107

8+
9+
# Internal flag used to determine whether or not to build examples automatically
10+
set(CLFML_LOWWI_MAIN_PROJECT OFF)
11+
1112
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
1213
set(CMAKE_CXX_STANDARD 17)
13-
set(MAIN_PROJECT ON)
14+
set(CLFML_LOWWI_MAIN_PROJECT ON)
1415
else()
1516
set(CLFML_LOWWI_BUILD_EXAMPLE_PROJECTS OFF)
1617
endif()
@@ -24,58 +25,129 @@ if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0")
2425
cmake_policy(SET CMP0135 NEW)
2526
endif()
2627

28+
# Create the Lowi Library
2729
add_library(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/src/lowwi.cpp
2830
${CMAKE_CURRENT_LIST_DIR}/src/lowwi_melspectrogram.cpp
2931
${CMAKE_CURRENT_LIST_DIR}/src/lowwi_embedding.cpp
3032
${CMAKE_CURRENT_LIST_DIR}/src/lowwi_wakeword.cpp)
33+
# Create alias CLFML::Lowi
3134
add_library(CLFML::${PROJECT_NAME} ALIAS ${PROJECT_NAME})
3235

3336
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src)
3437

35-
target_link_libraries(${PROJECT_NAME})
3638

39+
# Check if onnxruntime target exists?
3740
if (TARGET onnxruntime)
3841
target_link_libraries(${PROJECT_NAME} onnxruntime)
3942
else()
40-
set(ONNX_PATH ${CMAKE_CURRENT_LIST_DIR}/lib/x64)
43+
# Fetch onnx manually
4144
include(FetchContent)
42-
FetchContent_Declare(
43-
onnxruntime
44-
URL https://github.com/microsoft/onnxruntime/releases/download/v1.18.0/onnxruntime-linux-x64-1.18.0.tgz
45-
SOURCE_DIR ${ONNX_PATH}
46-
)
47-
FetchContent_MakeAvailable(onnxruntime)
48-
add_library(onnxruntime SHARED IMPORTED )
49-
# You can define two import-locations: one for debug and one for release.
50-
set_target_properties(onnxruntime PROPERTIES IMPORTED_LOCATION ${ONNX_PATH}/lib/libonnxruntime.so)
51-
target_include_directories(onnxruntime INTERFACE ${ONNX_PATH}/include)
52-
target_link_libraries(${PROJECT_NAME} onnxruntime)
53-
endif()
54-
55-
set(LOWWI_MODEL_DIR ${CMAKE_CURRENT_LIST_DIR}/models)
56-
target_compile_definitions(${PROJECT_NAME} PUBLIC -DCLFML_LOWWI_MODEL_DIR="${LOWWI_MODEL_DIR}")
45+
46+
set(ONNXRUNTIME_ROOTDIR ${CMAKE_CURRENT_LIST_DIR}/lib/x64)
47+
# Check if we are compiling with MSVC for Windows
48+
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
49+
# Get onnx release for windows x64 from Github page
50+
FetchContent_Declare(
51+
onnxruntime
52+
URL https://github.com/microsoft/onnxruntime/releases/download/v1.20.1/onnxruntime-win-x64-1.20.1.zip
53+
SOURCE_DIR ${ONNXRUNTIME_ROOTDIR}
54+
)
55+
FetchContent_MakeAvailable(onnxruntime)
56+
57+
# Add ONNX includes to include path
58+
target_include_directories(${PROJECT_NAME} PUBLIC ${ONNXRUNTIME_ROOTDIR}/include)
59+
60+
# Link ONNX directories, which contain the .lib files for ONNX
61+
link_directories(${PROJECT_NAME} ${ONNXRUNTIME_ROOTDIR}/lib)
62+
63+
# Link the specific .lib file libraries to LOWWI
64+
target_link_libraries(${PROJECT_NAME} onnxruntime onnxruntime_providers_shared)
65+
66+
# Get list of all dll files in the onnxruntime lib directory
67+
file(GLOB onnx_dll_files ${ONNXRUNTIME_ROOTDIR}/lib/*.dll)
68+
69+
# Copy the DLL files to the executable dir.
70+
add_custom_target(copy_onnxruntime_dll ALL
71+
COMMAND ${CMAKE_COMMAND} -E copy ${onnx_dll_files} $<TARGET_FILE_DIR:${PROJECT_NAME}>
72+
COMMENT "Copying ONNX dll files to build folder"
73+
)
74+
else()
75+
# Get Linux x64 onnx release from GitHub
76+
FetchContent_Declare(
77+
onnxruntime
78+
URL https://github.com/microsoft/onnxruntime/releases/download/v1.18.0/onnxruntime-linux-x64-1.18.0.tgz
79+
SOURCE_DIR ${ONNX_PATH}
80+
)
81+
FetchContent_MakeAvailable(onnxruntime)
82+
# Add ONNX library include files to include path
83+
target_include_directories(${PROJECT_NAME} PUBLIC ${ONNXRUNTIME_ROOTDIR}/include)
84+
# Link the directories to project
85+
link_directories(${PROJECT_NAME} ${ONNXRUNTIME_ROOTDIR}/lib)
86+
# Link the onnxruntime library to project
87+
target_link_libraries(${PROJECT_NAME} onnxruntime)
88+
endif()
5789

58-
set_property(TARGET ${PROJECT_NAME} PROPERTY CXX_STANDARD 17)
90+
endif()
5991

92+
# Models have to be copied to executable directory
6093
set(MODELS_SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/models)
6194
set(MODELS_DEST_DIR ${CMAKE_BINARY_DIR}/models)
6295

6396
add_custom_target(copy_models ALL
64-
COMMAND ${CMAKE_COMMAND} -E copy_directory ${MODELS_SOURCE_DIR} ${MODELS_DEST_DIR}
97+
COMMAND ${CMAKE_COMMAND} -E copy_directory ${MODELS_SOURCE_DIR} $<TARGET_FILE_DIR:${PROJECT_NAME}>
6598
COMMENT "Copying models directory to build folder"
6699
)
67100

101+
# Build examples?
68102
if(CLFML_LOWWI_BUILD_EXAMPLE_PROJECTS)
69-
find_package(SDL2 REQUIRED)
70-
set(LOWWI_EXAMPLE_FRAGMENTS_PATH ${CMAKE_BINARY_DIR}/example_fragments/)
103+
# Microphone demo has dependency on SDL2
104+
# Windows dependencies are annoying (as always has been)
105+
# So we include it manually into build
106+
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
107+
include(FetchContent)
108+
109+
# Fetch latest windows release of SDL2
110+
FetchContent_Declare(
111+
SDL2
112+
URL https://github.com/libsdl-org/SDL/releases/download/release-2.30.10/SDL2-devel-2.30.10-VC.zip
113+
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/lib/SDL2
114+
)
115+
FetchContent_MakeAvailable(SDL2)
116+
117+
# include the SDL2-config manually, as adding to modules did not work for me
118+
include("${CMAKE_CURRENT_LIST_DIR}/lib/SDL2/cmake/sdl2-config.cmake")
119+
120+
# Get all dll files in SDL2 library folder
121+
file(GLOB sdl2_dll_files ${CMAKE_CURRENT_LIST_DIR}/lib/SDL2/lib/x64/*.dll)
122+
123+
# Copy all dll_files of SDL2 to executable dir
124+
add_custom_target(copy_sdl2_dll ALL
125+
COMMAND ${CMAKE_COMMAND} -E copy ${sdl2_dll_files} $<TARGET_FILE_DIR:${PROJECT_NAME}>
126+
COMMENT "Copying dll file to build folder"
127+
)
128+
else()
129+
# On linux & mac, we want to use system/brew provided packages
130+
find_package(SDL2 REQUIRED)
131+
endif()
132+
133+
# Example fragments for demo_fragments should be copied to executable dir too
71134
add_custom_target(copy_example_fragments ALL
72-
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/example/LOWWI_demo_fragment/example_fragments ${LOWWI_EXAMPLE_FRAGMENTS_PATH}
135+
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_CURRENT_LIST_DIR}/example/LOWWI_demo_fragment/example_fragments $<TARGET_FILE_DIR:${PROJECT_NAME}>
73136
COMMENT "Copying example fragments to build folder"
74137
)
138+
139+
# Add the demo_fragments demo
75140
add_executable(LOWWI_demo ${CMAKE_CURRENT_LIST_DIR}/example/LOWWI_demo_fragment/demo.cpp)
141+
142+
# Add the mic demo
76143
add_executable(LOWWI_demo_mic ${CMAKE_CURRENT_LIST_DIR}/example/LOWWI_demo_mic/demo_mic.cpp
77144
${CMAKE_CURRENT_LIST_DIR}/example/LOWWI_demo_mic/audio_async/audio_async.cpp)
145+
146+
# Set the example fragments path
147+
set(LOWWI_EXAMPLE_FRAGMENTS_PATH $<TARGET_FILE_DIR:${PROJECT_NAME}>/example_fragments)
78148
target_compile_definitions(LOWWI_demo PUBLIC -DCLFML_LOWWI_EXAMPLE_FRAGMENTS="${LOWWI_EXAMPLE_FRAGMENTS_PATH}")
149+
150+
# Link Lowwi demo's with Lowwi
79151
target_link_libraries(LOWWI_demo PRIVATE Lowwi)
80152
target_include_directories(LOWWI_demo_mic PRIVATE ${SDL2_INCLUDE_DIRS} ${CMAKE_CURRENT_LIST_DIR}/example/LOWWI_demo_mic/audio_async)
81153
target_link_libraries(LOWWI_demo_mic PUBLIC Lowwi ${SDL2_LIBRARIES})

example/LOWWI_demo_fragment/demo.cpp

100644100755
+4-5
Original file line numberDiff line numberDiff line change
@@ -97,11 +97,10 @@ int main(int argc, char *argv[])
9797
CLFML::LOWWI::Lowwi ww_runtime;
9898

9999
/* Configure the wakeword model */
100-
CLFML::LOWWI::Lowwi_word_t ww{
101-
.phrase = "Hey Mycroft",
102-
.model_path = "models/example_wakewords/hey_mycroft.onnx",
103-
.cbfunc = wakeword_callback,
104-
};
100+
CLFML::LOWWI::Lowwi_word_t ww;
101+
ww.phrase = "Hey Mycroft";
102+
ww.model_path = std::filesystem::path("models/example_wakewords/hey_mycroft.onnx");
103+
ww.cbfunc = wakeword_callback;
105104

106105
/* Add the wakeword to the runtime */
107106
ww_runtime.add_wakeword(ww);

example/LOWWI_demo_fragment/example_fragments/hey_mycroft_test.wav

100644100755
File mode changed.

example/LOWWI_demo_mic/audio_async/audio_async.cpp

100644100755
+1-1
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ void audio_async::get(int ms, std::vector<float> & result) {
218218

219219
result.resize(n_samples);
220220

221-
int s0 = m_audio_pos - n_samples;
221+
signed long long s0 = m_audio_pos - n_samples;
222222
if (s0 < 0) {
223223
s0 += m_audio.size();
224224
}

example/LOWWI_demo_mic/audio_async/audio_async.hpp

100644100755
File mode changed.

example/LOWWI_demo_mic/demo_mic.cpp

100644100755
+1-1
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ int main(int argc, char *argv[])
6868
CLFML::LOWWI::Lowwi_word_t ww;
6969
ww.cbfunc = wakeword_callback;
7070
ww.cb_arg = audio;
71-
ww.model_path = "models/example_wakewords/hey_mycroft.onnx";
71+
ww.model_path = std::filesystem::path("models/example_wakewords/hey_mycroft.onnx");
7272
ww.phrase = "Hey Mycroft";
7373

7474
/* Add wakeword to ww-runtime */

src/lowwi.cpp

100644100755
+4-4
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,9 @@ namespace CLFML::LOWWI
4040
if(!lowwi_word.cbfunc) {
4141
throw std::runtime_error("[LOWI]: ERROR! No callback function defined for lowwi_word!");
4242
}
43-
wakeword_t wakeword = {
44-
.ww_inst = std::make_unique<WakeWord>(_env, _session_opt, lowwi_word.model_path, lowwi_word.threshold, lowwi_word.min_activations, lowwi_word.refractory, lowwi_word.debug),
45-
.properties = lowwi_word,
43+
wakeword_t wakeword {
44+
std::make_unique<WakeWord>(_env, _session_opt, lowwi_word.model_path, lowwi_word.threshold, lowwi_word.min_activations, lowwi_word.refractory, lowwi_word.debug),
45+
lowwi_word,
4646
};
4747
_wakewords.push_back(std::move(wakeword));
4848
}
@@ -62,7 +62,7 @@ namespace CLFML::LOWWI
6262
for (auto &ww : _wakewords) {
6363
wakeword_result res = ww.ww_inst->detect(_feature_samples);
6464
if(res.detected) {
65-
Lowwi_ctx_t cb = {.phrase = ww.properties.phrase, .confidence = res.confidence};
65+
Lowwi_ctx_t cb = {ww.properties.phrase, res.confidence};
6666
ww.properties.cbfunc(cb, ww.properties.cb_arg);
6767
}
6868
}

src/lowwi.hpp

100644100755
+8-7
Original file line numberDiff line numberDiff line change
@@ -35,17 +35,18 @@ namespace CLFML::LOWWI
3535
const float confidence;
3636
}Lowwi_ctx_t;
3737

38-
typedef struct
38+
struct Lowwi_word_t
3939
{
40-
std::string phrase;
41-
const char *model_path;
42-
std::function<void(Lowwi_ctx_t, std::shared_ptr<void>)> cbfunc;
43-
std::shared_ptr<void> cb_arg;
44-
float refractory = 20.0f;
40+
std::string phrase = "";
41+
std::filesystem::path model_path = std::filesystem::path("");
42+
std::function<void(Lowwi_ctx_t, std::shared_ptr<void>)> cbfunc = nullptr;
43+
std::shared_ptr<void> cb_arg = nullptr;
44+
int refractory = 20;
4545
float threshold = 0.5f;
4646
float min_activations = 5;
4747
uint8_t debug = false;
48-
} Lowwi_word_t;
48+
49+
} ;
4950

5051
class Lowwi
5152
{

src/lowwi_embedding.cpp

100644100755
+1-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace CLFML::LOWWI
2727
_session_options(session_options),
2828
_mem_info(Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeCPU))
2929
{
30-
_session = std::make_unique<Ort::Session>(_env, _embedding_model_path, _session_options);
30+
_session = std::make_unique<Ort::Session>(_env, _embedding_model_path.c_str(), _session_options);
3131
}
3232

3333
std::vector<float> &Embedding::convert(const std::vector<float> &mels_in)

src/lowwi_embedding.hpp

100644100755
+3-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
#define LOWWI_EMBEDDING_HPP
2424
#include <vector>
2525
#include <onnxruntime_cxx_api.h>
26+
#include <filesystem>
27+
2628
namespace CLFML::LOWWI
2729
{
2830

@@ -58,7 +60,7 @@ namespace CLFML::LOWWI
5860
std::vector<float> _samples_to_process;
5961
std::vector<float> _embedding_out;
6062

61-
const char *_embedding_model_path = "models/embedding_model.onnx";
63+
const std::filesystem::path _embedding_model_path = "models/embedding_model.onnx";
6264
};
6365
}
6466
#endif /* LOWWI_EMBEDDING_HPP */

src/lowwi_melspectrogram.cpp

100644100755
+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ namespace CLFML::LOWWI
3131
* Create new session for our Onnx model
3232
* Also load the model in :)
3333
*/
34-
_session = std::make_unique<Ort::Session>(_env, _melspectrogram_model_path, _session_options);
34+
_session = std::make_unique<Ort::Session>(_env, _melspectrogram_model_path.c_str(), _session_options);
3535
}
3636

3737
std::vector<float> &Melspectrogram::convert(const std::vector<float> &audio_samples)

src/lowwi_melspectrogram.hpp

100644100755
+2-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#define LOWWI_MELSPECTROGRAM_HPP
2424
#include <vector>
2525
#include "onnxruntime_cxx_api.h"
26+
#include <filesystem>
2627

2728
namespace CLFML::LOWWI
2829
{
@@ -59,7 +60,7 @@ namespace CLFML::LOWWI
5960
std::vector<float> _samples_to_process;
6061
std::vector<float> _melspectrogram_out;
6162

62-
const char *_melspectrogram_model_path = "models/melspectrogram.onnx";
63+
const std::filesystem::path _melspectrogram_model_path = "models/melspectrogram.onnx";
6364

6465
};
6566

src/lowwi_wakeword.cpp

100644100755
+4-4
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
namespace CLFML::LOWWI
2626
{
2727

28-
WakeWord::WakeWord(Ort::Env &env, Ort::SessionOptions &session_options, const char *model_path, const float threshold, const float min_activations, const float refractory, const uint8_t debug) : _env(env),
28+
WakeWord::WakeWord(Ort::Env &env, Ort::SessionOptions &session_options, const std::filesystem::path model_path, const float threshold, const float min_activations, const int refractory, const uint8_t debug) : _env(env),
2929
_session_options(session_options),
3030
_mem_info(Ort::MemoryInfo::CreateCpu(OrtAllocatorType::OrtArenaAllocator, OrtMemType::OrtMemTypeCPU)),
3131
_threshold(threshold), _model_path(model_path), _debug(debug), _min_activations(min_activations), _refractory(refractory)
@@ -34,7 +34,7 @@ namespace CLFML::LOWWI
3434
* Create new session for our Onnx model
3535
* Also load the model in :)
3636
*/
37-
_session = std::make_unique<Ort::Session>(_env, _model_path, _session_options);
37+
_session = std::make_unique<Ort::Session>(_env, _model_path.c_str(), _session_options);
3838
}
3939

4040
wakeword_result WakeWord::detect(const std::vector<float> &features)
@@ -112,7 +112,7 @@ namespace CLFML::LOWWI
112112
{
113113
res.detected = 1; // Trigger level reached
114114
activation = -_refractory; // Reset activation with refractory period
115-
sum_probability += float(probability*100);
115+
sum_probability += int(float(probability*100));
116116
num_of_triggers++;
117117
}
118118
}
@@ -131,7 +131,7 @@ namespace CLFML::LOWWI
131131
}
132132

133133
/* Calculate the avg probability or zero if no wakeword triggers */
134-
res.confidence = (num_of_triggers > 0) ? (sum_probability/num_of_triggers) : 0;
134+
res.confidence = (num_of_triggers > 0) ? float(sum_probability/num_of_triggers) : 0.0f;
135135

136136
if (sample_idx > 0)
137137
{

src/lowwi_wakeword.hpp

100644100755
+5-4
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <cstdint>
2525
#include <vector>
2626
#include <onnxruntime_cxx_api.h>
27+
#include <filesystem>
2728

2829
namespace CLFML::LOWWI
2930
{
@@ -51,10 +52,10 @@ namespace CLFML::LOWWI
5152
*/
5253
WakeWord(Ort::Env &env,
5354
Ort::SessionOptions &session_options,
54-
const char *model_path,
55+
const std::filesystem::path model_path,
5556
const float threshold,
5657
const float min_activations,
57-
const float refractory,
58+
const int refractory,
5859
const uint8_t debug);
5960

6061
/**
@@ -76,10 +77,10 @@ namespace CLFML::LOWWI
7677
std::vector<float> _samples_to_process;
7778

7879
const uint8_t _debug = false;
79-
const char *_model_path;
80+
const std::filesystem::path _model_path;
8081
const float _threshold;
8182
const float _min_activations;
82-
const float _refractory;
83+
const int _refractory;
8384
};
8485
}
8586

0 commit comments

Comments
 (0)