shithub: libsamplerate

Download patch

ref: 09cb4069319a83ab89e6cf9992ac99cb57ab0ae4
parent: ca49d59c42a3616d117857047a463f6e3aa86b73
author: evpobr <[email protected]>
date: Tue Oct 6 06:39:39 EDT 2020

Improve CMake project

* Add more Git ignore rules
* Use GNUInstallDirs module
* Make Installation directories configurable
* Fix include directories
* Make math library to private
* Fix shared library installation
* Add config-file package
* Deprecate DLL name mangling
* Let CMake choose output library names (expect MinGW and Cygwin, it is known bug)
* Set SOVERSION and VERSION for shared library
* Make SndFile find module compliant with upstream
* Fix dev warnings* Improve find modules
* Convert tabs to whitespaces
* Add Packaging module
* Use new required version syntax
* Allow new MSVC runtime library flags selection
* Small style fixes
* Fix dev warning
* Add Travis CI missing libopus-dev package
* CMake: Update examples
* Update tests
* Add library sources properly
* Silence some useless compiler warnings
* Reformat source code
* Set public header
* Deprecate LIBSAMPLERATE_TESTS option

--- a/.gitignore
+++ b/.gitignore
@@ -53,4 +53,21 @@
 tests/src-evaluate
 *.log
 *.trs
-build/
+
+CMakeCache.txt
+CMakeFiles
+CMakeScripts
+Testing
+Makefile
+cmake_install.cmake
+install_manifest.txt
+compile_commands.json
+CTestTestfile.cmake
+CMakeSettings.json
+
+/*[Bb]uild*/
+
+/.vscode/
+/.vs/
+/out/
+
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,7 +15,7 @@
 
 addons:
   apt:
-    packages: [libsndfile-dev, libfftw3-dev, libasound2-dev]
+    packages: [libsndfile-dev, libopus-dev, libfftw3-dev, libasound2-dev]
 
 env:
   - CMAKE_SHARED=OFF BUILD_TYPE=Debug
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,15 +1,31 @@
-cmake_minimum_required(VERSION 3.1)
+cmake_minimum_required(VERSION 3.1..3.18)
+
+# Policies
+
+# Include file check macros honor CMAKE_REQUIRED_LIBRARIES, CMake >= 3.12
+if(POLICY CMP0075)
+  cmake_policy(SET CMP0075 NEW)
+endif()
+
+# MSVC runtime library flags are selected by an abstraction, CMake >= 3.15
+# This policy still need to be set even with cmake_minimum_required() command above.
+if(POLICY CMP0091)
+  cmake_policy(SET CMP0091 NEW)
+endif()
+
 project(libsamplerate VERSION 0.1.9 LANGUAGES C)
 
+# Configuration
+
 if(CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR)
-    set(IS_ROOT_PROJECT ON)
+  set(IS_ROOT_PROJECT ON)
 else()
-    set(IS_ROOT_PROJECT OFF)
+  set(IS_ROOT_PROJECT OFF)
 endif()
 
-option(LIBSAMPLERATE_TESTS "Enable to generate test targets" ${IS_ROOT_PROJECT})
 option(LIBSAMPLERATE_EXAMPLES "Enable to generate examples" ${IS_ROOT_PROJECT})
 option(LIBSAMPLERATE_INSTALL "Enable to add install directives" ${IS_ROOT_PROJECT})
+option(LIBSAMPLERATE_COMPATIBLE_NAME "Use old dll name on Windows platform" OFF)
 
 list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
 
@@ -18,23 +34,34 @@
 
 include(TestBigEndian)
 include(CheckFunctionExists)
-include(CheckIncludeFiles)
+include(CheckIncludeFile)
+include(CheckLibraryExists)
 include(CheckSymbolExists)
 include(ClipMode)
+include(CMakePackageConfigHelpers)
+include(GNUInstallDirs)
+
+if(DEFINED LIBSAMPLERATE_TESTS)
+  message(DEPRECATION "LIBSAMPLERATE_TESTS option deprecated, use BUILD_TESTING option instead.")
+  set(BUILD_TESTING ${LIBSAMPLERATE_TESTS})
+endif()
+include(CTest)
+
 add_definitions(-DHAVE_CONFIG_H)
+if(MSVC)
+  add_definitions(-D_CRT_SECURE_NO_WARNINGS)
+endif()
 
-set(SAMPLERATE_SRC
-	${PROJECT_SOURCE_DIR}/src/samplerate.c
-	${PROJECT_SOURCE_DIR}/src/src_linear.c
-	${PROJECT_SOURCE_DIR}/src/src_sinc.c
-	${PROJECT_SOURCE_DIR}/src/src_zoh.c)
+set(OS_IS_WIN32 ${WIN32})
 
-if(WIN32)
-	set(OS_IS_WIN32 TRUE)
-	set(SAMPLERATE_SRC
-		${SAMPLERATE_SRC}
-		${PROJECT_SOURCE_DIR}/Win32/libsamplerate-0.def)
-	include_directories(Win32)
+if(NOT WIN32)
+  find_library(MATH_LIBRARY m)
+  if(MATH_LIBRARY)
+    set(LIBM_REQUIRED 1)
+    if(LIBM_REQUIRED)
+      list(APPEND CMAKE_REQUIRED_LIBRARIES m)
+    endif()
+  endif()
 endif()
 
 if(CMAKE_C_COMPILER_ID STREQUAL "GNU" OR CMAKE_C_COMPILER_ID MATCHES "Clang")
@@ -54,13 +81,11 @@
 
 test_big_endian(CPU_IS_BIG_ENDIAN)
 if(CPU_IS_BIG_ENDIAN)
-	set(CPU_IS_LITTLE_ENDIAN 0)
+  set(CPU_IS_LITTLE_ENDIAN 0)
 else()
-	set(CPU_IS_LITTLE_ENDIAN 1)
+  set(CPU_IS_LITTLE_ENDIAN 1)
 endif()
 
-find_library(LIBSAMPLERATE_MATH_LIBRARY m)
-
 # This will set CPU_CLIPS_NEGATIVE and CPU_CLIPS_POSITIVE
 clip_mode()
 
@@ -67,107 +92,290 @@
 check_function_exists(alarm HAVE_ALARM)
 check_function_exists(signal HAVE_SIGNAL)
 
-check_include_files(sys/times.h HAVE_SYS_TIMES_H)
+check_include_file(sys/times.h HAVE_SYS_TIMES_H)
+check_include_file(unistd.h HAVE_UNISTD_H)
 
 check_symbol_exists(SIGALRM signal.h HAVE_SIGALRM)
 
 find_package(ALSA)
 set(HAVE_ALSA ${ALSA_FOUND})
+# ALSA::ALSA target is exported since CMake >= 3.12, create it for
+# old CMake versions
 if(ALSA_FOUND)
-  include_directories("${ALSA_INCLUDE_DIR}")
+  if(NOT TARGET ALSA::ALSA)
+    add_library(ALSA::ALSA UNKNOWN IMPORTED)
+    set_target_properties(ALSA::ALSA PROPERTIES
+    INTERFACE_INCLUDE_DIRECTORIES "${ALSA_INCLUDE_DIRS}"
+    IMPORTED_LOCATION "${ALSA_LIBRARIES}")
+  endif()
 endif()
 
-find_package(Sndfile)
-set(HAVE_SNDFILE ${SNDFILE_FOUND})
-if(SNDFILE_FOUND)
-  include_directories("${SNDFILE_INCLUDE_DIR}")
-endif()
+find_package(SndFile)
+set(HAVE_SNDFILE ${SndFile_FOUND})
 
-find_package(FFTW)
-set(HAVE_FFTW3 ${FFTW_FOUND})
-if(FFTW_FOUND)
-  include_directories("${FFTW_INCLUDE_DIR}")
-endif()
+find_package(FFTW3)
+set(HAVE_FFTW3 ${FFTW3_FOUND})
 
-configure_file(${PROJECT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
+configure_file(config.h.in config.h)
 
-add_library(samplerate ${SAMPLERATE_SRC})
+# samplerate library target
 
+add_library(samplerate
+  src/common.h
+  src/fastest_coeffs.h
+  src/high_qual_coeffs.h
+  src/mid_qual_coeffs.h
+  src/samplerate.c
+  src/samplerate.h
+  src/src_config.h
+  src/src_linear.c
+  src/src_sinc.c
+  src/src_zoh.c
+  $<$<AND:$<BOOL:${WIN32}>,$<BOOL:${BUILD_SHARED_LIBS}>>:Win32/libsamplerate-0.def>)
+
+# ALIAS to use if libsamplerate is included from other project with add_subdirectory()
+add_library(SampleRate::samplerate ALIAS samplerate)
+
+# CMake generates wrong DLL names for MinGW and Cygwin, fix it
 if(BUILD_SHARED_LIBS AND WIN32)
-	if (MSVC)
-		set_target_properties(samplerate PROPERTIES OUTPUT_NAME "libsamplerate-0")
-	else()
-		set_target_properties(samplerate PROPERTIES OUTPUT_NAME "samplerate-0")
-	endif()
+  if(LIBSAMPLERATE_COMPATIBLE_NAME)
+    if(MSVC)
+      set_target_properties(samplerate PROPERTIES OUTPUT_NAME "libsamplerate-${libsamplerate_VERSION_MAJOR}")
+    else()
+      set_target_properties(samplerate PROPERTIES OUTPUT_NAME "samplerate-${libsamplerate_VERSION_MAJOR}")
+  endif()
+  else()
+    if(MINGW OR CYGWIN)
+      set_target_properties(samplerate PROPERTIES RUNTIME_OUTPUT_NAME "samplerate-${libsamplerate_VERSION_MAJOR}")
+    endif()
+  endif()
 endif()
 
-target_include_directories(samplerate PUBLIC
-	${PROJECT_SOURCE_DIR}/src
-  ${CMAKE_CURRENT_BINARY_DIR})
+target_include_directories(samplerate
+  PUBLIC
+    $<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>
+    $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
+  PRIVATE
+    ${CMAKE_CURRENT_BINARY_DIR})
 
-if(LIBSAMPLERATE_MATH_LIBRARY)
-    target_link_libraries(samplerate PUBLIC ${LIBSAMPLERATE_MATH_LIBRARY})
+if(LIBM_REQUIRED)
+    target_link_libraries(samplerate PRIVATE m)
 endif()
-    
-if(LIBSAMPLERATE_TESTS)
 
-	enable_testing()
+# Set public header
+set_property(TARGET samplerate PROPERTY PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/src/samplerate.h)
 
-	file(GLOB TEST_SRCS ${PROJECT_SOURCE_DIR}/tests/*_test.c)
+# Set ABI version. This is critical for Unix-like OSes
+if(BUILD_SHARED_LIBS)
+  set_target_properties(samplerate PROPERTIES
+    VERSION ${libsamplerate_VERSION}
+    SOVERSION ${libsamplerate_VERSION_MAJOR})
+endif()
 
-	foreach(testSrc ${TEST_SRCS})
-		get_filename_component(testName ${testSrc} NAME_WE)
-		add_executable(${testName}
-			${testSrc}
-			${PROJECT_SOURCE_DIR}/tests/util.c
-			${PROJECT_SOURCE_DIR}/tests/calc_snr.c)
-	target_link_libraries(${testName} PUBLIC samplerate)
-		if(FFTW_FOUND)
-			target_link_libraries(${testName} PUBLIC ${FFTW_LIBRARY})
-		endif()
-		add_test(NAME ${testName} COMMAND ${testName})
-	endforeach(testSrc)
+# Tests
+
+# BUILD_TESTING is declared by CTest module and is ON by default
+if(BUILD_TESTING)
+
+  add_executable(misc_test tests/misc_test.c tests/util.c tests/util.h)
+  target_include_directories(misc_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(misc_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME misc_test COMMAND misc_test)
+
+  add_executable(termination_test tests/termination_test.c tests/util.c tests/util.h)
+  target_include_directories(termination_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(termination_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME termination_test COMMAND termination_test)
+
+  add_executable(callback_hang_test tests/callback_hang_test.c tests/util.c tests/util.h)
+  target_include_directories(callback_hang_test
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(callback_hang_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME callback_hang_test COMMAND callback_hang_test)
+
+  add_executable(downsample_test tests/downsample_test.c tests/util.c tests/util.h)
+  target_include_directories(downsample_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(downsample_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME downsample_test COMMAND downsample_test)
+
+  add_executable(simple_test tests/simple_test.c tests/util.c tests/util.h)
+  target_include_directories(simple_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(simple_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME simple_test COMMAND simple_test)
+
+  add_executable(callback_test tests/callback_test.c tests/util.c tests/util.h)
+  target_include_directories(callback_test
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(callback_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME callback_test COMMAND callback_test)
+
+  add_executable(reset_test tests/reset_test.c tests/util.c tests/util.h)
+  target_include_directories(reset_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(reset_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME reset_test COMMAND reset_test)
+
+  add_executable(clone_test tests/clone_test.c tests/util.c tests/util.h)
+  target_include_directories(clone_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(clone_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME clone_test COMMAND clone_test)
+
+  add_executable(nullptr_test tests/nullptr_test.c tests/util.c tests/util.h)
+  target_include_directories(nullptr_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(nullptr_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME nullptr_test COMMAND nullptr_test)
+
+  add_executable(multi_channel_test tests/multi_channel_test.c tests/calc_snr.c tests/util.c tests/util.h)
+  target_include_directories(multi_channel_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(multi_channel_test
+    PRIVATE
+      samplerate
+      $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3>
+      $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME multi_channel_test COMMAND multi_channel_test)
+
+  add_executable(varispeed_test tests/varispeed_test.c tests/calc_snr.c tests/util.c tests/util.h)
+  target_include_directories(varispeed_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(varispeed_test
+    PRIVATE samplerate
+      $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3>
+      $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+  add_test(NAME varispeed_test COMMAND varispeed_test tests/util.c tests/util.h)
+
+  add_executable(float_short_test tests/float_short_test.c)
+  target_include_directories(float_short_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(float_short_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME float_short_test COMMAND float_short_test)
+
+  add_executable(snr_bw_test tests/snr_bw_test.c tests/calc_snr.c tests/util.c tests/util.h)
+  target_include_directories(snr_bw_test PRIVATE ${PROJECT_BINARY_DIR})
+  target_link_libraries(snr_bw_test
+    PRIVATE
+      samplerate
+      $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3>
+      $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  add_test(NAME snr_bw_test COMMAND snr_bw_test tests/util.c tests/util.h)
+
+  add_executable(throughput_test tests/throughput_test.c tests/util.c tests/util.h)
+  target_include_directories(throughput_test
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(throughput_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+  add_executable(multichan_throughput_test tests/multichan_throughput_test.c tests/util.c tests/util.h)
+  target_include_directories(multichan_throughput_test
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(multichan_throughput_test PRIVATE samplerate $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+  add_executable(src-evaluate tests/src-evaluate.c tests/util.c tests/util.h tests/calc_snr.c)
+  target_include_directories(src-evaluate
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(src-evaluate
+    PRIVATE
+      samplerate
+      $<$<BOOL:${FFTW3_FOUND}>:FFTW3::fftw3>
+      $<$<BOOL:${SndFile_FOUND}>:SndFile::sndfile>
+      $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
 endif()
 
+# Examples
+
 if(LIBSAMPLERATE_EXAMPLES)
-	set(EXAMPLE_SRCS
-		${PROJECT_SOURCE_DIR}/examples/timewarp-file.c
-		${PROJECT_SOURCE_DIR}/examples/varispeed-play.c)
 
-	foreach(exampleSrc ${EXAMPLE_SRCS})
-		get_filename_component(exampleName ${exampleSrc} NAME_WE)
-		add_executable(${exampleName}
-			${exampleSrc}
-			${PROJECT_SOURCE_DIR}/examples/audio_out.c)
-	target_link_libraries(${exampleName} PUBLIC samplerate)
-		if(ALSA_FOUND)
-			target_link_libraries(${exampleName} PUBLIC ${ALSA_LIBRARY})
-		endif()
-		if(SNDFILE_FOUND)
-			target_link_libraries(${exampleName} PUBLIC ${SNDFILE_LIBRARY})
-		endif()
-		if(WIN32)
-			target_link_libraries(${exampleName} PUBLIC winmm)
-		endif()
-		if (APPLE)
-			target_link_libraries (${exampleName} PUBLIC  "-framework CoreAudio")
-		endif()
-	endforeach(exampleSrc)
+  add_executable(timewarp-file examples/timewarp-file.c)
+  target_include_directories(timewarp-file
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(timewarp-file
+    PRIVATE
+      samplerate
+      $<$<BOOL:${SndFile_FOUND}>:SndFile::sndfile>
+      $<$<BOOL:${LIBM_REQUIRED}>:m>)
+
+  add_executable(varispeed-play examples/varispeed-play.c examples/audio_out.c examples/audio_out.h)
+  target_include_directories(varispeed-play
+    PRIVATE
+      ${PROJECT_BINARY_DIR}
+      $<$<NOT:$<BOOL:${HAVE_UNISTD_H}>>:${PROJECT_SOURCE_DIR}/Win32>)
+  target_link_libraries(varispeed-play
+    PRIVATE
+      samplerate
+      $<$<BOOL:${SndFile_FOUND}>:SndFile::sndfile>
+      $<$<BOOL:${LIBM_REQUIRED}>:m>)
+  if(WIN32)
+    target_link_libraries(varispeed-play PRIVATE winmm)
+  elseif(APPLE)
+    target_link_libraries(varispeed-play PRIVATE "-framework CoreAudio")
+  elseif(ALSA_FOUND)
+    target_link_libraries(varispeed-play PRIVATE ALSA::ALSA)
+  endif()
+
 endif() 
 
+# Istallation
+
 if(LIBSAMPLERATE_INSTALL)
-	set(prefix ${CMAKE_INSTALL_PREFIX})
-	set(exec_prefix "\${prefix}")
-	set(includedir "\${prefix}/include")
-	set(libdir "\${exec_prefix}/lib")
-	set(VERSION "${PROJECT_VERSION}")
-	if(LIBSAMPLERATE_MATH_LIBRARY)
-		set(LIBS "-lm")
-	endif()
-	configure_file(samplerate.pc.in samplerate.pc @ONLY)
 
-	install(TARGETS samplerate DESTINATION lib)
-	install(FILES src/samplerate.h DESTINATION include)
-	install(DIRECTORY doc/ DESTINATION share/doc/libsamplerate)
-	install(FILES ${CMAKE_BINARY_DIR}/samplerate.pc DESTINATION lib/pkgconfig)
+  # pkg-config module
+
+  set(prefix ${CMAKE_INSTALL_PREFIX})
+  set(exec_prefix "\${prefix}")
+  set(includedir "\${prefix}/${CMAKE_INSTALL_INCLUDEDIR}")
+  set(libdir "\${exec_prefix}/${CMAKE_INSTALL_LIBDIR}")
+  set(VERSION "${PROJECT_VERSION}")
+  if(LIBM_REQUIRED)
+    set(LIBS "-lm")
+  endif()
+  configure_file(samplerate.pc.in samplerate.pc @ONLY)
+  install(FILES ${CMAKE_BINARY_DIR}/samplerate.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig)
+
+  # samplerate library
+
+  install(TARGETS samplerate EXPORT SampleRateTargets
+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+
+  # samplerate config-file package
+
+  if(WIN32 AND (NOT MINGW) AND (NOT CYGWIN))
+    set(CMAKE_INSTALL_PACKAGEDIR cmake) 
+  else()
+    set(CMAKE_INSTALL_PACKAGEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/SampleRate)
+  endif()
+
+  install(EXPORT SampleRateTargets
+    NAMESPACE SampleRate::
+    DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
+
+  configure_package_config_file(cmake/SampleRateConfig.cmake.in SampleRateConfig.cmake
+    INSTALL_DESTINATION ${CMAKE_INSTALL_PACKAGEDIR})
+
+  write_basic_package_version_file(SampleRateConfigVersion.cmake COMPATIBILITY SameMajorVersion)
+    install(
+      FILES
+        ${PROJECT_BINARY_DIR}/SampleRateConfig.cmake
+        ${PROJECT_BINARY_DIR}/SampleRateConfigVersion.cmake
+      DESTINATION
+        ${CMAKE_INSTALL_PACKAGEDIR})
+
+  # Documentation
+
+  install(DIRECTORY doc/ DESTINATION ${CMAKE_INSTALL_DOCDIR})
 endif()
+
+# Packaging support
+
+include(CPack)
--- a/Win32/libsamplerate-0.def
+++ b/Win32/libsamplerate-0.def
@@ -1,4 +1,3 @@
-LIBRARY  libsamplerate-0.dll
 EXPORTS
 
 src_new 				@1
--- a/cmake/ClipMode.cmake
+++ b/cmake/ClipMode.cmake
@@ -1,47 +1,47 @@
-macro (CLIP_MODE)
+macro(CLIP_MODE)
 
-    set (CLIP_MODE_POSITIVE_MESSAGE "Target processor clips on positive float to int conversion")
-    set (CLIP_MODE_NEGATIVE_MESSAGE "Target processor clips on negative float to int conversion")
+  set(CLIP_MODE_POSITIVE_MESSAGE "Target processor clips on positive float to int conversion")
+  set(CLIP_MODE_NEGATIVE_MESSAGE "Target processor clips on negative float to int conversion")
 
-    message (STATUS "Checking processor clipping capabilities...")
+  message(STATUS "Checking processor clipping capabilities...")
 
-    if (CMAKE_CROSSCOMPILING)
+  if(CMAKE_CROSSCOMPILING)
 
-        set (CLIP_MSG "disabled")
-        set (CPU_CLIPS_POSITIVE FALSE CACHE BOOL ${CLIP_MODE_POSITIVE_MESSAGE})
-        set (CPU_CLIPS_NEGATIVE FALSE CACHE BOOL ${CLIP_MODE_NEGATIVE_MESSAGE})
+    set(CLIP_MSG "disabled")
+    set(CPU_CLIPS_POSITIVE FALSE CACHE BOOL ${CLIP_MODE_POSITIVE_MESSAGE})
+    set(CPU_CLIPS_NEGATIVE FALSE CACHE BOOL ${CLIP_MODE_NEGATIVE_MESSAGE})
 
-    else ()
-        include(CheckCSourceRuns)
-        include(CMakePushCheckState)
-        cmake_push_check_state(RESET)
+  else()
+      include(CheckCSourceRuns)
+      include(CMakePushCheckState)
+      cmake_push_check_state(RESET)
 
-        if(LIBSAMPLERATE_MATH_LIBRARY)
-            list(APPEND CMAKE_REQUIRED_LIBRARIES ${LIBSAMPLERATE_MATH_LIBRARY})
-        endif()
+      if(MATH_LIBRARY)
+        list(APPEND CMAKE_REQUIRED_LIBRARIES ${MATH_LIBRARY})
+      endif()
 
-        check_c_source_runs (
-        "
-        #include <math.h>
-        int main (void)
-        {   double  fval ;
-            int k, ival ;
+      check_c_source_runs(
+      "
+      #include <math.h>
+      int main (void)
+      {   double  fval ;
+          int k, ival ;
 
-            fval = 1.0 * 0x7FFFFFFF ;
-            for (k = 0 ; k < 100 ; k++)
-            {   ival = (lrint (fval)) >> 24 ;
-                if (ival != 127)
-                    return 1 ;
+          fval = 1.0 * 0x7FFFFFFF ;
+          for (k = 0 ; k < 100 ; k++)
+          {   ival = (lrint (fval)) >> 24 ;
+              if (ival != 127)
+                  return 1 ;
 
-                fval *= 1.2499999 ;
-                } ;
+              fval *= 1.2499999 ;
+              } ;
 
-                return 0 ;
-            }
-        "
-        CPU_CLIPS_POSITIVE)
+              return 0 ;
+          }
+      "
+      CPU_CLIPS_POSITIVE)
 
-        check_c_source_runs (
+      check_c_source_runs(
         "
         #include <math.h>
         int main (void)
@@ -62,20 +62,20 @@
         "
         CPU_CLIPS_NEGATIVE)
 
-        cmake_pop_check_state()
+      cmake_pop_check_state()
 
-        if (CPU_CLIPS_POSITIVE AND CPU_CLIPS_NEGATIVE)
-            set (CLIP_MSG "both")
-        elseif (CPU_CLIPS_POSITIVE)
-            set (CLIP_MSG "positive")
-        elseif (CPU_CLIPS_NEGATIVE)
-            set (CLIP_MSG "negative")
-        else ()
-            set (CLIP_MSG "none")
-        endif ()
+      if(CPU_CLIPS_POSITIVE AND CPU_CLIPS_NEGATIVE)
+          set(CLIP_MSG "both")
+      elseif(CPU_CLIPS_POSITIVE)
+          set(CLIP_MSG "positive")
+      elseif(CPU_CLIPS_NEGATIVE)
+          set(CLIP_MSG "negative")
+      else()
+          set(CLIP_MSG "none")
+      endif()
 
-    endif ()
+  endif()
 
-    message (STATUS "Checking processor clipping capabilities... ${CLIP_MSG}")
+  message(STATUS "Checking processor clipping capabilities... ${CLIP_MSG}")
 
-endmacro ()
+endmacro()
--- a/cmake/FindFFTW.cmake
+++ /dev/null
@@ -1,48 +1,0 @@
-# Adapted from: https://github.com/wjakob/layerlab/blob/master/cmake/FindFFTW.cmake
-
-# Copyright (c) 2015, Wenzel Jakob
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions are met:
-#
-# * Redistributions of source code must retain the above copyright notice, this
-#   list of conditions and the following disclaimer.
-#
-# * Redistributions in binary form must reproduce the above copyright notice,
-#   this list of conditions and the following disclaimer in the documentation
-#   and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
-# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
-# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-# - Find FFTW
-# Find the native FFTW includes and library
-#
-#  FFTW_INCLUDE_DIR   - where to find fftw3.h
-#  FFTW_LIBRARY       - List of libraries when using FFTW.
-#  FFTW_FOUND         - True if FFTW found.
-
-if (FFTW_INCLUDE_DIR)
-  # Already in cache, be silent
-  set (FFTW_FIND_QUIETLY TRUE)
-endif (FFTW_INCLUDE_DIR)
-
-find_path (FFTW_INCLUDE_DIR fftw3.h)
-
-find_library (FFTW_LIBRARY NAMES fftw3)
-
-# handle the QUIETLY and REQUIRED arguments and set FFTW_FOUND to TRUE if
-# all listed variables are TRUE
-include (FindPackageHandleStandardArgs)
-find_package_handle_standard_args (FFTW DEFAULT_MSG FFTW_LIBRARY FFTW_INCLUDE_DIR)
-
-mark_as_advanced (FFTW_LIBRARY FFTW_INCLUDE_DIR)
--- /dev/null
+++ b/cmake/FindFFTW3.cmake
@@ -1,0 +1,88 @@
+# Adapted from: https://github.com/wjakob/layerlab/blob/master/cmake/FindFFTW.cmake
+
+# Copyright (c) 2015, Wenzel Jakob
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+#   list of conditions and the following disclaimer.
+#
+# * Redistributions in binary form must reproduce the above copyright notice,
+#   this list of conditions and the following disclaimer in the documentation
+#   and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+# - Find FFTW3
+# Find the native FFTW3 includes and library
+#
+#  Cache variables:
+#
+#  FFTW3_INCLUDE_DIR  - where to find fftw3.h
+#  FFTW3_LIBRARY      - Path to FFTW3 libray.
+#  FFTW3_ROOT         - Root of FFTW3 installation.
+#
+#  User variables:
+#
+#  FFTW3_INCLUDE_DIRS - where to find fftw3.h
+#  FFTW3_LIBRARIES    - List of libraries when using FFTW3.
+#  FFTW3_FOUND        - True if FFTW3 found.
+
+
+if(FFTW3_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(FFTW3_FIND_QUIETLY TRUE)
+endif(FFTW3_INCLUDE_DIR)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_FFTW3 QUIET fftw)
+
+set(FFTW3_VERSION ${PC_FFTW3_VERSION})
+
+find_path(FFTW3_INCLUDE_DIR fftw3.h
+  HINTS
+    ${PC_FFTW3_INCLUDEDIR}
+    ${PC_FFTW3_INCLUDE_DIRS}
+    ${FFTW3_ROOT})
+
+find_library(FFTW3_LIBRARY NAMES fftw3
+  HINTS
+    ${PC_FFTW3_LIBDIR}
+    ${PC_FFTW3_LIBRARY_DIRS}
+    ${FFTW3_ROOT})
+
+# handle the QUIETLY and REQUIRED arguments and set FFTW3_FOUND to TRUE if
+# all listed variables are TRUE
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(FFTW3
+  REQUIRED_VARS
+    FFTW3_LIBRARY
+    FFTW3_INCLUDE_DIR
+  VERSION_VAR
+    FFTW3_VERSION)
+
+if(FFTW3_FOUND)
+	set(FFTW3_LIBRARIES ${FFTW3_LIBRARY})
+	set(FFTW3_INCLUDE_DIRS ${FFTW3_INCLUDE_DIR})
+	
+	if(NOT TARGET FFTW3::fftw3)
+	  add_library(FFTW3::fftw3 UNKNOWN IMPORTED)
+		set_target_properties(FFTW3::fftw3 PROPERTIES
+			INTERFACE_INCLUDE_DIRECTORIES "${FFTW3_INCLUDE_DIR}"
+			IMPORTED_LOCATION "${FFTW3_LIBRARY}"
+		)
+  endif()
+endif()
+
+mark_as_advanced(FFTW3_LIBRARY FFTW3_INCLUDE_DIR)
--- /dev/null
+++ b/cmake/FindFLAC.cmake
@@ -1,0 +1,63 @@
+# - Find FLAC
+# Find the native FLAC includes and libraries
+#
+#  FLAC_INCLUDE_DIRS - where to find FLAC headers.
+#  FLAC_LIBRARIES    - List of libraries when using libFLAC.
+#  FLAC_FOUND        - True if libFLAC found.
+#  FLAC_DEFINITIONS  - FLAC compile definitons 
+
+if(FLAC_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(FLAC_FIND_QUIETLY TRUE)
+endif()
+
+find_package(Ogg QUIET)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_FLAC QUIET flac)
+
+set(FLAC_VERSION ${PC_FLAC_VERSION})
+
+find_path(FLAC_INCLUDE_DIR FLAC/stream_decoder.h
+  HINTS
+    ${PC_FLAC_INCLUDEDIR}
+    ${PC_FLAC_INCLUDE_DIRS}
+    ${FLAC_ROOT})
+
+# MSVC built libraries can name them *_static, which is good as it
+# distinguishes import libraries from static libraries with the same extension.
+find_library(FLAC_LIBRARY
+  NAMES
+    FLAC
+    libFLAC
+    libFLAC_dynamic
+    libFLAC_static
+  HINTS
+    ${PC_FLAC_LIBDIR}
+    ${PC_FLAC_LIBRARY_DIRS}
+    ${FLAC_ROOT})
+
+# Handle the QUIETLY and REQUIRED arguments and set FLAC_FOUND to TRUE if
+# all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(FLAC
+  REQUIRED_VARS
+    FLAC_LIBRARY
+    FLAC_INCLUDE_DIR
+    Ogg_FOUND
+  VERSION_VAR
+        FLAC_VERSION)
+
+if(FLAC_FOUND)
+  set(FLAC_INCLUDE_DIRS ${FLAC_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS})
+  set(FLAC_LIBRARIES ${FLAC_LIBRARY} ${Ogg_LIBRARIES})
+    if(NOT TARGET FLAC::FLAC)
+    add_library(FLAC::FLAC UNKNOWN IMPORTED)
+    set_target_properties(FLAC::FLAC PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${FLAC_INCLUDE_DIR}"
+      IMPORTED_LOCATION "${FLAC_LIBRARY}"
+      INTERFACE_LINK_LIBRARIES Ogg::ogg)
+  endif()
+endif()
+
+mark_as_advanced(FLAC_INCLUDE_DIR FLAC_LIBRARY)
--- /dev/null
+++ b/cmake/FindOgg.cmake
@@ -1,0 +1,57 @@
+# - Find ogg
+# Find the native ogg includes and libraries
+#
+#  Ogg_INCLUDE_DIRS - where to find ogg.h, etc.
+#  Ogg_LIBRARIES    - List of libraries when using ogg.
+#  Ogg_FOUND        - True if ogg found.
+
+if(Ogg_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(Ogg_FIND_QUIETLY TRUE)
+endif()
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_Ogg QUIET ogg)
+
+set(Ogg_VERSION ${PC_Ogg_VERSION})
+
+find_path(Ogg_INCLUDE_DIR ogg/ogg.h
+  HINTS
+    ${PC_Ogg_INCLUDEDIR}
+    ${PC_Ogg_INCLUDE_DIRS}
+    ${Ogg_ROOT})
+# MSVC built ogg may be named ogg_static.
+# The provided project files name the library with the lib prefix.
+find_library(Ogg_LIBRARY
+  NAMES
+    ogg
+    ogg_static
+    libogg
+    libogg_static
+  HINTS
+    ${PC_Ogg_LIBDIR}
+    ${PC_Ogg_LIBRARY_DIRS}
+    ${Ogg_ROOT})
+# Handle the QUIETLY and REQUIRED arguments and set Ogg_FOUND
+# to TRUE if all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Ogg
+  REQUIRED_VARS
+    Ogg_LIBRARY
+    Ogg_INCLUDE_DIR
+  VERSION_VAR
+    Ogg_VERSION)
+
+if(Ogg_FOUND)
+  set(Ogg_LIBRARIES ${Ogg_LIBRARY})
+  set(Ogg_INCLUDE_DIRS ${Ogg_INCLUDE_DIR})
+  
+  if(NOT TARGET Ogg::ogg)
+  add_library(Ogg::ogg UNKNOWN IMPORTED)
+    set_target_properties(Ogg::ogg PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${Ogg_INCLUDE_DIR}"
+      IMPORTED_LOCATION "${Ogg_LIBRARY}")
+  endif()
+endif()
+
+mark_as_advanced(Ogg_INCLUDE_DIR Ogg_LIBRARY)
--- /dev/null
+++ b/cmake/FindOpus.cmake
@@ -1,0 +1,64 @@
+# - Find opus
+# Find the native opus includes and libraries
+#
+#  OPUS_INCLUDE_DIRS - where to find opus.h, etc.
+#  OPUS_LIBRARIES    - List of libraries when using opus.
+#  OPUS_FOUND        - True if Opus found.
+
+if(OPUS_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(OPUS_FIND_QUIETLY TRUE)
+endif()
+
+find_package(Ogg QUIET)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_OPUS QUIET opus)
+
+set(OPUS_VERSION ${PC_OPUS_VERSION})
+
+find_path(OPUS_INCLUDE_DIR opus/opus.h
+  HINTS
+    ${PC_OPUS_INCLUDEDIR}
+    ${PC_OPUS_INCLUDE_DIRS}
+    ${OPUS_ROOT})
+
+# MSVC built opus may be named opus_static.
+# The provided project files name the library with the lib prefix.
+
+find_library(OPUS_LIBRARY
+  NAMES
+    opus
+    opus_static
+    libopus
+    libopus_static
+  HINTS
+    ${PC_OPUS_LIBDIR}
+    ${PC_OPUS_LIBRARY_DIRS}
+    ${OPUS_ROOT})
+
+# Handle the QUIETLY and REQUIRED arguments and set OPUS_FOUND
+# to TRUE if all listed variables are TRUE.
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(Opus
+  REQUIRED_VARS
+    OPUS_LIBRARY
+    OPUS_INCLUDE_DIR
+    Ogg_FOUND
+  VERSION_VAR
+    OPUS_VERSION)
+
+if(OPUS_FOUND)
+  set(OPUS_LIBRARIES ${OPUS_LIBRARY})
+  set(OPUS_INCLUDE_DIRS ${OPUS_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS})
+
+  if(NOT TARGET Opus::opus)
+    add_library(Opus::opus UNKNOWN IMPORTED)
+    set_target_properties(Opus::opus PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${OPUS_INCLUDE_DIR}"
+      IMPORTED_LOCATION "${OPUS_LIBRARY}"
+      INTERFACE_LINK_LIBRARIES Ogg::ogg)
+  endif()
+endif()
+
+mark_as_advanced(OPUS_INCLUDE_DIR OPUS_LIBRARY)
--- /dev/null
+++ b/cmake/FindSndFile.cmake
@@ -1,0 +1,57 @@
+# Variables defined:
+#  SNDFILE_FOUND
+#  SNDFILE_INCLUDE_DIR
+#  SNDFILE_LIBRARY
+#
+# Environment variables used:
+#  SNDFILE_ROOT
+
+if(SndFile_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(SndFile_FIND_QUIETLY TRUE)
+endif(SndFile_INCLUDE_DIR)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_SndFile QUIET sndfile)
+
+set(SndFile_VERSION ${PC_SndFile_VERSION})
+
+find_package(Vorbis COMPONENTS Enc QUIET)
+find_package(FLAC QUIET)
+find_package(Opus QUIET)
+
+find_path(SndFile_INCLUDE_DIR sndfile.h
+  HINTS
+    ${PC_SndFile_INCLUDEDIR}
+    ${PC_SndFile_INCLUDE_DIRS}
+    ${SndFile_ROOT})
+
+find_library(SndFile_LIBRARY NAMES sndfile
+  HINTS
+    ${PC_SndFile_LIBDIR}
+    ${PC_SndFile_LIBRARY_DIRS}
+    ${SndFile_ROOT})
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(SndFile
+  REQUIRED_VARS
+    SndFile_LIBRARY
+    SndFile_INCLUDE_DIR
+  VERSION_VAR
+    SndFile_VERSION)
+
+if(SndFile_FOUND)
+
+  set(SndFile_LIBRARIES ${SndFile_LIBRARY} ${Vorbis_Enc_LIBRARIES} ${FLAC_LIBRARIES} ${OPUS_LIBRARIES})
+  set(SndFile_INCLUDE_DIRS ${SndFile_INCLUDE_DIR} ${Vorbis_Enc_INCLUDE_DIRS} ${FLAC_INCLUDE_DIRS} ${OPUS_INCLUDE_DIRS})
+  
+  if(NOT TARGET SndFile::sndfile)
+    add_library(SndFile::sndfile UNKNOWN IMPORTED)
+    set_target_properties(SndFile::sndfile PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${SndFile_INCLUDE_DIR}"
+      IMPORTED_LOCATION "${SndFile_LIBRARY}"
+      INTERFACE_LINK_LIBRARIES "Vorbis::vorbisenc;Opus::opus;FLAC::FLAC")
+  endif()
+endif()
+
+mark_as_advanced(SndFile_LIBRARY SndFile_INCLUDE_DIR)
--- a/cmake/FindSndfile.cmake
+++ /dev/null
@@ -1,18 +1,0 @@
-# Variables defined:
-#  SNDFILE_FOUND
-#  SNDFILE_INCLUDE_DIR
-#  SNDFILE_LIBRARY
-#
-# Environment variables used:
-#  SNDFILE_ROOT
-
-find_path(SNDFILE_INCLUDE_DIR sndfile.h
-  HINTS $ENV{SNDFILE_ROOT}/include)
-
-find_library(SNDFILE_LIBRARY NAMES sndfile
-    HINTS $ENV{SNDFILE_ROOT}/lib)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(SNDFILE DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
-
-mark_as_advanced(SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
--- /dev/null
+++ b/cmake/FindVorbis.cmake
@@ -1,0 +1,204 @@
+#[=======================================================================[.rst:
+FindVorbis
+----------
+
+Finds the native vorbis, vorbisenc amd vorbisfile includes and libraries.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module provides the following imported targets, if found:
+
+``Vorbis::vorbis``
+  The Vorbis library
+``Vorbis::vorbisenc``
+  The VorbisEnc library
+``Vorbis::vorbisfile``
+  The VorbisFile library
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables:
+
+``Vorbis_Vorbis_INCLUDE_DIRS``
+  List of include directories when using vorbis.
+``Vorbis_Enc_INCLUDE_DIRS``
+  List of include directories when using vorbisenc.
+``Vorbis_File_INCLUDE_DIRS``
+  List of include directories when using vorbisfile.
+``Vorbis_Vorbis_LIBRARIES``
+  List of libraries when using vorbis.
+``Vorbis_Enc_LIBRARIES``
+  List of libraries when using vorbisenc.
+``Vorbis_File_LIBRARIES``
+  List of libraries when using vorbisfile.
+``Vorbis_FOUND``
+  True if vorbis and requested components found.
+``Vorbis_Vorbis_FOUND``
+  True if vorbis found.
+``Vorbis_Enc_FOUND``
+  True if vorbisenc found.
+``Vorbis_Enc_FOUND``
+  True if vorbisfile found.
+
+Cache variables
+^^^^^^^^^^^^^^^
+
+The following cache variables may also be set:
+
+``Vorbis_Vorbis_INCLUDE_DIR``
+  The directory containing ``vorbis/vorbis.h``.
+``Vorbis_Enc_INCLUDE_DIR``
+  The directory containing ``vorbis/vorbisenc.h``.
+``Vorbis_File_INCLUDE_DIR``
+  The directory containing ``vorbis/vorbisenc.h``.
+``Vorbis_Vorbis_LIBRARY``
+  The path to the vorbis library.
+``Vorbis_Enc_LIBRARY``
+  The path to the vorbisenc library.
+``Vorbis_File_LIBRARY``
+  The path to the vorbisfile library.
+
+Hints
+^^^^^
+
+A user may set ``Vorbis_ROOT`` to a vorbis installation root to tell this module where to look.
+
+#]=======================================================================]
+
+if(Vorbis_Vorbis_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(Vorbis_FIND_QUIETLY TRUE)
+endif()
+
+set(Vorbis_Vorbis_FIND_QUIETLY TRUE)
+set(Vorbis_Enc_FIND_QUIETLY TRUE)
+set(Vorbis_File_FIND_QUIETLY TRUE)
+
+find_package(Ogg QUIET)
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_Vorbis_Vorbis QUIET vorbis)
+pkg_check_modules(PC_Vorbis_Enc QUIET vorbisenc)
+pkg_check_modules(PC_Vorbis_File QUIET vorbisfile)
+
+set(Vorbis_VERSION ${PC_Vorbis_Vorbis_VERSION})
+
+find_path(Vorbis_Vorbis_INCLUDE_DIR vorbis/codec.h
+  HINTS
+    ${PC_Vorbis_Vorbis_INCLUDEDIR}
+    ${PC_Vorbis_Vorbis_INCLUDE_DIRS}
+    ${Vorbis_ROOT})
+
+find_path(Vorbis_Enc_INCLUDE_DIR vorbis/vorbisenc.h
+  HINTS
+    ${PC_Vorbis_Enc_INCLUDEDIR}
+    ${PC_Vorbis_Enc_INCLUDE_DIRS}
+    ${Vorbis_ROOT})
+
+find_path(Vorbis_File_INCLUDE_DIR vorbis/vorbisfile.h
+  HINTS
+    ${PC_Vorbis_File_INCLUDEDIR}
+    ${PC_Vorbis_File_INCLUDE_DIRS}
+    ${Vorbis_ROOT})
+
+find_library(Vorbis_Vorbis_LIBRARY
+  NAMES
+    vorbis
+    vorbis_static
+    libvorbis
+    libvorbis_static
+  HINTS
+    ${PC_Vorbis_Vorbis_LIBDIR}
+    ${PC_Vorbis_Vorbis_LIBRARY_DIRS}
+    ${Vorbis_ROOT})
+
+find_library(Vorbis_Enc_LIBRARY
+  NAMES
+    vorbisenc
+    vorbisenc_static
+    libvorbisenc
+    libvorbisenc_static
+  HINTS
+    ${PC_Vorbis_Enc_LIBDIR}
+    ${PC_Vorbis_Enc_LIBRARY_DIRS}
+    ${Vorbis_ROOT})
+
+find_library(Vorbis_File_LIBRARY
+  NAMES
+    vorbisfile
+    vorbisfile_static
+    libvorbisfile
+    libvorbisfile_static
+  HINTS
+    ${PC_Vorbis_File_LIBDIR}
+    ${PC_Vorbis_File_LIBRARY_DIRS}
+    ${Vorbis_ROOT})
+
+include(FindPackageHandleStandardArgs)
+
+if(Vorbis_Vorbis_LIBRARY AND Vorbis_Vorbis_INCLUDE_DIR AND Ogg_FOUND)
+  set(Vorbis_Vorbis_FOUND TRUE)
+endif()
+
+if(Vorbis_Enc_LIBRARY AND Vorbis_Enc_INCLUDE_DIR AND Vorbis_Vorbis_FOUND)
+  set(Vorbis_Enc_FOUND TRUE)
+endif()
+
+if(Vorbis_Vorbis_FOUND AND Vorbis_File_LIBRARY AND Vorbis_File_INCLUDE_DIR)
+  set(Vorbis_File_FOUND TRUE)
+endif()
+
+find_package_handle_standard_args(Vorbis
+  REQUIRED_VARS
+    Vorbis_Vorbis_LIBRARY
+    Vorbis_Vorbis_INCLUDE_DIR
+    Ogg_FOUND
+  HANDLE_COMPONENTS
+  VERSION_VAR Vorbis_VERSION)
+
+
+if(Vorbis_Vorbis_FOUND)
+  set(Vorbis_Vorbis_INCLUDE_DIRS ${Vorbis_Vorbis_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS})
+  set(Vorbis_Vorbis_LIBRARIES ${Vorbis_Vorbis_LIBRARY} ${Ogg_LIBRARIES})
+  if(NOT TARGET Vorbis::vorbis)
+    add_library(Vorbis::vorbis UNKNOWN IMPORTED)
+    set_target_properties(Vorbis::vorbis PROPERTIES
+      INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Vorbis_INCLUDE_DIR}"
+      IMPORTED_LOCATION "${Vorbis_Vorbis_LIBRARY}"
+      INTERFACE_LINK_LIBRARIES Ogg::ogg
+    )
+  endif()
+
+  if(Vorbis_Enc_FOUND)
+    set(Vorbis_Enc_INCLUDE_DIRS ${Vorbis_Enc_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS})
+    set(Vorbis_Enc_LIBRARIES ${Vorbis_Enc_LIBRARY} ${Vorbis_Vorbis_LIBRARIES})
+    if(NOT TARGET Vorbis::vorbisenc)
+      add_library(Vorbis::vorbisenc UNKNOWN IMPORTED)
+      set_target_properties(Vorbis::vorbisenc PROPERTIES
+        INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_Enc_INCLUDE_DIR}"
+        IMPORTED_LOCATION "${Vorbis_Enc_LIBRARY}"
+        INTERFACE_LINK_LIBRARIES Vorbis::vorbis
+      )
+    endif()
+  endif()
+
+  if(Vorbis_File_FOUND)
+    set(Vorbis_File_INCLUDE_DIRS ${Vorbis_File_INCLUDE_DIR} ${Ogg_INCLUDE_DIRS})
+    set(Vorbis_File_LIBRARIES ${Vorbis_File_LIBRARY} ${Vorbis_Vorbis_LIBRARIES})
+    if(NOT TARGET Vorbis::vorbisfile)
+      add_library(Vorbis::vorbisfile UNKNOWN IMPORTED)
+      set_target_properties(Vorbis::vorbisfile PROPERTIES
+        INTERFACE_INCLUDE_DIRECTORIES "${Vorbis_File_INCLUDE_DIR}"
+        IMPORTED_LOCATION "${Vorbis_File_LIBRARY}"
+        INTERFACE_LINK_LIBRARIES Vorbis::vorbis
+      )
+    endif()
+  endif()
+
+endif()
+
+mark_as_advanced(Vorbis_Vorbis_INCLUDE_DIR Vorbis_Vorbis_LIBRARY)
+mark_as_advanced(Vorbis_Enc_INCLUDE_DIR Vorbis_Enc_LIBRARY)
+mark_as_advanced(Vorbis_File_INCLUDE_DIR Vorbis_File_LIBRARY)
--- /dev/null
+++ b/cmake/SampleRateConfig.cmake.in
@@ -1,0 +1,1 @@
+include(${CMAKE_CURRENT_LIST_DIR}/SampleRateTargets.cmake)
--- a/doc/win32.html
+++ b/doc/win32.html
@@ -57,74 +57,17 @@
 <TD VALIGN="top">
 <DIV CLASS="block">
 
-<H1><B>Compiling on Win32.</B></H1>
+<H1>Compiling on Win32</H1>
 <P>
-For Win32 there is a Microsoft Visual C++ compatible makefile in the <B>Win32\</B>
-directory and a MSDOS batch file in the top level directory of the distribution. 
+	You can use <A HREF="https://cmake.org/">CMake</A> to generate Visual Studio project.
+	The configuration process is described <A HREF="https://cmake.org/runningcmake/">here</A>.
 </P>
 <P>
-To build the examples programs you will need to download the precompiled
-win32 or win64
-	<A HREF="https://github.com/libsndfile/libsndfile/releases">libsndfile</A>
-binary and install them.
-
-</P>
-<P>
-Making the libsamplerate DLL on Win32 involves the following:
-</P>
-<OL>
-	<LI> Using WinZip in the GUI, open the libsamplerate-0.X.Y.tar.gz file and 
-			extract the files into a directory. The following example assumes 
-		<B>C:\</B>.
-	<LI> In the directory containing the extracted files, find the file 
-	    	<B>Win32\Makefile.msvc</B> and open it in a text editor (ie Notepad or 
-			similar). 
-	<LI> Find the line which starts with <B>MSVCDir</B> and modify the directory
-		    path to point to the location of MSVC++ on your machine. This allows the
-			makefile to inform the compiler of the location of the standard header
-			files.
-    <LI> Copy <B>libsndfile-1.dll</B>, <B>libsndfile-1.lib</B> and
-			<B>libsndfile-1.def</B> from the directory libsndfile was installed in
-			to the the directory containing libsamplerate.
-    <LI> Copy the header file <B>include/sndfile.h</B> from where libsndfile was
-			installed to the <B>Win32</B> directory under the libsamplerate
-			directory.
-	<LI> Open a Command Shell and cd into the libsamplerate-0.X.Y directory.
-	<LI> Make sure that the program <B>nmake</B> (which is part of the MSCV++ 
-			package) is in a directory which is part of your <B>PATH</B> variable.
-	<LI> Type in the command 
-		<PRE>    C:\libsamplerate-0.X.Y> make
-		</PRE>
-			and press &lt;return&gt;. You should now see a a large number of compile
-			commands as libsamplerate.dll is built. 
-	<LI> To check that the built DLL has been compiled correctly type in and run the
-			command
-		<PRE>    C:\libsamplerate-0.X.Y> make check
-		</PRE>
-			which will compile a set of test programs and run them. 
-			If any of the programs fail the error message will be help in debugging 
-			the problem.
-			(Note that some of the tests require libsndfile or libfftw/librfftw and
-			are not able to run on Win32).
-</OL>
-<P>
-At the end of the above procedure, you will find the DLL, <B>libsamplerate.dll</B>, a
-LIB file <B>libsamplerate.lib</B> in the current directory. These two files, along
-with the header file <B>samplerate.h</B> (in the <B>src\</B> directory) are all that 
-you need to copy to your project in order to use libsamplerate.
-</P>
-
-<H2><BR>Compile Problems</H2>
-<P>
-If you run into compile problems using the above procedure, you should 
-	<A HREF="lists.html"> join the main mailing list </A>
-and post your problem and/or questions there. 
-Please include any error messages generated during step 6 above.
-</P>
-
-<P>
-If you are using some other method to compile the libsamplerate DLL you are 
-probably on your own.
+	The libsamplerate library itself does not require any dependencies, but if you want to build
+	examples and tests, you will need the <A HREF="https://github.com/libsndfile/libsndfile">libsndfile</A>
+	and <A HREF="http://www.fftw.org/">FFTW</A> libraries. The easiest way to install them is to use a package
+	manager, such as <A HREF="">Vcpkg</A>. Their README.md contains detailed installation instructions for
+	supported platforms. Libsamplerate requires the <CODE>libsndfile</CODE> and <CODE>fftw3</CODE> packages.
 </P>
 <BR>