cmake_minimum_required(VERSION 3.25) project(dsp-engine) include(ExternalProject) include(FetchContent) option(BUILD_TESTS "Build test executable" OFF) option(BUILD_ASAN "Build with address sanitizer" OFF) option(BUILD_UBSAN "Build with undefined behaviour sanitizer" OFF) set(CMAKE_CXX_STANDARD 23) set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_POLICY_DEFAULT_CMP0177 NEW) # squash some warnings set(CMAKE_CXX_FLAGS_RELEASE "-O3 -g" CACHE STRING "" FORCE) set(CMAKE_C_FLAGS_RELEASE "-O3 -g" CACHE STRING "" FORCE) SET(EM_COMMON_FLAGS "-msimd128 -msse4.2 -sWASM_WORKERS=1") if(BUILD_ASAN) SET(EM_COMMON_FLAGS "${EM_COMMON_FLAGS} -fsanitize=address -fsanitize-address-use-after-return=always") endif() if(BUILD_UBSAN) SET(EM_COMMON_FLAGS "${EM_COMMON_FLAGS} -fsanitize=undefined") endif() SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${EM_COMMON_FLAGS}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EM_COMMON_FLAGS}") # for speexdsp SET(USE_SSE ON CACHE BOOL "Use SSE") FetchContent_Declare( speexdsp GIT_REPOSITORY https://github.com/marc-suno/speexdsp-cmake GIT_TAG 8383a0ebc940a7dc260ecae90a2e86307bfe2e9e ) FetchContent_MakeAvailable(speexdsp) FetchContent_Declare( Catch2 GIT_REPOSITORY https://github.com/catchorg/Catch2.git GIT_TAG v2.13.10 ) set(CATCH_BUILD_TESTING OFF CACHE BOOL "Disable Catch2 self-test") set(CATCH_INSTALL_DOCS OFF CACHE BOOL "Disable Catch2 docs") set(CATCH_INSTALL_HELPERS OFF CACHE BOOL "Disable Catch2 contrib helpers") FetchContent_MakeAvailable(Catch2) FetchContent_Declare( Eigen GIT_REPOSITORY https://gitlab.com/libeigen/eigen.git GIT_TAG d81aa18f4dc56264b2cd7e2f230807d776a2d385 ) set(EIGEN_BUILD_TESTING OFF CACHE BOOL "Disable Eigen tests") FetchContent_MakeAvailable(Eigen) add_executable(dsp-engine fft/pffft.c buffer.cc simd.cc randomaccessaudioreadable.cc remotebuffer.cc timestretch.cc audioclip.cc track.cc meter.cc timeline.cc timing.cc ffmpegbuffer.cc ringbuffercache.cc resampler.cc dspcontext.cc util.cc analytics.cc complexflux.cc limiter.cc delayline.cc mipmapworker.cc biquad.cc concurrent/bag.cc concurrent/appendonlybuffer.cc concurrent/workq.cc concurrent/globalpool.cc $,test.cc,main.cc> ) add_dependencies( dsp-engine speexdsp eigen ) target_compile_options( dsp-engine PRIVATE # see https://stackoverflow.com/questions/7420665/what-does-gccs-ffast-math-actually-do/22135559#22135559 -fno-math-errno -fno-trapping-math -funsafe-math-optimizations -fno-signed-zeros -Wno-deprecated-declarations # for Eigen in c++23 $<$:-DBUILD_TESTS> $<$>:-DCATCH_CONFIG_DISABLE> ) target_include_directories( dsp-engine PRIVATE "${CMAKE_SOURCE_DIR}/bungee-pro-v1.4.38/wasm" ${CMAKE_SOURCE_DIR} ${eigen_SOURCE_DIR} "${CMAKE_SOURCE_DIR}/ffmpeg/dist/include" ) target_link_directories( dsp-engine PRIVATE "${CMAKE_SOURCE_DIR}/ffmpeg/dist/lib" ) target_link_libraries(dsp-engine speexdsp opus avformat avcodec avutil avfilter swresample swscale Catch2::Catch2 ) set_target_properties(dsp-engine PROPERTIES LINK_DEPENDS "${CMAKE_SOURCE_DIR}/asanOptions.js") target_link_options(dsp-engine PRIVATE -lembind -flto -sSTACK_SIZE=3670016 -sALLOW_MEMORY_GROWTH=1 -sMODULARIZE=1 -sEXPORT_ES6=1 -sEXPORT_NAME=createDspEngineModule #-sNO_EXIT_RUNTIME # asan $<$:--pre-js ${CMAKE_SOURCE_DIR}/asanOptions.js -sSTACK_OVERFLOW_CHECK=2 -sMAXIMUM_MEMORY=4294967296 -sINITIAL_MEMORY=1073741824> $<$>:-sINITIAL_MEMORY=33554432> # tests $<$>:--emit-tsd ${CMAKE_BINARY_DIR}/dsp-engine.d.ts> $<$:-sNODERAWFS=1> -sWASM_WORKERS=1 -sAUDIO_WORKLET=1 -sFETCH=1 -sUSE_ZLIB=1 #$<$>:-sMALLOC=mimalloc> --post-js ${CMAKE_SOURCE_DIR}/exposeGrowable.js "${CMAKE_SOURCE_DIR}/bungee-pro-v1.4.38/wasm/emscripten-4.0.5/bungeepro.o" ) set(CLANGD_FILE ${CMAKE_BINARY_DIR}/clangd) if(EMSCRIPTEN) execute_process(COMMAND ${CMAKE_C_COMPILER} --cflags OUTPUT_VARIABLE CLANGD_FLAGS_TO_ADD) separate_arguments(CLANGD_FLAGS_TO_ADD UNIX_COMMAND "${CLANGD_FLAGS_TO_ADD}") list(JOIN CLANGD_FLAGS_TO_ADD ", " CLANGD_FLAGS_TO_ADD) set(CLANGD_TEMPLATE ${CMAKE_SOURCE_DIR}/clangd.in) configure_file(${CLANGD_TEMPLATE} ${CLANGD_FILE}) else() file(WRITE ${CLANGD_FILE} "") endif() add_custom_target( postprocess_output ALL DEPENDS "${CMAKE_SOURCE_DIR}/artifacts/__doesnotexist" ) add_custom_command( OUTPUT "${CMAKE_SOURCE_DIR}/artifacts/__doesnotexist" DEPENDS dsp-engine COMMAND python3 "${CMAKE_SOURCE_DIR}/postprocess_build.py" "${CMAKE_SOURCE_DIR}" "${CMAKE_BINARY_DIR}" )