mirror of
https://github.com/ZDoom/ZMusic.git
synced 2025-04-19 07:21:21 +00:00
Compare commits
45 commits
Author | SHA1 | Date | |
---|---|---|---|
|
6928b8609d | ||
|
f6facdaa68 | ||
|
7e369774d5 | ||
|
4cc05f7584 | ||
|
628cd49221 | ||
|
7062053c04 | ||
|
3944bbc756 | ||
|
519b76b6e7 | ||
|
89f3d65734 | ||
|
6c5cf572aa | ||
|
b71e1a2639 | ||
|
fd03bca3ff | ||
|
05601a9ee1 | ||
|
1a1499d20e | ||
|
0b9d08d243 | ||
|
7307ecfc93 | ||
|
50ad730c38 | ||
|
b31b43efd0 | ||
|
7476a18975 | ||
|
3eabbd3598 | ||
|
5ce525efc7 | ||
|
26c889088d | ||
|
33de9d93fc | ||
|
3e1deba3a2 | ||
|
b5bd930369 | ||
|
576b7da64d | ||
|
e970fb15f0 | ||
|
1d5e34466d | ||
|
0a7dc86a55 | ||
|
a036a16450 | ||
|
fc30a8f1e4 | ||
|
22ab5b210c | ||
|
7695852856 | ||
|
75d2994b4b | ||
|
faa997b986 | ||
|
5bd573478b | ||
|
36a5308de1 | ||
|
1dda85bbe1 | ||
|
7a7ee92ff8 | ||
|
4725517832 | ||
|
8ebcd430b2 | ||
|
dad5c5a765 | ||
|
da12efde2b | ||
|
43203cb207 | ||
|
47475495f4 |
380 changed files with 141606 additions and 28119 deletions
114
.github/workflows/continuous_integration.yml
vendored
114
.github/workflows/continuous_integration.yml
vendored
|
@ -10,80 +10,65 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: "Visual Studio - Release",
|
||||
os: windows-2019,
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Visual Studio - Debug",
|
||||
os: windows-2019,
|
||||
build_type: "Debug"
|
||||
}
|
||||
- {
|
||||
name: "macOS Clang - Dynamic Deps",
|
||||
os: macos-10.15,
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "macOS Clang - Static Deps",
|
||||
os: macos-10.15,
|
||||
build_type: "Release",
|
||||
extra_options: "-DDYN_FLUIDSYNTH=OFF -DDYN_MPG123=OFF -DDYN_SNDFILE=OFF"
|
||||
}
|
||||
- {
|
||||
name: "Linux GCC - Dynamic Deps",
|
||||
os: ubuntu-20.04,
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Linux GCC - Static Deps",
|
||||
os: ubuntu-20.04,
|
||||
build_type: "Release",
|
||||
extra_options: "-DDYN_FLUIDSYNTH=OFF -DDYN_MPG123=OFF -DDYN_SNDFILE=OFF"
|
||||
}
|
||||
- {
|
||||
name: "Linux Clang - Dynamic Deps",
|
||||
os: ubuntu-20.04,
|
||||
build_type: "Release",
|
||||
extra_options: "-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++"
|
||||
}
|
||||
- {
|
||||
name: "Linux Clang - Static Deps",
|
||||
os: ubuntu-20.04,
|
||||
build_type: "Release",
|
||||
extra_options: "-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DDYN_FLUIDSYNTH=OFF -DDYN_MPG123=OFF -DDYN_SNDFILE=OFF"
|
||||
}
|
||||
- name: Visual Studio - Release
|
||||
os: windows-latest
|
||||
build_type: Release
|
||||
|
||||
- name: Visual Studio - Debug
|
||||
os: windows-latest
|
||||
build_type: Debug
|
||||
|
||||
- name: macOS Clang - Dynamic Deps
|
||||
os: macos-latest
|
||||
build_type: Release
|
||||
|
||||
- name: macOS Clang - Static Deps
|
||||
os: macos-latest
|
||||
build_type: Release
|
||||
cmake_options: -DDYN_FLUIDSYNTH=OFF -DDYN_MPG123=OFF -DDYN_SNDFILE=OFF
|
||||
deps_cmd: brew install libsndfile mpg123
|
||||
|
||||
- name: Linux GCC - Dynamic Deps
|
||||
os: ubuntu-latest
|
||||
build_type: Release
|
||||
deps_cmd: sudo apt update && sudo apt install libglib2.0-dev
|
||||
|
||||
- name: Linux GCC - Static Deps
|
||||
os: ubuntu-latest
|
||||
build_type: Release
|
||||
cmake_options: -DDYN_FLUIDSYNTH=OFF -DDYN_MPG123=OFF -DDYN_SNDFILE=OFF
|
||||
deps_cmd: sudo apt update && sudo apt install libasound2-dev libglib2.0-dev libmpg123-dev libsndfile1-dev
|
||||
|
||||
- name: Linux Clang - Dynamic Deps
|
||||
os: ubuntu-latest
|
||||
build_type: Release
|
||||
cmake_options: -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++
|
||||
deps_cmd: sudo apt update && sudo apt install libglib2.0-dev
|
||||
|
||||
- name: Linux Clang - Static Deps
|
||||
os: ubuntu-latest
|
||||
build_type: Release
|
||||
cmake_options: -DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++ -DDYN_FLUIDSYNTH=OFF -DDYN_MPG123=OFF -DDYN_SNDFILE=OFF
|
||||
deps_cmd: sudo apt update && sudo apt install libasound2-dev libglib2.0-dev libmpg123-dev libsndfile1-dev
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v1
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install Dependencies
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ runner.os }}" == 'Linux' ]]; then
|
||||
sudo apt update
|
||||
sudo apt install libasound2-dev libfluidsynth-dev libmpg123-dev libsndfile1-dev
|
||||
elif [[ "${{ runner.os }}" == 'macOS' ]]; then
|
||||
brew install fluidsynth mpg123 libsndfile
|
||||
fi
|
||||
${{ matrix.config.deps_cmd }}
|
||||
|
||||
- name: Configure
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DCMAKE_INSTALL_PREFIX=../build_install ${{ matrix.config.extra_options }} ..
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=${{ matrix.config.build_type }} -DCMAKE_INSTALL_PREFIX=./build_install ${{ matrix.config.cmake_options }} .
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
cd build
|
||||
if [[ "${{ runner.os }}" == 'Windows' ]]; then
|
||||
cmake --build . --target install --config ${{ matrix.config.build_type }} -- -maxcpucount -verbosity:minimal
|
||||
else
|
||||
cmake --build . --target install -- --jobs=2 --keep-going
|
||||
fi
|
||||
export MAKEFLAGS=--keep-going
|
||||
cmake --build build --target install --config ${{ matrix.config.build_type }} --parallel 3
|
||||
|
||||
- name: Test
|
||||
shell: bash
|
||||
|
@ -92,7 +77,7 @@ jobs:
|
|||
mkdir build
|
||||
cd build
|
||||
declare -x PREFIX=`pwd`/../../../build_install
|
||||
cmake -DCMAKE_PREFIX_PATH=${PREFIX} ${{ matrix.config.extra_options }} ..
|
||||
cmake -DCMAKE_PREFIX_PATH=${PREFIX} ${{ matrix.config.cmake_options }} ..
|
||||
cmake --build . --config ${{ matrix.config.build_type }}
|
||||
if [[ "${{ runner.os }}" == 'macOS' ]]; then
|
||||
declare -x DYLD_LIBRARY_PATH=${DYLD_LIBRARY_PATH}:${PREFIX}
|
||||
|
@ -103,3 +88,10 @@ jobs:
|
|||
else
|
||||
./list_midi_devices
|
||||
fi
|
||||
|
||||
- name: Upload Install Directory
|
||||
if: false # Remove this line to upload build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ${{ matrix.config.name }}
|
||||
path: build_install
|
||||
|
|
|
@ -1,9 +1,24 @@
|
|||
cmake_minimum_required(VERSION 3.13...3.19)
|
||||
|
||||
if (VCPKG_LIBSNDFILE)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "vcpkg-libsndfile")
|
||||
endif()
|
||||
|
||||
project(ZMusic
|
||||
VERSION 1.1.10
|
||||
VERSION 1.1.14
|
||||
LANGUAGES C CXX
|
||||
)
|
||||
|
||||
if (VCPKG_TOOLCHAIN)
|
||||
if(VCPKG_TARGET_TRIPLET MATCHES "-static$")
|
||||
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
endif()
|
||||
|
||||
option(VCPKG_LIBSNDFILE "Import libsndfile from vcpkg" OFF)
|
||||
else()
|
||||
set(VCPKG_MANIFEST_FEATURES)
|
||||
endif()
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)
|
||||
|
||||
include(CMakePackageConfigHelpers)
|
||||
|
@ -113,6 +128,11 @@ endif()
|
|||
# Initialize our list of find_package dependencies for configure_package_config_file
|
||||
set(ZMUSIC_PACKAGE_DEPENDENCIES "" CACHE INTERNAL "")
|
||||
|
||||
if (WIN32 AND MINGW)
|
||||
add_compile_definitions(-D_UNICODE -DUNICODE)
|
||||
add_compile_definitions(-D__USE_MINGW_ANSI_STDIO=1)
|
||||
endif()
|
||||
|
||||
add_subdirectory(thirdparty)
|
||||
add_subdirectory(source)
|
||||
|
||||
|
|
|
@ -151,6 +151,7 @@ typedef enum EIntConfigKey_
|
|||
|
||||
zmusic_snd_mididevice,
|
||||
zmusic_snd_outputrate,
|
||||
zmusic_mod_preferredplayer,
|
||||
|
||||
NUM_ZMUSIC_INT_CONFIGS
|
||||
} EIntConfigKey;
|
||||
|
|
|
@ -18,9 +18,9 @@
|
|||
*/
|
||||
|
||||
|
||||
Dynamic Universal Music Bibliotheque
|
||||
Dynamic Universal Music Bibliotheque, Version 0.9.3
|
||||
|
||||
Copyright (C) 2001-2003 Ben Davis, Robert J Ohannessian and Julien Cugniere
|
||||
Copyright (C) 2001-2005 Ben Davis, Robert J Ohannessian and Julien Cugniere
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty.
|
||||
In no event shall the authors be held liable for any damages arising from the
|
||||
|
@ -39,16 +39,49 @@ freely, subject to the following restrictions:
|
|||
[Note that the above point asks for a link to DUMB, not just a mention.
|
||||
Googling for DUMB doesn't help much! The URL is "http://dumb.sf.net/".]
|
||||
|
||||
[The only reason why the link is not strictly required is that such a
|
||||
requirement prevents DUMB from being used in projects with certain other
|
||||
licences, notably the GPL. See http://www.gnu.org/philosophy/bsd.html .]
|
||||
[The link was originally strictly required. This was changed for two
|
||||
reasons. Firstly, if many projects request an acknowledgement, the list of
|
||||
acknowledgements can become quite unmanageable. Secondly, DUMB was placing
|
||||
a restriction on the code using it, preventing people from using the GNU
|
||||
General Public Licence which disallows any such restrictions. See
|
||||
http://www.gnu.org/philosophy/bsd.html for more information on this
|
||||
subject. However, if DUMB plays a significant part in your project, we do
|
||||
urge you to acknowledge its use.]
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed from or altered in any source distribution.
|
||||
|
||||
4. If you are using the Program in someone else's bedroom at any Monday
|
||||
3:05 PM, you are not allowed to modify the Program for ten minutes. [This
|
||||
4. If you are using the Program in someone else's bedroom on any Monday at
|
||||
3:05 pm, you are not allowed to modify the Program for ten minutes. [This
|
||||
clause provided by Inphernic; every licence should contain at least one
|
||||
clause, the reasoning behind which is far from obvious.]
|
||||
|
||||
5. Users who wish to use DUMB for the specific purpose of playing music are
|
||||
required to feed their dog on every full moon (if deemed appropriate).
|
||||
[This clause provided by Allefant, who couldn't remember what Inphernic's
|
||||
clause was.]
|
||||
|
||||
6. No clause in this licence shall prevent this software from being depended
|
||||
upon by a product licensed under the GNU General Public Licence. If such a
|
||||
clause is deemed to exist, Debian, then it shall be respected in spirit as
|
||||
far as possible and all other clauses shall continue to apply in full
|
||||
force.
|
||||
|
||||
8. Take the number stated as introducing this clause. Multiply it by two,
|
||||
then subtract four. Now insert a '+' between the two digits and evaluate
|
||||
the resulting sum. Call the result 'x'. If you have not yet concluded that
|
||||
every numbered clause in this licence whose ordinal number is strictly
|
||||
greater than 'x' (with the exception of the present clause) is null and
|
||||
void, Debian, then you are hereby informed that laughter is good for one's
|
||||
health and you are warmly suggested to do it. By the way, Clauses 4, 5 and
|
||||
6 are null and void. Incidentally, I like Kubuntu. The work you guys do is
|
||||
awesome. (Lawyers, on the other hand ...)
|
||||
|
||||
We regret that we cannot provide any warranty, not even the implied warranty
|
||||
of merchantability or fitness for a particular purpose.
|
||||
|
||||
Some files generated or copied by automake, autoconf and friends are
|
||||
available in an extra download. These fall under separate licences but are
|
||||
all free to distribute. Please check their licences as necessary.
|
||||
|
|
|
@ -25,6 +25,7 @@ INTERFACE
|
|||
streamsources/music_dumb.cpp
|
||||
streamsources/music_gme.cpp
|
||||
streamsources/music_libsndfile.cpp
|
||||
streamsources/music_libxmp.cpp
|
||||
streamsources/music_opl.cpp
|
||||
streamsources/music_xa.cpp
|
||||
musicformats/music_stream.cpp
|
||||
|
@ -65,7 +66,12 @@ if(NOT WIN32 AND NOT APPLE)
|
|||
determine_package_config_dependency(ZMUSIC_PACKAGE_DEPENDENCIES TARGET Threads::Threads MODULE Threads)
|
||||
endif()
|
||||
|
||||
option(DYN_SNDFILE "Dynamically load libsndfile" ON)
|
||||
if ("vcpkg-libsndfile" IN_LIST VCPKG_MANIFEST_FEATURES)
|
||||
set(DYN_SNDFILE 0)
|
||||
else()
|
||||
option(DYN_SNDFILE "Dynamically load libsndfile" ON)
|
||||
endif()
|
||||
|
||||
if(DYN_SNDFILE)
|
||||
target_compile_definitions(zmusic-obj INTERFACE HAVE_SNDFILE DYN_SNDFILE)
|
||||
else()
|
||||
|
@ -78,10 +84,14 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
option(DYN_MPG123 "Dynamically load libmpg123" ON)
|
||||
if ("vcpkg-libsndfile" IN_LIST VCPKG_MANIFEST_FEATURES)
|
||||
set(DYN_MPG123 0)
|
||||
else()
|
||||
option(DYN_MPG123 "Dynamically load libmpg123" ON)
|
||||
endif()
|
||||
if(DYN_MPG123)
|
||||
target_compile_definitions(zmusic-obj INTERFACE HAVE_MPG123 DYN_MPG123)
|
||||
else()
|
||||
elseif(NOT ("vcpkg-libsndfile" IN_LIST VCPKG_MANIFEST_FEATURES))
|
||||
find_package(MPG123)
|
||||
|
||||
if(MPG123_FOUND)
|
||||
|
@ -91,19 +101,6 @@ else()
|
|||
endif()
|
||||
endif()
|
||||
|
||||
option(DYN_FLUIDSYNTH "Dynamically load fluidsynth" ON)
|
||||
if(DYN_FLUIDSYNTH)
|
||||
target_compile_definitions(zmusic-obj INTERFACE HAVE_FLUIDSYNTH DYN_FLUIDSYNTH)
|
||||
else()
|
||||
find_package(FluidSynth)
|
||||
|
||||
if(FLUIDSYNTH_FOUND)
|
||||
target_compile_definitions(zmusic-obj INTERFACE HAVE_FLUIDSYNTH)
|
||||
target_link_libraries(zmusic-obj INTERFACE libfluidsynth)
|
||||
determine_package_config_dependency(ZMUSIC_PACKAGE_DEPENDENCIES TARGET libfluidsynth MODULE FluidSynth)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# System MIDI support
|
||||
if(WIN32)
|
||||
target_compile_definitions(zmusic-obj INTERFACE HAVE_SYSTEM_MIDI)
|
||||
|
@ -131,7 +128,7 @@ if(WIN32)
|
|||
)
|
||||
endif()
|
||||
|
||||
target_link_libraries(zmusic-obj INTERFACE dumb gme ZLIB::ZLIB ${CMAKE_DL_LIBS})
|
||||
target_link_libraries(zmusic-obj INTERFACE dumb gme libxmp miniz ${CMAKE_DL_LIBS})
|
||||
|
||||
target_include_directories(zmusic-obj
|
||||
INTERFACE
|
||||
|
@ -155,8 +152,8 @@ use_fast_math(zmusiclite)
|
|||
target_include_directories(zmusic INTERFACE $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${ZMusic_SOURCE_DIR}/include>)
|
||||
target_include_directories(zmusiclite INTERFACE $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${ZMusic_SOURCE_DIR}/include>)
|
||||
|
||||
target_link_libraries_hidden(zmusic zmusic-obj adl oplsynth opn timidity timidityplus wildmidi)
|
||||
target_link_libraries_hidden(zmusiclite zmusic-obj)
|
||||
target_link_libraries_hidden(zmusic zmusic-obj adl oplsynth opn timidity timidityplus wildmidi fluidsynth)
|
||||
target_link_libraries_hidden(zmusiclite zmusic-obj fluidsynth)
|
||||
|
||||
target_compile_definitions(zmusic PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:zmusic,TYPE>,STATIC_LIBRARY>:ZMUSIC_STATIC>)
|
||||
target_compile_definitions(zmusiclite PRIVATE ZMUSIC_LITE=1 PUBLIC $<$<STREQUAL:$<TARGET_PROPERTY:zmusiclite,TYPE>,STATIC_LIBRARY>:ZMUSIC_STATIC>)
|
||||
|
@ -169,6 +166,10 @@ PROPERTIES
|
|||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
)
|
||||
|
||||
if (VCPKG_TOOLCHAIN)
|
||||
x_vcpkg_install_local_dependencies(TARGETS zmusic zmusiclite DESTINATION ".")
|
||||
endif()
|
||||
|
||||
if(ZMUSIC_INSTALL)
|
||||
install(TARGETS zmusic EXPORT ZMusicFullTargets
|
||||
PUBLIC_HEADER
|
||||
|
|
19916
source/data/xg.h
19916
source/data/xg.h
File diff suppressed because it is too large
Load diff
Binary file not shown.
|
@ -43,14 +43,14 @@ FModule SndFileModule{"SndFile"};
|
|||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define SNDFILELIB "libsndfile-1.dll"
|
||||
static const char* libnames[] = { "sndfile.dll", "libsndfile-1.dll" };
|
||||
#elif defined(__APPLE__)
|
||||
#define SNDFILELIB "libsndfile.1.dylib"
|
||||
static const char* libnames[] = { "libsndfile.1.dylib" };
|
||||
#else
|
||||
#define SNDFILELIB "libsndfile.so.1"
|
||||
static const char* libnames[] = { "libsndfile.so.1" };
|
||||
#endif
|
||||
|
||||
bool IsSndFilePresent()
|
||||
extern "C" int IsSndFilePresent()
|
||||
{
|
||||
#if !defined DYN_SNDFILE
|
||||
return true;
|
||||
|
@ -61,14 +61,17 @@ bool IsSndFilePresent()
|
|||
if (!done)
|
||||
{
|
||||
done = true;
|
||||
auto abspath = FModule_GetProgDir() + "/" SNDFILELIB;
|
||||
cached_result = SndFileModule.Load({abspath.c_str(), SNDFILELIB});
|
||||
for (auto libname : libnames)
|
||||
{
|
||||
auto abspath = FModule_GetProgDir() + "/" + libname;
|
||||
cached_result = SndFileModule.Load({ abspath.c_str(), libname });
|
||||
if (cached_result) break;
|
||||
}
|
||||
}
|
||||
return cached_result;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
sf_count_t SndFileDecoder::file_get_filelen(void *user_data)
|
||||
{
|
||||
auto &reader = reinterpret_cast<SndFileDecoder*>(user_data)->Reader;
|
||||
|
@ -206,4 +209,60 @@ size_t SndFileDecoder::getSampleLength()
|
|||
return (size_t)((SndInfo.frames > 0) ? SndInfo.frames : 0);
|
||||
}
|
||||
|
||||
// band-aid for FluidSynth, which is C, not C++ and cannot use the module interface.
|
||||
#ifdef DYN_SNDFILE
|
||||
|
||||
#undef sf_open_virtual
|
||||
extern "C" SNDFILE * sf_open_virtual(SF_VIRTUAL_IO * sfvirtual, int mode, SF_INFO * sfinfo, void* user_data)
|
||||
{
|
||||
return p_sf_open_virtual(sfvirtual, mode, sfinfo, user_data);
|
||||
}
|
||||
|
||||
extern "C" const char* sf_strerror(SNDFILE * sndfile)
|
||||
{
|
||||
return p_sf_strerror(sndfile);
|
||||
}
|
||||
|
||||
extern "C" sf_count_t sf_readf_short(SNDFILE * sndfile, short* ptr, sf_count_t frames)
|
||||
{
|
||||
return p_sf_readf_short(sndfile, ptr, frames);
|
||||
}
|
||||
|
||||
#undef sf_close
|
||||
extern "C" int sf_close(SNDFILE * sndfile)
|
||||
{
|
||||
return p_sf_close(sndfile);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#else // in case someone decided to build without sndfile support
|
||||
|
||||
extern "C" int IsSndFilePresent()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
extern "C" SNDFILE * sf_open_virtual(SF_VIRTUAL_IO * sfvirtual, int mode, SF_INFO * sfinfo, void* user_data)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
extern "C" const char* sf_strerror(SNDFILE * sndfile)
|
||||
{
|
||||
return "no sndfile support";
|
||||
}
|
||||
|
||||
extern "C" sf_count_t sf_readf_short(SNDFILE * sndfile, short* ptr, sf_count_t frames)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int sf_close(SNDFILE * sndfile)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ private:
|
|||
static sf_count_t file_tell(void *user_data);
|
||||
};
|
||||
|
||||
#else
|
||||
#include "../thirdparty/sndfile.h"
|
||||
#endif
|
||||
|
||||
#endif /* SNDFILE_DECODER_H */
|
||||
|
|
|
@ -1,12 +1,16 @@
|
|||
#ifndef SNDDEF_H
|
||||
#define SNDDEF_H
|
||||
|
||||
|
||||
|
||||
#if defined HAVE_SNDFILE && defined DYN_SNDFILE
|
||||
|
||||
#define DEFINE_ENTRY(type, name) static TReqProc<SndFileModule, type> p_##name{#name};
|
||||
DEFINE_ENTRY(const char* (*)(SNDFILE* sndfile), sf_strerror)
|
||||
DEFINE_ENTRY(int (*)(SNDFILE *sndfile), sf_close)
|
||||
DEFINE_ENTRY(SNDFILE* (*)(SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data), sf_open_virtual)
|
||||
DEFINE_ENTRY(sf_count_t (*)(SNDFILE *sndfile, float *ptr, sf_count_t frames), sf_readf_float)
|
||||
DEFINE_ENTRY(sf_count_t(*)(SNDFILE* sndfile, short* ptr, sf_count_t frames), sf_readf_short)
|
||||
DEFINE_ENTRY(sf_count_t (*)(SNDFILE *sndfile, sf_count_t frames, int whence), sf_seek)
|
||||
#undef DEFINE_ENTRY
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
|
|
@ -35,27 +35,19 @@
|
|||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/mus2midi.h"
|
||||
#include "loader/i_module.h"
|
||||
|
||||
// FluidSynth implementation of a MIDI device -------------------------------
|
||||
|
||||
FluidConfig fluidConfig;
|
||||
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
|
||||
#if !defined DYN_FLUIDSYNTH
|
||||
#include <fluidsynth.h>
|
||||
#else
|
||||
#include "loader/i_module.h"
|
||||
extern FModule FluidSynthModule;
|
||||
|
||||
struct fluid_settings_t;
|
||||
struct fluid_synth_t;
|
||||
#endif
|
||||
#include "../thirdparty/fluidsynth/include/fluidsynth.h"
|
||||
|
||||
class FluidSynthMIDIDevice : public SoftSynthMIDIDevice
|
||||
{
|
||||
|
@ -84,64 +76,10 @@ protected:
|
|||
int FluidSettingsResultOk = FLUID_OK;
|
||||
int FluidSettingsResultFailed = FLUID_FAILED;
|
||||
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
enum { FLUID_FAILED = -1, FLUID_OK = 0 };
|
||||
static TReqProc<FluidSynthModule, void (*)(int *, int*, int*)> fluid_version;
|
||||
static TReqProc<FluidSynthModule, fluid_settings_t *(*)()> new_fluid_settings;
|
||||
static TReqProc<FluidSynthModule, fluid_synth_t *(*)(fluid_settings_t *)> new_fluid_synth;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> delete_fluid_synth;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_settings_t *)> delete_fluid_settings;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, double)> fluid_settings_setnum;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, const char *)> fluid_settings_setstr;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, int)> fluid_settings_setint;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_settings_t *, const char *, int *)> fluid_settings_getint;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, int)> fluid_synth_set_reverb_on;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, int)> fluid_synth_set_chorus_on;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_set_interp_method;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int)> fluid_synth_set_polyphony;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> fluid_synth_get_polyphony;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> fluid_synth_get_active_voice_count;
|
||||
static TReqProc<FluidSynthModule, double (*)(fluid_synth_t *)> fluid_synth_get_cpu_load;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *)> fluid_synth_system_reset;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int, int)> fluid_synth_noteon;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_noteoff;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int, int)> fluid_synth_cc;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_program_change;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_channel_pressure;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, int)> fluid_synth_pitch_bend;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, int, void *, int, int, void *, int, int)> fluid_synth_write_float;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, const char *, int)> fluid_synth_sfload;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, double, double, double, double)> fluid_synth_set_reverb;
|
||||
static TReqProc<FluidSynthModule, void (*)(fluid_synth_t *, int, double, double, double, int)> fluid_synth_set_chorus;
|
||||
static TReqProc<FluidSynthModule, int (*)(fluid_synth_t *, const char *, int, char *, int *, int *, int)> fluid_synth_sysex;
|
||||
|
||||
bool LoadFluidSynth(const char *fluid_lib);
|
||||
#endif
|
||||
};
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef _M_X64
|
||||
#define FLUIDSYNTHLIBS { "fluidsynth.dll", "libfluidsynth.dll" }
|
||||
#else
|
||||
#define FLUIDSYNTHLIBS { "fluidsynth64.dll", "libfluidsynth64.dll" }
|
||||
#endif
|
||||
#else
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define FLUIDSYNTHLIBS { "libfluidsynth.1.dylib", "libfluidsynth.2.dylib", "libfluidsynth.3.dylib" }
|
||||
#else // !__APPLE__
|
||||
#define FLUIDSYNTHLIBS { "libfluidsynth.so.1", "libfluidsynth.so.2", "libfluidsynth.so.3" }
|
||||
#endif // __APPLE__
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
@ -173,21 +111,6 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, std::vector<std::stri
|
|||
|
||||
FluidSynth = NULL;
|
||||
FluidSettings = NULL;
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
if (!LoadFluidSynth(fluidConfig.fluid_lib.c_str()))
|
||||
{
|
||||
throw std::runtime_error("Failed to load FluidSynth.\n");
|
||||
}
|
||||
#endif
|
||||
int major = 0, minor = 0, micro = 0;
|
||||
fluid_version(&major, &minor, µ);
|
||||
|
||||
if (major < 2)
|
||||
{
|
||||
// FluidSynth 1.x: fluid_settings_...() functions return 1 on success and 0 otherwise
|
||||
FluidSettingsResultOk = 1;
|
||||
FluidSettingsResultFailed = 0;
|
||||
}
|
||||
|
||||
FluidSettings = new_fluid_settings();
|
||||
if (FluidSettings == NULL)
|
||||
|
@ -219,8 +142,8 @@ FluidSynthMIDIDevice::FluidSynthMIDIDevice(int samplerate, std::vector<std::stri
|
|||
return;
|
||||
}
|
||||
|
||||
delete_fluid_settings(FluidSettings);
|
||||
delete_fluid_synth(FluidSynth);
|
||||
delete_fluid_settings(FluidSettings);
|
||||
FluidSynth = nullptr;
|
||||
FluidSettings = nullptr;
|
||||
throw std::runtime_error("Failed to load any MIDI patches.\n");
|
||||
|
@ -316,9 +239,10 @@ void FluidSynthMIDIDevice::HandleEvent(int status, int parm1, int parm2)
|
|||
|
||||
void FluidSynthMIDIDevice::HandleLongEvent(const uint8_t *data, int len)
|
||||
{
|
||||
if (len > 1 && (data[0] == 0xF0 || data[0] == 0xF7))
|
||||
constexpr int excludedByteCount = 2; // 0xF0 (first byte) and 0xF7 (last byte) are not given to FluidSynth.
|
||||
if (len > excludedByteCount && data[0] == 0xF0 && data[len - 1] == 0xF7)
|
||||
{
|
||||
fluid_synth_sysex(FluidSynth, (const char *)data + 1, len - 1, NULL, NULL, NULL, 0);
|
||||
fluid_synth_sysex(FluidSynth, (const char *)data + 1, len - excludedByteCount, NULL, NULL, NULL, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -484,93 +408,6 @@ std::string FluidSynthMIDIDevice::GetStats()
|
|||
return out;
|
||||
}
|
||||
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FluidSynthMIDIDevice :: LoadFluidSynth
|
||||
//
|
||||
// Returns true if the FluidSynth library was successfully loaded.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
FModuleMaybe<DYN_FLUIDSYNTH> FluidSynthModule{"FluidSynth"};
|
||||
|
||||
#define DYN_FLUID_SYM(x) decltype(FluidSynthMIDIDevice::x) FluidSynthMIDIDevice::x{#x}
|
||||
DYN_FLUID_SYM(fluid_version);
|
||||
DYN_FLUID_SYM(new_fluid_settings);
|
||||
DYN_FLUID_SYM(new_fluid_synth);
|
||||
DYN_FLUID_SYM(delete_fluid_synth);
|
||||
DYN_FLUID_SYM(delete_fluid_settings);
|
||||
DYN_FLUID_SYM(fluid_settings_setnum);
|
||||
DYN_FLUID_SYM(fluid_settings_setstr);
|
||||
DYN_FLUID_SYM(fluid_settings_setint);
|
||||
DYN_FLUID_SYM(fluid_settings_getint);
|
||||
DYN_FLUID_SYM(fluid_synth_set_reverb_on);
|
||||
DYN_FLUID_SYM(fluid_synth_set_chorus_on);
|
||||
DYN_FLUID_SYM(fluid_synth_set_interp_method);
|
||||
DYN_FLUID_SYM(fluid_synth_set_polyphony);
|
||||
DYN_FLUID_SYM(fluid_synth_get_polyphony);
|
||||
DYN_FLUID_SYM(fluid_synth_get_active_voice_count);
|
||||
DYN_FLUID_SYM(fluid_synth_get_cpu_load);
|
||||
DYN_FLUID_SYM(fluid_synth_system_reset);
|
||||
DYN_FLUID_SYM(fluid_synth_noteon);
|
||||
DYN_FLUID_SYM(fluid_synth_noteoff);
|
||||
DYN_FLUID_SYM(fluid_synth_cc);
|
||||
DYN_FLUID_SYM(fluid_synth_program_change);
|
||||
DYN_FLUID_SYM(fluid_synth_channel_pressure);
|
||||
DYN_FLUID_SYM(fluid_synth_pitch_bend);
|
||||
DYN_FLUID_SYM(fluid_synth_write_float);
|
||||
DYN_FLUID_SYM(fluid_synth_sfload);
|
||||
DYN_FLUID_SYM(fluid_synth_set_reverb);
|
||||
DYN_FLUID_SYM(fluid_synth_set_chorus);
|
||||
DYN_FLUID_SYM(fluid_synth_sysex);
|
||||
|
||||
bool FluidSynthMIDIDevice::LoadFluidSynth(const char *fluid_lib)
|
||||
{
|
||||
static bool is_loaded = false;
|
||||
static bool is_checked = false;
|
||||
|
||||
if (!is_checked)
|
||||
{
|
||||
if (fluid_lib && strlen(fluid_lib) > 0)
|
||||
{
|
||||
is_loaded = FluidSynthModule.Load({ fluid_lib });
|
||||
if (!is_loaded)
|
||||
ZMusic_Printf(ZMUSIC_MSG_ERROR, "Could not load %s\n", fluid_lib);
|
||||
}
|
||||
|
||||
if (!is_loaded)
|
||||
{
|
||||
is_loaded = FluidSynthModule.Load(FLUIDSYNTHLIBS);
|
||||
if (!is_loaded)
|
||||
{
|
||||
std::string error = "Could not load ";
|
||||
bool need_or = false;
|
||||
|
||||
for (const char *library : FLUIDSYNTHLIBS)
|
||||
{
|
||||
if (need_or)
|
||||
error += " or ";
|
||||
else
|
||||
need_or = true;
|
||||
error += library;
|
||||
}
|
||||
|
||||
ZMusic_Printf(ZMUSIC_MSG_ERROR, "%s\n", error.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
is_checked = true;
|
||||
}
|
||||
|
||||
return is_loaded;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// sndfile
|
||||
//
|
||||
|
@ -685,12 +522,3 @@ MIDIDevice *CreateFluidSynthMIDIDevice(int samplerate, const char *Args)
|
|||
Fluid_SetupConfig(Args, fluid_patchset, true);
|
||||
return new FluidSynthMIDIDevice(samplerate, fluid_patchset);
|
||||
}
|
||||
#else
|
||||
|
||||
MIDIDevice* CreateFluidSynthMIDIDevice(int samplerate, const char* Args)
|
||||
{
|
||||
throw std::runtime_error("FlidSynth device not supported in this configuration");
|
||||
}
|
||||
|
||||
|
||||
#endif // HAVE_FLUIDSYNTH
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/mus2midi.h"
|
||||
|
@ -333,4 +334,4 @@ MIDIDevice* CreateOplMIDIDevice(const char* Args)
|
|||
{
|
||||
throw std::runtime_error("OPL device not supported in this configuration");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#include <stdexcept>
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
||||
|
@ -239,4 +240,4 @@ MIDIDevice* CreateTimidityPPMIDIDevice(const char* Args, int samplerate)
|
|||
{
|
||||
throw std::runtime_error("Timidity++ device not supported in this configuration");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "mididevice.h"
|
||||
#include "zmusic/m_swap.h"
|
||||
#include "fileio.h"
|
||||
#include <stdexcept>
|
||||
#include <errno.h>
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
||||
|
@ -278,4 +279,4 @@ MIDIDevice* CreateWildMIDIDevice(const char* Args, int samplerate)
|
|||
{
|
||||
throw std::runtime_error("WildMidi device not supported in this configuration");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <mmsystem.h>
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
#include <assert.h>
|
||||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
|
|
@ -134,8 +134,8 @@ void MUSSong2::DoInitialSetup()
|
|||
{
|
||||
for (int i = 0; i < 16; ++i)
|
||||
{
|
||||
LastVelocity[i] = 100;
|
||||
ChannelVolumes[i] = 127;
|
||||
LastVelocity[i] = 127;
|
||||
ChannelVolumes[i] = 100;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -34,8 +34,9 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <assert.h>
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
#include "zmusic/musinfo.h"
|
||||
|
@ -814,7 +815,7 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, uint32_t max_time)
|
|||
if (InitialPlayback)
|
||||
{
|
||||
InitialPlayback = false;
|
||||
// Send the GS System Reset SysEx message.
|
||||
// Send the GM System Enable SysEx message.
|
||||
events[0] = 0; // dwDeltaTime
|
||||
events[1] = 0; // dwStreamID
|
||||
events[2] = (MEVENT_LONGMSG << 24) | 6; // dwEvent
|
||||
|
@ -822,6 +823,15 @@ int MIDIStreamer::FillBuffer(int buffer_num, int max_events, uint32_t max_time)
|
|||
events[4] = MAKE_ID(0x01, 0xf7, 0x00, 0x00); // dwParms[1]
|
||||
events += 5;
|
||||
|
||||
// Send the GS DT1 MODE SET GS Reset SysEx message.
|
||||
events[0] = 0; // dwDeltaTime
|
||||
events[1] = 0; // dwStreamID
|
||||
events[2] = (MEVENT_LONGMSG << 24) | 11; // dwEvent
|
||||
events[3] = MAKE_ID(0xf0, 0x41, 0x7f, 0x42); // dwParms[0]
|
||||
events[4] = MAKE_ID(0x12, 0x40, 0x00, 0x7f); // dwParms[1]
|
||||
events[5] = MAKE_ID(0x00, 0x41, 0xf7, 0x00); // dwParms[2]
|
||||
events += 6;
|
||||
|
||||
// Send the full master volume SysEx message.
|
||||
events[0] = 0; // dwDeltaTime
|
||||
events[1] = 0; // dwStreamID
|
||||
|
|
|
@ -38,9 +38,11 @@
|
|||
//#define GME_DLL
|
||||
|
||||
#include <algorithm>
|
||||
#include <mutex>
|
||||
#include <stdexcept>
|
||||
|
||||
#include "streamsource.h"
|
||||
#include <gme/gme.h>
|
||||
#include <mutex>
|
||||
#include "fileio.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
|
180
source/streamsources/music_libxmp.cpp
Normal file
180
source/streamsources/music_libxmp.cpp
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
** music_libxmp.cpp
|
||||
** libxmp module player.
|
||||
**
|
||||
**---------------------------------------------------------------------------
|
||||
** Copyright 2024 Cacodemon345
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions
|
||||
** are met:
|
||||
**
|
||||
** 1. Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** 2. 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.
|
||||
** 3. The name of the author may not be used to endorse or promote products
|
||||
** derived from this software without specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
|
||||
**---------------------------------------------------------------------------
|
||||
**
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
#include <limits.h>
|
||||
#include "streamsource.h"
|
||||
|
||||
#define LIBXMP_STATIC 1
|
||||
#include "../libxmp/include/xmp.h"
|
||||
#include "zmusic/m_swap.h"
|
||||
#include "zmusic/mididefs.h"
|
||||
#include "zmusic/midiconfig.h"
|
||||
#include "fileio.h"
|
||||
|
||||
extern DumbConfig dumbConfig;
|
||||
|
||||
static unsigned long xmp_read(void *dest, unsigned long len, unsigned long nmemb, void *priv)
|
||||
{
|
||||
if (len == 0 || nmemb == 0)
|
||||
return (unsigned long)0;
|
||||
|
||||
MusicIO::FileInterface* interface = (MusicIO::FileInterface*)priv;
|
||||
|
||||
auto origpos = interface->tell();
|
||||
auto length = interface->read(dest, (int32_t)(len * nmemb));
|
||||
|
||||
if (length != len * nmemb)
|
||||
{
|
||||
// Let's hope the compiler doesn't misoptimize this.
|
||||
interface->seek(origpos + (length / len) * len, SEEK_SET);
|
||||
}
|
||||
return length / len;
|
||||
}
|
||||
|
||||
static struct xmp_callbacks callbacks =
|
||||
{
|
||||
xmp_read,
|
||||
[](void *priv, long offset, int whence) -> int { return ((MusicIO::FileInterface*)priv)->seek(offset, whence); },
|
||||
[](void *priv) -> long { return ((MusicIO::FileInterface*)priv)->tell(); },
|
||||
[](void *priv) -> int { return 0; }
|
||||
};
|
||||
|
||||
class XMPSong : public StreamSource
|
||||
{
|
||||
private:
|
||||
xmp_context context = nullptr;
|
||||
int samplerate = 44100;
|
||||
int subsong = 0;
|
||||
|
||||
// libxmp can't output in float.
|
||||
std::vector<int16_t> int16_buffer;
|
||||
|
||||
public:
|
||||
XMPSong(xmp_context ctx, int samplerate);
|
||||
~XMPSong();
|
||||
bool SetSubsong(int subsong) override;
|
||||
bool Start() override;
|
||||
SoundStreamInfoEx GetFormatEx() override;
|
||||
|
||||
protected:
|
||||
bool GetData(void *buffer, size_t len) override;
|
||||
};
|
||||
|
||||
XMPSong::XMPSong(xmp_context ctx, int rate)
|
||||
{
|
||||
context = ctx;
|
||||
samplerate = (dumbConfig.mod_samplerate != 0) ? dumbConfig.mod_samplerate : rate;
|
||||
xmp_set_player(context, XMP_PLAYER_VOLUME, 100);
|
||||
xmp_set_player(context, XMP_PLAYER_INTERP, dumbConfig.mod_interp);
|
||||
|
||||
int16_buffer.reserve(16 * 1024);
|
||||
}
|
||||
|
||||
XMPSong::~XMPSong()
|
||||
{
|
||||
xmp_end_player(context);
|
||||
xmp_free_context(context);
|
||||
}
|
||||
|
||||
SoundStreamInfoEx XMPSong::GetFormatEx()
|
||||
{
|
||||
return { 32 * 1024, samplerate, SampleType_Float32, ChannelConfig_Stereo };
|
||||
}
|
||||
|
||||
bool XMPSong::SetSubsong(int subsong)
|
||||
{
|
||||
this->subsong = subsong;
|
||||
if (xmp_get_player(context, XMP_PLAYER_STATE) >= XMP_STATE_PLAYING)
|
||||
return xmp_set_position(context, subsong) >= 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool XMPSong::GetData(void *buffer, size_t len)
|
||||
{
|
||||
if ((len / 4) > int16_buffer.size())
|
||||
int16_buffer.resize(len / 4);
|
||||
|
||||
int ret = xmp_play_buffer(context, (void*)int16_buffer.data(), len / 2, m_Looping? INT_MAX : 0);
|
||||
xmp_set_player(context, XMP_PLAYER_INTERP, dumbConfig.mod_interp);
|
||||
|
||||
if (ret >= 0)
|
||||
{
|
||||
float* soundbuffer = (float*)buffer;
|
||||
for (unsigned int i = 0; i < len / 4; i++)
|
||||
{
|
||||
soundbuffer[i] = ((int16_buffer[i] < 0.) ? (int16_buffer[i] / 32768.) : (int16_buffer[i] / 32767.)) * dumbConfig.mod_dumb_mastervolume;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret < 0 && m_Looping)
|
||||
{
|
||||
xmp_restart_module(context);
|
||||
xmp_set_position(context, subsong);
|
||||
return true;
|
||||
}
|
||||
|
||||
return ret >= 0;
|
||||
}
|
||||
|
||||
bool XMPSong::Start()
|
||||
{
|
||||
int ret = xmp_start_player(context, samplerate, 0);
|
||||
if (ret >= 0)
|
||||
xmp_set_position(context, subsong);
|
||||
return ret >= 0;
|
||||
}
|
||||
|
||||
StreamSource* XMP_OpenSong(MusicIO::FileInterface* reader, int samplerate)
|
||||
{
|
||||
if (xmp_test_module_from_callbacks((void*)reader, callbacks, nullptr) < 0)
|
||||
return nullptr;
|
||||
|
||||
xmp_context ctx = xmp_create_context();
|
||||
if (!ctx)
|
||||
return nullptr;
|
||||
|
||||
reader->seek(0, SEEK_SET);
|
||||
|
||||
if (xmp_load_module_from_callbacks(ctx, (void*)reader, callbacks) < 0)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return new XMPSong(ctx, samplerate);
|
||||
}
|
||||
|
|
@ -35,6 +35,8 @@
|
|||
|
||||
#ifdef HAVE_OPL
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include "streamsource.h"
|
||||
#include "oplsynth/opl.h"
|
||||
#include "oplsynth/opl_mus_player.h"
|
||||
|
|
|
@ -33,6 +33,7 @@ protected:
|
|||
|
||||
|
||||
StreamSource *MOD_OpenSong(MusicIO::FileInterface* reader, int samplerate);
|
||||
StreamSource *XMP_OpenSong(MusicIO::FileInterface* reader, int samplerate);
|
||||
StreamSource* GME_OpenSong(MusicIO::FileInterface* reader, const char* fmt, int sample_rate);
|
||||
StreamSource *SndFile_OpenSong(MusicIO::FileInterface* fr);
|
||||
StreamSource* XA_OpenSong(MusicIO::FileInterface* reader);
|
||||
|
|
|
@ -197,9 +197,9 @@ struct MidiDeviceList
|
|||
#ifdef HAVE_WILDMIDI
|
||||
devices.push_back({ strdup("WildMidi"), -6, MIDIDEV_SWSYNTH });
|
||||
#endif
|
||||
#ifdef HAVE_FLUIDSYNTH
|
||||
// this will always exist.
|
||||
devices.push_back({ strdup("FluidSynth"), -5, MIDIDEV_SWSYNTH });
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GUS
|
||||
devices.push_back({ strdup("GUS Emulation"), -4, MIDIDEV_SWSYNTH });
|
||||
#endif
|
||||
|
@ -652,6 +652,10 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingInt(EIntConfigKey key, MusInfo *currSon
|
|||
miscConfig.snd_outputrate = value;
|
||||
return false;
|
||||
|
||||
case zmusic_mod_preferredplayer:
|
||||
dumbConfig.mod_preferred_player = value;
|
||||
return false;
|
||||
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -678,8 +682,8 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingFloat(EFloatConfigKey key, MusInfo* cur
|
|||
case zmusic_fluid_reverb_roomsize:
|
||||
if (value < 0)
|
||||
value = 0;
|
||||
else if (value > 1.2f)
|
||||
value = 1.2f;
|
||||
else if (value > 1.0f)
|
||||
value = 1.0f;
|
||||
|
||||
if (currSong != NULL)
|
||||
currSong->ChangeSettingNum("fluidsynth.z.reverb", value);
|
||||
|
@ -736,8 +740,8 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingFloat(EFloatConfigKey key, MusInfo* cur
|
|||
return false;
|
||||
|
||||
case zmusic_fluid_chorus_speed:
|
||||
if (value < 0.29f)
|
||||
value = 0.29f;
|
||||
if (value < 0.1f)
|
||||
value = 0.1f;
|
||||
else if (value > 5)
|
||||
value = 5;
|
||||
|
||||
|
@ -751,8 +755,8 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingFloat(EFloatConfigKey key, MusInfo* cur
|
|||
case zmusic_fluid_chorus_depth:
|
||||
if (value < 0)
|
||||
value = 0;
|
||||
else if (value > 21)
|
||||
value = 21;
|
||||
else if (value > 256)
|
||||
value = 256;
|
||||
|
||||
if (currSong != NULL)
|
||||
currSong->ChangeSettingNum("fluidsynth.z.chorus", value);
|
||||
|
@ -942,6 +946,7 @@ static ZMusicConfigurationSetting config[] = {
|
|||
{"zmusic_mod_autochip_size_force", zmusic_mod_autochip_size_force, ZMUSIC_VAR_INT, 100},
|
||||
{"zmusic_mod_autochip_size_scan", zmusic_mod_autochip_size_scan, ZMUSIC_VAR_INT, 500},
|
||||
{"zmusic_mod_autochip_scan_threshold", zmusic_mod_autochip_scan_threshold, ZMUSIC_VAR_INT, 12},
|
||||
{"zmusic_mod_preferred_player", zmusic_mod_preferredplayer, ZMUSIC_VAR_INT, 0},
|
||||
{"zmusic_mod_dumb_mastervolume", zmusic_mod_dumb_mastervolume, ZMUSIC_VAR_FLOAT, 1},
|
||||
|
||||
{"zmusic_gme_stereodepth", zmusic_gme_stereodepth, ZMUSIC_VAR_FLOAT, 0},
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cstdint>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
@ -220,6 +221,9 @@ struct VectorReader : public MemoryReader
|
|||
{
|
||||
mVector.resize(size);
|
||||
memcpy(mVector.data(), data, size);
|
||||
mData = mVector.data();
|
||||
mLength = (long)size;
|
||||
mPos = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -129,6 +129,7 @@ struct DumbConfig
|
|||
int mod_autochip_size_force = 100;
|
||||
int mod_autochip_size_scan = 500;
|
||||
int mod_autochip_scan_threshold = 12;
|
||||
int mod_preferred_player = 0;
|
||||
float mod_dumb_mastervolume = 1;
|
||||
};
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
#include <stdint.h>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <zlib.h>
|
||||
#include <miniz.h>
|
||||
#include "m_swap.h"
|
||||
#include "zmusic_internal.h"
|
||||
#include "midiconfig.h"
|
||||
|
@ -257,10 +257,28 @@ static MusInfo *ZMusic_OpenSongInternal (MusicIO::FileInterface *reader, EMidiD
|
|||
streamsource = GME_OpenSong(reader, fmt, miscConfig.snd_outputrate);
|
||||
}
|
||||
// Check for module formats
|
||||
else
|
||||
else if ((id[0] == MAKE_ID('R', 'I', 'F', 'F') && id[2] == MAKE_ID('D', 'S', 'M', 'F')))
|
||||
{
|
||||
streamsource = MOD_OpenSong(reader, miscConfig.snd_outputrate);
|
||||
}
|
||||
else
|
||||
{
|
||||
// give the calling app an option to select between XMP and DUMB.
|
||||
if (dumbConfig.mod_preferred_player != 0)
|
||||
{
|
||||
streamsource = MOD_OpenSong(reader, miscConfig.snd_outputrate);
|
||||
}
|
||||
if (!streamsource)
|
||||
{
|
||||
reader->seek(0, SEEK_SET);
|
||||
streamsource = XMP_OpenSong(reader, miscConfig.snd_outputrate);
|
||||
if (!streamsource && dumbConfig.mod_preferred_player == 0)
|
||||
{
|
||||
reader->seek(0, SEEK_SET);
|
||||
streamsource = MOD_OpenSong(reader, miscConfig.snd_outputrate);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (streamsource == nullptr)
|
||||
{
|
||||
streamsource = SndFile_OpenSong(reader); // this only takes over the reader if it succeeds. We need to look out for this.
|
||||
|
|
24
thirdparty/CMakeLists.txt
vendored
24
thirdparty/CMakeLists.txt
vendored
|
@ -1,22 +1,4 @@
|
|||
if(NOT TARGET ZLIB::ZLIB)
|
||||
option(FORCE_INTERNAL_ZLIB "Use internal zlib" OFF)
|
||||
find_package(ZLIB QUIET)
|
||||
if(ZLIB_FOUND AND NOT FORCE_INTERNAL_ZLIB)
|
||||
message(STATUS "Using system zlib, includes found at ${ZLIB_INCLUDE_DIRS}")
|
||||
set_property(TARGET ZLIB::ZLIB PROPERTY IMPORTED_GLOBAL TRUE)
|
||||
determine_package_config_dependency(ZMUSIC_PACKAGE_DEPENDENCIES TARGET ZLIB::ZLIB MODULE ZLIB)
|
||||
else()
|
||||
message(STATUS "Using internal zlib")
|
||||
set(SKIP_INSTALL_ALL TRUE) # Avoid installing zlib alongside ZMusic
|
||||
add_subdirectory(zlib)
|
||||
add_library(ZLIB::ZLIB ALIAS z)
|
||||
|
||||
# Setup variables for GME's CMakeLists
|
||||
set(ZLIB_LIBRARY ZLIB::ZLIB)
|
||||
get_property(ZLIB_INCLUDE_DIR TARGET ZLIB::ZLIB PROPERTY INTERFACE_INCLUDE_DIRECTORIES)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_subdirectory(miniz)
|
||||
# GME is not currently released in a way that's conducive to using as a system
|
||||
# library. Nevertheless at least one person tried, and so the ability to use a
|
||||
# system copy exists soley to placate people following distro guidelines to the
|
||||
|
@ -33,7 +15,7 @@ endif()
|
|||
# message(STATUS "Using internal gme library")
|
||||
# Use MAME as it's a balanced emulator: well-accurate, but doesn't eats lot of CPU
|
||||
# Nuked OPN2 is very accurate emulator, but it eats too much CPU for the workflow
|
||||
set(GME_YM2612_EMU "MAME" CACHE STRING "Which YM2612 emulator to use: \"Nuked\" (LGPLv2.1+), \"MAME\" (GPLv2+), or \"GENS\" (LGPLv2.1+)")
|
||||
set(GME_YM2612_EMU "Nuked" CACHE STRING "Which YM2612 emulator to use: \"Nuked\" (LGPLv2.1+), \"MAME\" (GPLv2+), or \"GENS\" (LGPLv2.1+)")
|
||||
mark_as_advanced(GME_YM2612_EMU)
|
||||
add_subdirectory(game-music-emu)
|
||||
#endif()
|
||||
|
@ -45,3 +27,5 @@ add_subdirectory(timidity)
|
|||
add_subdirectory(timidityplus)
|
||||
add_subdirectory(wildmidi)
|
||||
add_subdirectory(oplsynth)
|
||||
add_subdirectory(libxmp)
|
||||
add_subdirectory(fluidsynth/src)
|
||||
|
|
340
thirdparty/adlmidi/adlmidi.cpp
vendored
340
thirdparty/adlmidi/adlmidi.cpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -551,6 +551,24 @@ ADLMIDI_EXPORT void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, in
|
|||
play->m_setup.fullRangeBrightnessCC74 = (fr_brightness != 0);
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setAutoArpeggio(ADL_MIDIPlayer *device, int aaEn)
|
||||
{
|
||||
if(!device)
|
||||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_setup.enableAutoArpeggio = (aaEn != 0);
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_getAutoArpeggio(ADL_MIDIPlayer *device)
|
||||
{
|
||||
if(!device)
|
||||
return 0;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_setup.enableAutoArpeggio ? 1 : 0;
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
|
@ -565,6 +583,34 @@ ADLMIDI_EXPORT void adl_setLoopEnabled(ADL_MIDIPlayer *device, int loopEn)
|
|||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setLoopCount(ADL_MIDIPlayer *device, int loopCount)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
if(!device)
|
||||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencer->setLoopsCount(loopCount);
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(loopCount);
|
||||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setLoopHooksOnly(ADL_MIDIPlayer *device, int loopHooksOnly)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
if(!device)
|
||||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencer->setLoopHooksOnly(loopHooksOnly);
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(loopHooksOnly);
|
||||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setSoftPanEnabled(ADL_MIDIPlayer *device, int softPanEn)
|
||||
{
|
||||
if(!device)
|
||||
|
@ -618,6 +664,29 @@ ADLMIDI_EXPORT int adl_getVolumeRangeModel(struct ADL_MIDIPlayer *device)
|
|||
return play->m_synth->getVolumeScaleModel();
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_setChannelAllocMode(struct ADL_MIDIPlayer *device, int chanalloc)
|
||||
{
|
||||
if(!device)
|
||||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
Synth &synth = *play->m_synth;
|
||||
|
||||
if(chanalloc < -1 || chanalloc >= ADLMIDI_ChanAlloc_Count)
|
||||
chanalloc = ADLMIDI_ChanAlloc_AUTO;
|
||||
|
||||
synth.m_channelAlloc = static_cast<ADLMIDI_ChannelAlloc>(chanalloc);
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_getChannelAllocMode(struct ADL_MIDIPlayer *device)
|
||||
{
|
||||
if(!device)
|
||||
return -1;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return static_cast<int>(play->m_synth->m_channelAlloc);
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_openBankFile(struct ADL_MIDIPlayer *device, const char *filePath)
|
||||
{
|
||||
if(device)
|
||||
|
@ -716,6 +785,35 @@ ADLMIDI_EXPORT int adl_openData(ADL_MIDIPlayer *device, const void *mem, unsigne
|
|||
return -1;
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT void adl_selectSongNum(struct ADL_MIDIPlayer *device, int songNumber)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
if(!device)
|
||||
return;
|
||||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->m_sequencer->setSongNum(songNumber);
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(songNumber);
|
||||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_getSongsCount(struct ADL_MIDIPlayer *device)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
if(!device)
|
||||
return 0;
|
||||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
return play->m_sequencer->getSongsCount();
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT const char *adl_emulatorName()
|
||||
{
|
||||
|
@ -1083,6 +1181,36 @@ ADLMIDI_EXPORT void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_D
|
|||
#endif
|
||||
}
|
||||
|
||||
/* Set loop start hook */
|
||||
ADLMIDI_EXPORT void adl_setLoopStartHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopStartHook, void *userData)
|
||||
{
|
||||
if(!device)
|
||||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->hooks.onLoopStart = loopStartHook;
|
||||
play->hooks.onLoopStart_userData = userData;
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
play->m_sequencerInterface->onloopStart = loopStartHook;
|
||||
play->m_sequencerInterface->onloopStart_userData = userData;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Set loop end hook */
|
||||
ADLMIDI_EXPORT void adl_setLoopEndHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopEndHook, void *userData)
|
||||
{
|
||||
if(!device)
|
||||
return;
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
play->hooks.onLoopEnd = loopEndHook;
|
||||
play->hooks.onLoopEnd_userData = userData;
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
play->m_sequencerInterface->onloopEnd = loopEndHook;
|
||||
play->m_sequencerInterface->onloopEnd_userData = userData;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef ADLMIDI_HW_OPL
|
||||
|
||||
# ifndef __WATCOMC__
|
||||
|
@ -1310,74 +1438,69 @@ ADLMIDI_EXPORT int adl_playFormat(ADL_MIDIPlayer *device, int sampleCount,
|
|||
|
||||
while(left > 0)
|
||||
{
|
||||
{//...
|
||||
if(setup.delay <= 0.0)
|
||||
setup.delay = double(left / 2) / double(setup.PCM_RATE);
|
||||
const double eat_delay = setup.delay < setup.maxdelay ? setup.delay : setup.maxdelay;
|
||||
if(hasSkipped)
|
||||
const double eat_delay = setup.delay < setup.maxdelay ? setup.delay : setup.maxdelay;
|
||||
if(hasSkipped)
|
||||
{
|
||||
size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay;
|
||||
n_periodCountStereo = samples / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
setup.delay -= eat_delay;
|
||||
setup.carry += double(setup.PCM_RATE) * eat_delay;
|
||||
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
|
||||
setup.carry -= double(n_periodCountStereo);
|
||||
}
|
||||
|
||||
//if(setup.SkipForward > 0)
|
||||
// setup.SkipForward -= 1;
|
||||
//else
|
||||
{
|
||||
if((player->m_sequencer->positionAtEnd()) && (setup.delay <= 0.0))
|
||||
break;//Stop to fetch samples at reaching the song end with disabled loop
|
||||
|
||||
ssize_t leftSamples = left / 2;
|
||||
if(n_periodCountStereo > leftSamples)
|
||||
{
|
||||
size_t samples = setup.tick_skip_samples_delay > sampleCount ? sampleCount : setup.tick_skip_samples_delay;
|
||||
n_periodCountStereo = samples / 2;
|
||||
setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2;
|
||||
n_periodCountStereo = leftSamples;
|
||||
}
|
||||
else
|
||||
//! Count of stereo samples
|
||||
ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
|
||||
//! Total count of samples
|
||||
ssize_t in_generatedPhys = in_generatedStereo * 2;
|
||||
//! Unsigned total sample count
|
||||
//fill buffer with zeros
|
||||
int32_t *out_buf = player->m_outBuf;
|
||||
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
|
||||
Synth &synth = *player->m_synth;
|
||||
unsigned int chips = synth.m_numChips;
|
||||
if(chips == 1)
|
||||
{
|
||||
setup.delay -= eat_delay;
|
||||
setup.carry += double(setup.PCM_RATE) * eat_delay;
|
||||
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
|
||||
setup.carry -= double(n_periodCountStereo);
|
||||
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
else if(n_periodCountStereo > 0)
|
||||
{
|
||||
/* Generate data from every chip and mix result */
|
||||
for(size_t card = 0; card < chips; ++card)
|
||||
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
|
||||
//if(setup.SkipForward > 0)
|
||||
// setup.SkipForward -= 1;
|
||||
//else
|
||||
{
|
||||
if((player->m_sequencer->positionAtEnd()) && (setup.delay <= 0.0))
|
||||
break;//Stop to fetch samples at reaching the song end with disabled loop
|
||||
/* Process it */
|
||||
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
|
||||
return 0;
|
||||
|
||||
ssize_t leftSamples = left / 2;
|
||||
if(n_periodCountStereo > leftSamples)
|
||||
{
|
||||
setup.tick_skip_samples_delay = (n_periodCountStereo - leftSamples) * 2;
|
||||
n_periodCountStereo = leftSamples;
|
||||
}
|
||||
//! Count of stereo samples
|
||||
ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
|
||||
//! Total count of samples
|
||||
ssize_t in_generatedPhys = in_generatedStereo * 2;
|
||||
//! Unsigned total sample count
|
||||
//fill buffer with zeros
|
||||
int32_t *out_buf = player->m_outBuf;
|
||||
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
|
||||
Synth &synth = *player->m_synth;
|
||||
unsigned int chips = synth.m_numChips;
|
||||
if(chips == 1)
|
||||
{
|
||||
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
else if(n_periodCountStereo > 0)
|
||||
{
|
||||
/* Generate data from every chip and mix result */
|
||||
for(size_t card = 0; card < chips; ++card)
|
||||
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
left -= (int)in_generatedPhys;
|
||||
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
|
||||
}
|
||||
|
||||
/* Process it */
|
||||
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
|
||||
return 0;
|
||||
|
||||
left -= (int)in_generatedPhys;
|
||||
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
|
||||
}
|
||||
|
||||
if(hasSkipped)
|
||||
{
|
||||
setup.tick_skip_samples_delay -= n_periodCountStereo * 2;
|
||||
hasSkipped = setup.tick_skip_samples_delay > 0;
|
||||
}
|
||||
else
|
||||
setup.delay = player->Tick(eat_delay, setup.mindelay);
|
||||
|
||||
}//...
|
||||
if(hasSkipped)
|
||||
{
|
||||
setup.tick_skip_samples_delay -= n_periodCountStereo * 2;
|
||||
hasSkipped = setup.tick_skip_samples_delay > 0;
|
||||
}
|
||||
else
|
||||
setup.delay = player->Tick(eat_delay, setup.mindelay);
|
||||
}
|
||||
|
||||
return static_cast<int>(gotten_len);
|
||||
|
@ -1420,47 +1543,45 @@ ADLMIDI_EXPORT int adl_generateFormat(struct ADL_MIDIPlayer *device, int sampleC
|
|||
|
||||
while(left > 0)
|
||||
{
|
||||
{//...
|
||||
if(delay <= 0.0)
|
||||
delay = double(left / 2) / double(setup.PCM_RATE);
|
||||
const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
|
||||
delay -= eat_delay;
|
||||
setup.carry += double(setup.PCM_RATE) * eat_delay;
|
||||
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
|
||||
setup.carry -= double(n_periodCountStereo);
|
||||
if(delay <= 0.0)
|
||||
delay = double(left / 2) / double(setup.PCM_RATE);
|
||||
const double eat_delay = delay < setup.maxdelay ? delay : setup.maxdelay;
|
||||
delay -= eat_delay;
|
||||
setup.carry += double(setup.PCM_RATE) * eat_delay;
|
||||
n_periodCountStereo = static_cast<ssize_t>(setup.carry);
|
||||
setup.carry -= double(n_periodCountStereo);
|
||||
|
||||
{
|
||||
ssize_t leftSamples = left / 2;
|
||||
if(n_periodCountStereo > leftSamples)
|
||||
n_periodCountStereo = leftSamples;
|
||||
//! Count of stereo samples
|
||||
ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
|
||||
//! Total count of samples
|
||||
ssize_t in_generatedPhys = in_generatedStereo * 2;
|
||||
//! Unsigned total sample count
|
||||
//fill buffer with zeros
|
||||
int32_t *out_buf = player->m_outBuf;
|
||||
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
|
||||
Synth &synth = *player->m_synth;
|
||||
unsigned int chips = synth.m_numChips;
|
||||
if(chips == 1)
|
||||
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
|
||||
else if(n_periodCountStereo > 0)
|
||||
{
|
||||
ssize_t leftSamples = left / 2;
|
||||
if(n_periodCountStereo > leftSamples)
|
||||
n_periodCountStereo = leftSamples;
|
||||
//! Count of stereo samples
|
||||
ssize_t in_generatedStereo = (n_periodCountStereo > 512) ? 512 : n_periodCountStereo;
|
||||
//! Total count of samples
|
||||
ssize_t in_generatedPhys = in_generatedStereo * 2;
|
||||
//! Unsigned total sample count
|
||||
//fill buffer with zeros
|
||||
int32_t *out_buf = player->m_outBuf;
|
||||
std::memset(out_buf, 0, static_cast<size_t>(in_generatedPhys) * sizeof(out_buf[0]));
|
||||
Synth &synth = *player->m_synth;
|
||||
unsigned int chips = synth.m_numChips;
|
||||
if(chips == 1)
|
||||
synth.m_chips[0]->generate32(out_buf, (size_t)in_generatedStereo);
|
||||
else if(n_periodCountStereo > 0)
|
||||
{
|
||||
/* Generate data from every chip and mix result */
|
||||
for(unsigned card = 0; card < chips; ++card)
|
||||
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
/* Process it */
|
||||
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
|
||||
return 0;
|
||||
|
||||
left -= (int)in_generatedPhys;
|
||||
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
|
||||
/* Generate data from every chip and mix result */
|
||||
for(unsigned card = 0; card < chips; ++card)
|
||||
synth.m_chips[card]->generateAndMix32(out_buf, (size_t)in_generatedStereo);
|
||||
}
|
||||
/* Process it */
|
||||
if(SendStereoAudio(sampleCount, in_generatedStereo, out_buf, gotten_len, out_left, out_right, format) == -1)
|
||||
return 0;
|
||||
|
||||
player->TickIterators(eat_delay);
|
||||
}//...
|
||||
left -= (int)in_generatedPhys;
|
||||
gotten_len += (in_generatedPhys) /* - setup.stored_samples*/;
|
||||
}
|
||||
|
||||
player->TickIterators(eat_delay);
|
||||
}
|
||||
|
||||
return static_cast<int>(gotten_len);
|
||||
|
@ -1552,6 +1673,27 @@ ADLMIDI_EXPORT int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t tra
|
|||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_setChannelEnabled(struct ADL_MIDIPlayer *device, size_t channelNumber, int enabled)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
if(!device)
|
||||
return -1;
|
||||
|
||||
MidiPlayer *play = GET_MIDI_PLAYER(device);
|
||||
assert(play);
|
||||
MidiSequencer &seq = *play->m_sequencer;
|
||||
|
||||
if(!seq.setChannelEnabled(channelNumber, (bool)enabled))
|
||||
return -1;
|
||||
return 0;
|
||||
#else
|
||||
ADL_UNUSED(device);
|
||||
ADL_UNUSED(channelNumber);
|
||||
ADL_UNUSED(enabled);
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
ADLMIDI_EXPORT int adl_setTriggerHandler(struct ADL_MIDIPlayer *device, ADL_TriggerHandler handler, void *userData)
|
||||
{
|
||||
#ifndef ADLMIDI_DISABLE_MIDI_SEQUENCER
|
||||
|
|
151
thirdparty/adlmidi/adlmidi.h
vendored
151
thirdparty/adlmidi/adlmidi.h
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -30,7 +30,7 @@ extern "C" {
|
|||
|
||||
#define ADLMIDI_VERSION_MAJOR 1
|
||||
#define ADLMIDI_VERSION_MINOR 5
|
||||
#define ADLMIDI_VERSION_PATCHLEVEL 0
|
||||
#define ADLMIDI_VERSION_PATCHLEVEL 1
|
||||
|
||||
#define ADLMIDI_TOSTR_I(s) #s
|
||||
#define ADLMIDI_TOSTR(s) ADLMIDI_TOSTR_I(s)
|
||||
|
@ -125,7 +125,26 @@ enum ADLMIDI_VolumeModels
|
|||
/*! HMI Sound Operating System volume scaling model */
|
||||
ADLMIDI_VolumeModel_HMI = 10,
|
||||
/*! HMI Sound Operating System volume scaling model, older variant with bugs */
|
||||
ADLMIDI_VolumeModel_HMI_OLD = 11
|
||||
ADLMIDI_VolumeModel_HMI_OLD = 11,
|
||||
/*! Count of available volume model modes */
|
||||
ADLMIDI_VolumeModel_Count
|
||||
};
|
||||
|
||||
/*!
|
||||
* \brief Algorithms of channel allocation for new notes
|
||||
*/
|
||||
enum ADLMIDI_ChannelAlloc
|
||||
{
|
||||
/*! Automatical choise of the method according to the volume model and internal preferrences */
|
||||
ADLMIDI_ChanAlloc_AUTO = -1,
|
||||
/*! Take only channels that has expired sounding delay */
|
||||
ADLMIDI_ChanAlloc_OffDelay,
|
||||
/*! Take any first released channel with the same instrument */
|
||||
ADLMIDI_ChanAlloc_SameInst,
|
||||
/*! Take any first released channel */
|
||||
ADLMIDI_ChanAlloc_AnyReleased,
|
||||
/*! Count of available channel allocation modes */
|
||||
ADLMIDI_ChanAlloc_Count
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -548,6 +567,21 @@ extern ADLMIDI_DECLSPEC void adl_setScaleModulators(struct ADL_MIDIPlayer *devic
|
|||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *device, int fr_brightness);
|
||||
|
||||
/**
|
||||
* @brief Enable(1) or Disable(0) the automatical arpeggio system
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param aaEn 0 - disabled, 1 - enabled
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setAutoArpeggio(struct ADL_MIDIPlayer *device, int aaEn);
|
||||
|
||||
/**
|
||||
* @brief Get the state of the automatical arpeggio system enable state
|
||||
* @param device Instalce of the library
|
||||
* @return 0 - disabled, 1 - enabled
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_getAutoArpeggio(struct ADL_MIDIPlayer *device);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable built-in loop (built-in loop supports 'loopStart' and 'loopEnd' tags to loop specific part)
|
||||
* @param device Instance of the library
|
||||
|
@ -555,6 +589,23 @@ extern ADLMIDI_DECLSPEC void adl_setFullRangeBrightness(struct ADL_MIDIPlayer *d
|
|||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setLoopEnabled(struct ADL_MIDIPlayer *device, int loopEn);
|
||||
|
||||
/**
|
||||
* @brief Set how many times loop will be played
|
||||
*
|
||||
* Note: The song will be played once if loop has been disabled with no matter which value of loop count was set
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param loopCount Number of loops or -1 to loop infinitely
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setLoopCount(struct ADL_MIDIPlayer *device, int loopCount);
|
||||
|
||||
/**
|
||||
* @brief Make song immediately stop on reaching a loop end point
|
||||
* @param device Instance of the library
|
||||
* @param loopHooksOnly 0 - disabled, 1 - enabled
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setLoopHooksOnly(struct ADL_MIDIPlayer *device, int loopHooksOnly);
|
||||
|
||||
/**
|
||||
* @brief Enable or disable soft panning with chip emulators
|
||||
* @param device Instance of the library
|
||||
|
@ -584,6 +635,20 @@ extern ADLMIDI_DECLSPEC void adl_setVolumeRangeModel(struct ADL_MIDIPlayer *devi
|
|||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_getVolumeRangeModel(struct ADL_MIDIPlayer *device);
|
||||
|
||||
/**
|
||||
* @brief Set the channel allocation mode
|
||||
* @param device Instance of the library
|
||||
* @param chanalloc Channel allocation mode (#ADLMIDI_ChannelAlloc)
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setChannelAllocMode(struct ADL_MIDIPlayer *device, int chanalloc);
|
||||
|
||||
/**
|
||||
* @brief Get the current channel allocation mode
|
||||
* @param device Instance of the library
|
||||
* @return Channel allocation mode (#ADLMIDI_ChannelAlloc)
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_getChannelAllocMode(struct ADL_MIDIPlayer *device);
|
||||
|
||||
/**
|
||||
* @brief Load WOPL bank file from File System
|
||||
*
|
||||
|
@ -766,6 +831,27 @@ extern ADLMIDI_DECLSPEC int adl_openFile(struct ADL_MIDIPlayer *device, const ch
|
|||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_openData(struct ADL_MIDIPlayer *device, const void *mem, unsigned long size);
|
||||
|
||||
/**
|
||||
* @brief Switch another song if multi-song file is playing (for example, XMI)
|
||||
*
|
||||
* Note: to set the initial song to load, you should call this function
|
||||
* BBEFORE calling `adl_openFile` or `adl_openData`. When loaded file has more than
|
||||
* one built-in songs (Usually XMIformat), it will be started from the selected number.
|
||||
* You may call this function to switch another song.
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param songNumber Identifier of the track to load (or -1 to mix all tracks as one song)
|
||||
* @return
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_selectSongNum(struct ADL_MIDIPlayer *device, int songNumber);
|
||||
|
||||
/**
|
||||
* @brief Retrive the number of songs in a currently opened file
|
||||
* @param device Instance of the library
|
||||
* @return Number of songs in the file. If 1 or less, means, the file has only one song inside.
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_getSongsCount(struct ADL_MIDIPlayer *device);
|
||||
|
||||
/**
|
||||
* @brief Resets MIDI player (per-channel setup) into initial state
|
||||
* @param device Instance of the library
|
||||
|
@ -876,6 +962,15 @@ enum ADLMIDI_TrackOptions
|
|||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_setTrackOptions(struct ADL_MIDIPlayer *device, size_t trackNumber, unsigned trackOptions);
|
||||
|
||||
/**
|
||||
* @brief Sets the channel of the current sequence enable state
|
||||
* @param device Instance of the library
|
||||
* @param channelNumber Number of the channel (from 0 to 15)
|
||||
* @param enabled 1 to enable and 0 to disable
|
||||
* @return 0 on success, <0 when any error has occurred
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC int adl_setChannelEnabled(struct ADL_MIDIPlayer *device, size_t channelNumber, int enabled);
|
||||
|
||||
/**
|
||||
* @brief Handler of callback trigger events
|
||||
* @param userData Pointer to user data (usually, context of something)
|
||||
|
@ -1210,8 +1305,19 @@ typedef void (*ADL_NoteHook)(void *userdata, int adlchn, int note, int ins, int
|
|||
*/
|
||||
typedef void (*ADL_DebugMessageHook)(void *userdata, const char *fmt, ...);
|
||||
|
||||
/**
|
||||
* @brief Loop start/end point reach hook
|
||||
* @param userdata Pointer to user data (usually, context of someting)
|
||||
*/
|
||||
typedef void (*ADL_LoopPointHook)(void *userdata);
|
||||
|
||||
/**
|
||||
* @brief Set raw MIDI event hook
|
||||
*
|
||||
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
|
||||
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
|
||||
* apply your action outside of this hook, for example, in the next after audio output call.
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param rawEventHook Pointer to the callback function which will be called on every MIDI event
|
||||
* @param userData Pointer to user data which will be passed through the callback.
|
||||
|
@ -1220,6 +1326,11 @@ extern ADLMIDI_DECLSPEC void adl_setRawEventHook(struct ADL_MIDIPlayer *device,
|
|||
|
||||
/**
|
||||
* @brief Set note hook
|
||||
*
|
||||
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
|
||||
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
|
||||
* apply your action outside of this hook, for example, in the next after audio output call.
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param noteHook Pointer to the callback function which will be called on every noteOn MIDI event
|
||||
* @param userData Pointer to user data which will be passed through the callback.
|
||||
|
@ -1228,12 +1339,46 @@ extern ADLMIDI_DECLSPEC void adl_setNoteHook(struct ADL_MIDIPlayer *device, ADL_
|
|||
|
||||
/**
|
||||
* @brief Set debug message hook
|
||||
*
|
||||
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
|
||||
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
|
||||
* apply your action outside of this hook, for example, in the next after audio output call.
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param debugMessageHook Pointer to the callback function which will be called on every debug message
|
||||
* @param userData Pointer to user data which will be passed through the callback.
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setDebugMessageHook(struct ADL_MIDIPlayer *device, ADL_DebugMessageHook debugMessageHook, void *userData);
|
||||
|
||||
/**
|
||||
* @brief Set the look start point hook
|
||||
*
|
||||
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
|
||||
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
|
||||
* apply your action outside of this hook, for example, in the next after audio output call.
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param loopStartHook Pointer to the callback function which will be called on every loop start point passing
|
||||
* @param userData Pointer to user data which will be passed through the callback.
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setLoopStartHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopStartHook, void *userData);
|
||||
|
||||
/**
|
||||
* @brief Set the look start point hook
|
||||
*
|
||||
* CAUTION: Don't call any libADLMIDI API functions from off this hook directly!
|
||||
* Suggestion: Use boolean variables to mark the fact this hook got been called, and then,
|
||||
* apply your action outside of this hook, for example, in the next after audio output call.
|
||||
*
|
||||
* If you want to switch the song after calling this hook, suggested to call the function
|
||||
* adl_setLoopHooksOnly(device, 1) to immediately stop the song on reaching the loop point
|
||||
*
|
||||
* @param device Instance of the library
|
||||
* @param loopStartHook Pointer to the callback function which will be called on every loop start point passing
|
||||
* @param userData Pointer to user data which will be passed through the callback.
|
||||
*/
|
||||
extern ADLMIDI_DECLSPEC void adl_setLoopEndHook(struct ADL_MIDIPlayer *device, ADL_LoopPointHook loopEndHook, void *userData);
|
||||
|
||||
/**
|
||||
* @brief Get a textual description of the channel state. For display only.
|
||||
* @param device Instance of the library
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_bankmap.h
vendored
2
thirdparty/adlmidi/adlmidi_bankmap.h
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_bankmap.tcc
vendored
2
thirdparty/adlmidi/adlmidi_bankmap.tcc
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free MIDI to WAV conversion library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_cvt.hpp
vendored
2
thirdparty/adlmidi/adlmidi_cvt.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
4
thirdparty/adlmidi/adlmidi_db.h
vendored
4
thirdparty/adlmidi/adlmidi_db.h
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -31,7 +31,7 @@
|
|||
#include <stddef.h>
|
||||
#include <vector>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#if !defined(_MSC_VER) && !defined(__aarch64__) && !defined(__3DS__)
|
||||
#define ATTRIB_PACKED __attribute__((__packed__))
|
||||
#else
|
||||
#define ATTRIB_PACKED
|
||||
|
|
3
thirdparty/adlmidi/adlmidi_load.cpp
vendored
3
thirdparty/adlmidi/adlmidi_load.cpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -117,6 +117,7 @@ bool MIDIplay::LoadBank(FileAndMemReader &fr)
|
|||
synth.m_insBankSetup.scaleModulators = false;
|
||||
synth.m_insBankSetup.deepTremolo = (wopl->opl_flags & WOPL_FLAG_DEEP_TREMOLO) != 0;
|
||||
synth.m_insBankSetup.deepVibrato = (wopl->opl_flags & WOPL_FLAG_DEEP_VIBRATO) != 0;
|
||||
synth.m_insBankSetup.mt32defaults = (wopl->opl_flags & WOPL_FLAG_MT32) != 0;
|
||||
synth.m_insBankSetup.volumeModel = wopl->volume_model;
|
||||
m_setup.deepTremoloMode = -1;
|
||||
m_setup.deepVibratoMode = -1;
|
||||
|
|
66
thirdparty/adlmidi/adlmidi_midiplay.cpp
vendored
66
thirdparty/adlmidi/adlmidi_midiplay.cpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -36,7 +36,8 @@ enum { MasterVolumeDefault = 127 };
|
|||
|
||||
inline bool isXgPercChannel(uint8_t msb, uint8_t lsb)
|
||||
{
|
||||
return (msb == 0x7E || msb == 0x7F) && (lsb == 0);
|
||||
ADL_UNUSED(lsb);
|
||||
return (msb == 0x7E || msb == 0x7F);
|
||||
}
|
||||
|
||||
void MIDIplay::AdlChannel::addAge(int64_t us)
|
||||
|
@ -90,6 +91,7 @@ MIDIplay::MIDIplay(unsigned long sampleRate):
|
|||
//m_setup.SkipForward = 0;
|
||||
m_setup.scaleModulators = -1;
|
||||
m_setup.fullRangeBrightnessCC74 = false;
|
||||
m_setup.enableAutoArpeggio = false;
|
||||
m_setup.delay = 0.0;
|
||||
m_setup.carry = 0.0;
|
||||
m_setup.tick_skip_samples_delay = 0;
|
||||
|
@ -126,6 +128,7 @@ void MIDIplay::applySetup()
|
|||
synth.m_insBankSetup.volumeModel = (b.bankSetup & 0x00FF);
|
||||
synth.m_insBankSetup.deepTremolo = (b.bankSetup >> 8 & 0x0001) != 0;
|
||||
synth.m_insBankSetup.deepVibrato = (b.bankSetup >> 8 & 0x0002) != 0;
|
||||
synth.m_insBankSetup.mt32defaults = (b.bankSetup >> 8 & 0x0004) != 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -200,15 +203,15 @@ void MIDIplay::resetMIDIDefaults(int offset)
|
|||
for(size_t c = offset, n = m_midiChannels.size(); c < n; ++c)
|
||||
{
|
||||
MIDIchannel &ch = m_midiChannels[c];
|
||||
if(synth.m_musicMode == Synth::MODE_XMIDI)
|
||||
|
||||
if(synth.m_musicMode == Synth::MODE_RSXX)
|
||||
ch.def_volume = 127;
|
||||
else if(synth.m_insBankSetup.mt32defaults)
|
||||
{
|
||||
ch.def_volume = 127;
|
||||
ch.def_bendsense_lsb = 0;
|
||||
ch.def_bendsense_msb = 12;
|
||||
}
|
||||
else
|
||||
if(synth.m_musicMode == Synth::MODE_RSXX)
|
||||
ch.def_volume = 127;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -290,10 +293,11 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
|
|||
if(!i.is_end())
|
||||
{
|
||||
MIDIchannel::NoteInfo &ni = i->value;
|
||||
const int veloffset = ni.ains->midiVelocityOffset;
|
||||
const int veloffset = ni.ains ? ni.ains->midiVelocityOffset : 0;
|
||||
velocity = (uint8_t)std::min(127, std::max(1, (int)velocity + veloffset));
|
||||
ni.vol = velocity;
|
||||
noteUpdate(channel, i, Upd_Volume);
|
||||
if(ni.ains)
|
||||
noteUpdate(channel, i, Upd_Volume);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -329,7 +333,7 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
|
|||
// Let XG Percussion bank will use (0...127 LSB range in WOPN file)
|
||||
|
||||
// Choose: SFX or Drum Kits
|
||||
bank = midiins + ((bank == 0x7E00) ? 128 : 0);
|
||||
bank = midiins + ((midiChan.bank_msb == 0x7E) ? 128 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -357,8 +361,8 @@ bool MIDIplay::realTime_NoteOn(uint8_t channel, uint8_t note, uint8_t velocity)
|
|||
caughtMissingBank = true;
|
||||
}
|
||||
|
||||
//Or fall back to bank ignoring LSB (GS)
|
||||
if((ains->flags & OplInstMeta::Flag_NoSound) && ((m_synthMode & Mode_GS) != 0))
|
||||
//Or fall back to bank ignoring LSB (GS/XG)
|
||||
if(ains->flags & OplInstMeta::Flag_NoSound)
|
||||
{
|
||||
size_t fallback = bank & ~(size_t)0x7F;
|
||||
if(fallback != bank)
|
||||
|
@ -1345,6 +1349,17 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
|
|||
const AdlChannel &chan = m_chipChannels[c];
|
||||
int64_t koff_ms = chan.koff_time_until_neglible_us / 1000;
|
||||
int64_t s = -koff_ms;
|
||||
ADLMIDI_ChannelAlloc allocType = synth.m_channelAlloc;
|
||||
|
||||
if(allocType == ADLMIDI_ChanAlloc_AUTO)
|
||||
{
|
||||
if(synth.m_musicMode == Synth::MODE_CMF)
|
||||
allocType = ADLMIDI_ChanAlloc_SameInst;
|
||||
else if(synth.m_volumeScale == Synth::VOLUME_HMI)
|
||||
allocType = ADLMIDI_ChanAlloc_AnyReleased; // HMI doesn't care about the same instrument
|
||||
else
|
||||
allocType = ADLMIDI_ChanAlloc_OffDelay;
|
||||
}
|
||||
|
||||
// Rate channel with a releasing note
|
||||
if(s < 0 && chan.users.empty())
|
||||
|
@ -1353,19 +1368,22 @@ int64_t MIDIplay::calculateChipChannelGoodness(size_t c, const MIDIchannel::Note
|
|||
s -= 40000;
|
||||
|
||||
// If it's same instrument, better chance to get it when no free channels
|
||||
if(synth.m_musicMode == Synth::MODE_CMF)
|
||||
switch(allocType)
|
||||
{
|
||||
case ADLMIDI_ChanAlloc_SameInst:
|
||||
if(isSame)
|
||||
s = 0; // Re-use releasing channel with the same instrument
|
||||
}
|
||||
else if(synth.m_volumeScale == Synth::VOLUME_HMI)
|
||||
{
|
||||
s = 0; // HMI doesn't care about the same instrument
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
|
||||
case ADLMIDI_ChanAlloc_AnyReleased:
|
||||
s = 0; // Re-use any releasing channel
|
||||
break;
|
||||
|
||||
default:
|
||||
case ADLMIDI_ChanAlloc_OffDelay:
|
||||
if(isSame)
|
||||
s = -koff_ms; // Wait until releasing sound will complete
|
||||
break;
|
||||
}
|
||||
|
||||
return s;
|
||||
|
@ -1502,6 +1520,9 @@ void MIDIplay::killOrEvacuate(size_t from_channel,
|
|||
{
|
||||
uint16_t cs = static_cast<uint16_t>(c);
|
||||
|
||||
if(!m_setup.enableAutoArpeggio)
|
||||
break; // Arpeggio disabled completely
|
||||
|
||||
if(c >= maxChannels)
|
||||
break;
|
||||
if(c == from_channel)
|
||||
|
@ -1725,6 +1746,13 @@ void MIDIplay::updateArpeggio(double) // amount = amount of time passed
|
|||
|
||||
Synth &synth = *m_synth;
|
||||
|
||||
if(!m_setup.enableAutoArpeggio) // Arpeggio was disabled
|
||||
{
|
||||
if(m_arpeggioCounter != 0)
|
||||
m_arpeggioCounter = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
#if 0
|
||||
const unsigned desired_arpeggio_rate = 40; // Hz (upper limit)
|
||||
# if 1
|
||||
|
|
14
thirdparty/adlmidi/adlmidi_midiplay.hpp
vendored
14
thirdparty/adlmidi/adlmidi_midiplay.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -37,6 +37,10 @@ struct MIDIEventHooks
|
|||
MIDIEventHooks() :
|
||||
onNote(NULL),
|
||||
onNote_userData(NULL),
|
||||
onLoopStart(NULL),
|
||||
onLoopStart_userData(NULL),
|
||||
onLoopEnd(NULL),
|
||||
onLoopEnd_userData(NULL),
|
||||
onDebugMessage(NULL),
|
||||
onDebugMessage_userData(NULL)
|
||||
{}
|
||||
|
@ -46,6 +50,13 @@ struct MIDIEventHooks
|
|||
NoteHook onNote;
|
||||
void *onNote_userData;
|
||||
|
||||
// Loop start/end hooks
|
||||
ADL_LoopPointHook onLoopStart;
|
||||
void *onLoopStart_userData;
|
||||
ADL_LoopPointHook onLoopEnd;
|
||||
void *onLoopEnd_userData;
|
||||
|
||||
|
||||
//! Library internal debug messages
|
||||
typedef void (*DebugMessageHook)(void *userdata, const char *fmt, ...);
|
||||
DebugMessageHook onDebugMessage;
|
||||
|
@ -526,6 +537,7 @@ public:
|
|||
//unsigned int SkipForward;
|
||||
int scaleModulators;
|
||||
bool fullRangeBrightnessCC74;
|
||||
bool enableAutoArpeggio;
|
||||
|
||||
double delay;
|
||||
double carry;
|
||||
|
|
8
thirdparty/adlmidi/adlmidi_opl3.cpp
vendored
8
thirdparty/adlmidi/adlmidi_opl3.cpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -868,12 +868,14 @@ OPL3::OPL3() :
|
|||
m_softPanning(false),
|
||||
m_masterVolume(MasterVolumeDefault),
|
||||
m_musicMode(MODE_MIDI),
|
||||
m_volumeScale(VOLUME_Generic)
|
||||
m_volumeScale(VOLUME_Generic),
|
||||
m_channelAlloc(ADLMIDI_ChanAlloc_AUTO)
|
||||
{
|
||||
m_insBankSetup.volumeModel = OPL3::VOLUME_Generic;
|
||||
m_insBankSetup.deepTremolo = false;
|
||||
m_insBankSetup.deepVibrato = false;
|
||||
m_insBankSetup.scaleModulators = false;
|
||||
m_insBankSetup.mt32defaults = false;
|
||||
|
||||
#ifdef DISABLE_EMBEDDED_BANKS
|
||||
m_embeddedBank = CustomBankTag;
|
||||
|
@ -913,6 +915,7 @@ void OPL3::setEmbeddedBank(uint32_t bank)
|
|||
const BanksDump::BankEntry &bankEntry = g_embeddedBanks[m_embeddedBank];
|
||||
m_insBankSetup.deepTremolo = ((bankEntry.bankSetup >> 8) & 0x01) != 0;
|
||||
m_insBankSetup.deepVibrato = ((bankEntry.bankSetup >> 8) & 0x02) != 0;
|
||||
m_insBankSetup.mt32defaults = ((bankEntry.bankSetup >> 8) & 0x04) != 0;
|
||||
m_insBankSetup.volumeModel = (bankEntry.bankSetup & 0xFF);
|
||||
m_insBankSetup.scaleModulators = false;
|
||||
|
||||
|
@ -1628,6 +1631,7 @@ void OPL3::setVolumeScaleModel(ADLMIDI_VolumeModels volumeModel)
|
|||
{
|
||||
switch(volumeModel)
|
||||
{
|
||||
default:
|
||||
case ADLMIDI_VolumeModel_AUTO://Do nothing until restart playing
|
||||
break;
|
||||
|
||||
|
|
5
thirdparty/adlmidi/adlmidi_opl3.hpp
vendored
5
thirdparty/adlmidi/adlmidi_opl3.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -162,6 +162,9 @@ public:
|
|||
VOLUME_HMI_OLD
|
||||
} m_volumeScale;
|
||||
|
||||
//! Channel allocation algorithm
|
||||
ADLMIDI_ChannelAlloc m_channelAlloc;
|
||||
|
||||
//! Reserved
|
||||
char _padding3[8];
|
||||
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_private.cpp
vendored
2
thirdparty/adlmidi/adlmidi_private.cpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_private.hpp
vendored
2
thirdparty/adlmidi/adlmidi_private.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
2
thirdparty/adlmidi/adlmidi_ptr.hpp
vendored
2
thirdparty/adlmidi/adlmidi_ptr.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
88
thirdparty/adlmidi/chips/common/mutex.hpp
vendored
88
thirdparty/adlmidi/chips/common/mutex.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -21,14 +21,26 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#include <pthread.h>
|
||||
#ifndef DOSBOX_NO_MUTEX
|
||||
# if defined(USE_LIBOGC_MUTEX)
|
||||
# include <ogc/mutex.h>
|
||||
typedef mutex_t MutexNativeObject;
|
||||
# elif defined(USE_WUT_MUTEX)
|
||||
# if __cplusplus < 201103L || (defined(_MSC_VER) && _MSC_VER < 1900)
|
||||
# define static_assert(x, y)
|
||||
# endif
|
||||
# include <coreinit/mutex.h>
|
||||
typedef OSMutex MutexNativeObject;
|
||||
# elif !defined(_WIN32)
|
||||
# include <pthread.h>
|
||||
typedef pthread_mutex_t MutexNativeObject;
|
||||
#else
|
||||
#include <windows.h>
|
||||
# else
|
||||
# include <windows.h>
|
||||
typedef CRITICAL_SECTION MutexNativeObject;
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
class Mutex
|
||||
{
|
||||
public:
|
||||
|
@ -37,7 +49,9 @@ public:
|
|||
void lock();
|
||||
void unlock();
|
||||
private:
|
||||
#if !defined(DOSBOX_NO_MUTEX)
|
||||
MutexNativeObject m;
|
||||
#endif
|
||||
Mutex(const Mutex &);
|
||||
Mutex &operator=(const Mutex &);
|
||||
};
|
||||
|
@ -53,7 +67,65 @@ private:
|
|||
MutexHolder &operator=(const MutexHolder &);
|
||||
};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
#if defined(DOSBOX_NO_MUTEX) // No mutex, just a dummy
|
||||
|
||||
inline Mutex::Mutex()
|
||||
{}
|
||||
|
||||
inline Mutex::~Mutex()
|
||||
{}
|
||||
|
||||
inline void Mutex::lock()
|
||||
{}
|
||||
|
||||
inline void Mutex::unlock()
|
||||
{}
|
||||
|
||||
#elif defined(USE_WUT_MUTEX)
|
||||
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
OSInitMutex(&m);
|
||||
}
|
||||
|
||||
inline Mutex::~Mutex()
|
||||
{}
|
||||
|
||||
inline void Mutex::lock()
|
||||
{
|
||||
OSLockMutex(&m);
|
||||
}
|
||||
|
||||
inline void Mutex::unlock()
|
||||
{
|
||||
OSUnlockMutex(&m);
|
||||
}
|
||||
|
||||
#elif defined(USE_LIBOGC_MUTEX)
|
||||
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
m = LWP_MUTEX_NULL;
|
||||
LWP_MutexInit(&m, 0);
|
||||
}
|
||||
|
||||
inline Mutex::~Mutex()
|
||||
{
|
||||
LWP_MutexDestroy(m);
|
||||
}
|
||||
|
||||
inline void Mutex::lock()
|
||||
{
|
||||
LWP_MutexLock(m);
|
||||
}
|
||||
|
||||
inline void Mutex::unlock()
|
||||
{
|
||||
LWP_MutexUnlock(m);
|
||||
}
|
||||
|
||||
#elif !defined(_WIN32) // pthread
|
||||
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
pthread_mutex_init(&m, NULL);
|
||||
|
@ -73,7 +145,9 @@ inline void Mutex::unlock()
|
|||
{
|
||||
pthread_mutex_unlock(&m);
|
||||
}
|
||||
#else
|
||||
|
||||
#else // Win32
|
||||
|
||||
inline Mutex::Mutex()
|
||||
{
|
||||
InitializeCriticalSection(&m);
|
||||
|
|
2
thirdparty/adlmidi/chips/common/ptr.hpp
vendored
2
thirdparty/adlmidi/chips/common/ptr.hpp
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
|
2
thirdparty/adlmidi/chips/dosbox_opl3.cpp
vendored
2
thirdparty/adlmidi/chips/dosbox_opl3.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/dosbox_opl3.h
vendored
2
thirdparty/adlmidi/chips/dosbox_opl3.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/java_opl3.cpp
vendored
2
thirdparty/adlmidi/chips/java_opl3.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/java_opl3.h
vendored
2
thirdparty/adlmidi/chips/java_opl3.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3.cpp
vendored
2
thirdparty/adlmidi/chips/nuked_opl3.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3.h
vendored
2
thirdparty/adlmidi/chips/nuked_opl3.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3_v174.cpp
vendored
2
thirdparty/adlmidi/chips/nuked_opl3_v174.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/nuked_opl3_v174.h
vendored
2
thirdparty/adlmidi/chips/nuked_opl3_v174.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/opal_opl3.cpp
vendored
2
thirdparty/adlmidi/chips/opal_opl3.cpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/opal_opl3.h
vendored
2
thirdparty/adlmidi/chips/opal_opl3.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Interfaces over Yamaha OPL3 (YMF262) chip emulators
|
||||
*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/chips/opl_chip_base.h
vendored
2
thirdparty/adlmidi/chips/opl_chip_base.h
vendored
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (c) 2017-2020 Vitaly Novichkov (Wohlstand)
|
||||
* Copyright (c) 2017-2022 Vitaly Novichkov (Wohlstand)
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
|
2
thirdparty/adlmidi/file_reader.hpp
vendored
2
thirdparty/adlmidi/file_reader.hpp
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* FileAndMemoryReader - a tiny helper to utify file reading from a disk and memory block
|
||||
*
|
||||
* Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
|
|
6451
thirdparty/adlmidi/inst_db.cpp
vendored
6451
thirdparty/adlmidi/inst_db.cpp
vendored
File diff suppressed because one or more lines are too long
3
thirdparty/adlmidi/oplinst.h
vendored
3
thirdparty/adlmidi/oplinst.h
vendored
|
@ -2,7 +2,7 @@
|
|||
* libADLMIDI is a free Software MIDI synthesizer library with OPL3 emulation
|
||||
*
|
||||
* Original ADLMIDI code: Copyright (c) 2010-2014 Joel Yliluoma <bisqwit@iki.fi>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* ADLMIDI Library API: Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Library is based on the ADLMIDI, a MIDI player for Linux and Windows with OPL3 emulation:
|
||||
* http://iki.fi/bisqwit/source/adlmidi.html
|
||||
|
@ -106,6 +106,7 @@ struct OplBankSetup
|
|||
bool deepTremolo;
|
||||
bool deepVibrato;
|
||||
bool scaleModulators;
|
||||
bool mt32defaults;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
2
thirdparty/adlmidi/wopl/wopl_file.c
vendored
2
thirdparty/adlmidi/wopl/wopl_file.c
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup
|
||||
*
|
||||
* Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
|
|
24
thirdparty/adlmidi/wopl/wopl_file.h
vendored
24
thirdparty/adlmidi/wopl/wopl_file.h
vendored
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
* Wohlstand's OPL3 Bank File - a bank format to store OPL3 timbre data and setup
|
||||
*
|
||||
* Copyright (c) 2015-2020 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
* Copyright (c) 2015-2022 Vitaly Novichkov <admin@wohlnet.ru>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the "Software"),
|
||||
|
@ -32,8 +32,22 @@
|
|||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if !defined(__STDC_VERSION__) || (defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L)) \
|
||||
|| defined(__STRICT_ANSI__) || !defined(__cplusplus)
|
||||
/* Solaris defines the integer types regardless of what C/C++ standard is actually available,
|
||||
* so avoid defining them at all by ourselves. */
|
||||
#if !defined(WOPL_STDINT_TYPEDEFS_NOT_NEEDED) && defined(__sun)
|
||||
# define WOPL_STDINT_TYPEDEFS_NOT_NEEDED
|
||||
#endif
|
||||
|
||||
#if !defined(WOPL_STDINT_TYPEDEFS_NEEDED) && !defined(WOPL_STDINT_TYPEDEFS_NOT_NEEDED)
|
||||
# if !defined(__STDC_VERSION__) || \
|
||||
(defined(__STDC_VERSION__) && (__STDC_VERSION__ < 199901L)) || \
|
||||
defined(__STRICT_ANSI__) || \
|
||||
!defined(__cplusplus)
|
||||
# define WOPL_STDINT_TYPEDEFS_NEEDED
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef WOPL_STDINT_TYPEDEFS_NEEDED
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed short int int16_t;
|
||||
|
@ -46,7 +60,9 @@ typedef enum WOPLFileFlags
|
|||
/* Enable Deep-Tremolo flag */
|
||||
WOPL_FLAG_DEEP_TREMOLO = 0x01,
|
||||
/* Enable Deep-Vibrato flag */
|
||||
WOPL_FLAG_DEEP_VIBRATO = 0x02
|
||||
WOPL_FLAG_DEEP_VIBRATO = 0x02,
|
||||
/* Enable MT32 defaults (127 initials and octave-wide pitch bend by default, etc.) */
|
||||
WOPL_FLAG_MT32 = 0x04
|
||||
} WOPLFileFlags;
|
||||
|
||||
/* Volume scaling model implemented in the libADLMIDI */
|
||||
|
|
119
thirdparty/fluidsynth/include/fluidsynth.h
vendored
Normal file
119
thirdparty/fluidsynth/include/fluidsynth.h
vendored
Normal file
|
@ -0,0 +1,119 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_H
|
||||
#define _FLUIDSYNTH_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if (BUILD_SHARED_LIBS == 0)
|
||||
#define FLUIDSYNTH_API // building static lib? no visibility control then
|
||||
#elif defined(WIN32)
|
||||
#if defined(FLUIDSYNTH_NOT_A_DLL)
|
||||
#define FLUIDSYNTH_API
|
||||
#elif defined(FLUIDSYNTH_DLL_EXPORTS)
|
||||
#define FLUIDSYNTH_API __declspec(dllexport)
|
||||
#else
|
||||
#define FLUIDSYNTH_API __declspec(dllimport)
|
||||
#endif
|
||||
|
||||
#elif defined(MACOS9)
|
||||
#define FLUIDSYNTH_API __declspec(export)
|
||||
|
||||
#elif defined(__OS2__)
|
||||
#define FLUIDSYNTH_API __declspec(dllexport)
|
||||
|
||||
#elif defined(__GNUC__)
|
||||
#define FLUIDSYNTH_API __attribute__ ((visibility ("default")))
|
||||
|
||||
#else
|
||||
#define FLUIDSYNTH_API
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) || defined(__clang__)
|
||||
# define FLUID_DEPRECATED __attribute__((deprecated))
|
||||
#elif defined(_MSC_VER) && _MSC_VER > 1200
|
||||
# define FLUID_DEPRECATED __declspec(deprecated)
|
||||
#else
|
||||
# define FLUID_DEPRECATED
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @file fluidsynth.h
|
||||
* @brief FluidSynth is a real-time synthesizer designed for SoundFont(R) files.
|
||||
*
|
||||
* This is the header of the fluidsynth library and contains the
|
||||
* synthesizer's public API.
|
||||
*
|
||||
* Depending on how you want to use or extend the synthesizer you
|
||||
* will need different API functions. You probably do not need all
|
||||
* of them. Here is what you might want to do:
|
||||
*
|
||||
* - Embedded synthesizer: create a new synthesizer and send MIDI
|
||||
* events to it. The sound goes directly to the audio output of
|
||||
* your system.
|
||||
*
|
||||
* - Plugin synthesizer: create a synthesizer and send MIDI events
|
||||
* but pull the audio back into your application.
|
||||
*
|
||||
* - SoundFont plugin: create a new type of "SoundFont" and allow
|
||||
* the synthesizer to load your type of SoundFonts.
|
||||
*
|
||||
* - MIDI input: Create a MIDI handler to read the MIDI input on your
|
||||
* machine and send the MIDI events directly to the synthesizer.
|
||||
*
|
||||
* - MIDI files: Open MIDI files and send the MIDI events to the
|
||||
* synthesizer.
|
||||
*
|
||||
* - Command lines: You can send textual commands to the synthesizer.
|
||||
*
|
||||
* SoundFont(R) is a registered trademark of E-mu Systems, Inc.
|
||||
*/
|
||||
|
||||
#include "fluidsynth/types.h"
|
||||
#include "fluidsynth/settings.h"
|
||||
#include "fluidsynth/synth.h"
|
||||
#include "fluidsynth/shell.h"
|
||||
#include "fluidsynth/sfont.h"
|
||||
#include "fluidsynth/audio.h"
|
||||
#include "fluidsynth/event.h"
|
||||
#include "fluidsynth/midi.h"
|
||||
#include "fluidsynth/seq.h"
|
||||
#include "fluidsynth/seqbind.h"
|
||||
#include "fluidsynth/log.h"
|
||||
#include "fluidsynth/misc.h"
|
||||
#include "fluidsynth/mod.h"
|
||||
#include "fluidsynth/gen.h"
|
||||
#include "fluidsynth/voice.h"
|
||||
#include "fluidsynth/version.h"
|
||||
#include "fluidsynth/ladspa.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_H */
|
155
thirdparty/fluidsynth/include/fluidsynth/audio.h
vendored
Normal file
155
thirdparty/fluidsynth/include/fluidsynth/audio.h
vendored
Normal file
|
@ -0,0 +1,155 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_AUDIO_H
|
||||
#define _FLUIDSYNTH_AUDIO_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup audio_output Audio Output
|
||||
*
|
||||
* Functions for managing audio drivers and file renderers.
|
||||
*
|
||||
* The file renderer is used for fast rendering of MIDI files to
|
||||
* audio files. The audio drivers are a high-level interface to
|
||||
* connect the synthesizer with external audio sinks or to render
|
||||
* real-time audio to files.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup audio_driver Audio Driver
|
||||
* @ingroup audio_output
|
||||
*
|
||||
* Functions for managing audio drivers.
|
||||
*
|
||||
* Defines functions for creating audio driver output. Use
|
||||
* new_fluid_audio_driver() to create a new audio driver for a given synth
|
||||
* and configuration settings.
|
||||
*
|
||||
* The function new_fluid_audio_driver2() can be
|
||||
* used if custom audio processing is desired before the audio is sent to the
|
||||
* audio driver (although it is not as efficient).
|
||||
*
|
||||
* @sa @ref CreatingAudioDriver
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Callback function type used with new_fluid_audio_driver2() to allow for
|
||||
* custom user audio processing before the audio is sent to the driver.
|
||||
*
|
||||
* @param data The user data parameter as passed to new_fluid_audio_driver2().
|
||||
* @param len Count of audio frames to synthesize.
|
||||
* @param nfx Count of arrays in \c fx.
|
||||
* @param fx Array of buffers to store effects audio to. Buffers may alias with buffers of \c out.
|
||||
* @param nout Count of arrays in \c out.
|
||||
* @param out Array of buffers to store (dry) audio to. Buffers may alias with buffers of \c fx.
|
||||
* @return Should return #FLUID_OK on success, #FLUID_FAILED if an error occurred.
|
||||
*
|
||||
* This function is responsible for rendering audio to the buffers.
|
||||
* The buffers passed to this function are allocated and owned by the respective
|
||||
* audio driver and are only valid during that specific call (do not cache them).
|
||||
* The buffers have already been zeroed-out.
|
||||
* For further details please refer to fluid_synth_process().
|
||||
*
|
||||
* @parblock
|
||||
* @note Whereas fluid_synth_process() allows aliasing buffers, there is the guarantee that @p out
|
||||
* and @p fx buffers provided by fluidsynth's audio drivers never alias. This prevents downstream
|
||||
* applications from e.g. applying a custom effect accidentally to the same buffer multiple times.
|
||||
* @endparblock
|
||||
*
|
||||
* @parblock
|
||||
* @note Also note that the Jack driver is currently the only driver that has dedicated @p fx buffers
|
||||
* (but only if \setting{audio_jack_multi} is true). All other drivers do not provide @p fx buffers.
|
||||
* In this case, users are encouraged to mix the effects into the provided dry buffers when calling
|
||||
* fluid_synth_process().
|
||||
* @code{.cpp}
|
||||
int myCallback(void *, int len, int nfx, float *fx[], int nout, float *out[])
|
||||
{
|
||||
int ret;
|
||||
if(nfx == 0)
|
||||
{
|
||||
float *fxb[4] = {out[0], out[1], out[0], out[1]};
|
||||
ret = fluid_synth_process(synth, len, sizeof(fxb) / sizeof(fxb[0]), fxb, nout, out);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = fluid_synth_process(synth, len, nfx, fx, nout, out);
|
||||
}
|
||||
// ... client-code ...
|
||||
return ret;
|
||||
}
|
||||
* @endcode
|
||||
* For other possible use-cases refer to \ref fluidsynth_process.c .
|
||||
* @endparblock
|
||||
*/
|
||||
typedef int (*fluid_audio_func_t)(void *data, int len,
|
||||
int nfx, float *fx[],
|
||||
int nout, float *out[]);
|
||||
|
||||
/** @startlifecycle{Audio Driver} */
|
||||
FLUIDSYNTH_API fluid_audio_driver_t *new_fluid_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
|
||||
FLUIDSYNTH_API fluid_audio_driver_t *new_fluid_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
|
||||
FLUIDSYNTH_API void delete_fluid_audio_driver(fluid_audio_driver_t *driver);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_audio_driver_register(const char **adrivers);
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @defgroup file_renderer File Renderer
|
||||
* @ingroup audio_output
|
||||
*
|
||||
* Functions for managing file renderers and triggering the rendering.
|
||||
*
|
||||
* The file renderer is only used to render a MIDI file to audio as fast
|
||||
* as possible. Please see \ref FileRenderer for a full example.
|
||||
*
|
||||
* If you are looking for a way to write audio generated
|
||||
* from real-time events (for example from an external sequencer or a MIDI controller) to a file,
|
||||
* please have a look at the \c file \ref audio_driver instead.
|
||||
*
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @startlifecycle{File Renderer} */
|
||||
FLUIDSYNTH_API fluid_file_renderer_t *new_fluid_file_renderer(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API void delete_fluid_file_renderer(fluid_file_renderer_t *dev);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_file_renderer_process_block(fluid_file_renderer_t *dev);
|
||||
FLUIDSYNTH_API int fluid_file_set_encoding_quality(fluid_file_renderer_t *dev, double q);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_AUDIO_H */
|
143
thirdparty/fluidsynth/include/fluidsynth/event.h
vendored
Normal file
143
thirdparty/fluidsynth/include/fluidsynth/event.h
vendored
Normal file
|
@ -0,0 +1,143 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_EVENT_H
|
||||
#define _FLUIDSYNTH_EVENT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup sequencer_events Sequencer Events
|
||||
* @ingroup sequencer
|
||||
*
|
||||
* Create, modify, query and destroy sequencer events.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Sequencer event type enumeration.
|
||||
*/
|
||||
enum fluid_seq_event_type
|
||||
{
|
||||
FLUID_SEQ_NOTE = 0, /**< Note event with duration */
|
||||
FLUID_SEQ_NOTEON, /**< Note on event */
|
||||
FLUID_SEQ_NOTEOFF, /**< Note off event */
|
||||
FLUID_SEQ_ALLSOUNDSOFF, /**< All sounds off event */
|
||||
FLUID_SEQ_ALLNOTESOFF, /**< All notes off event */
|
||||
FLUID_SEQ_BANKSELECT, /**< Bank select message */
|
||||
FLUID_SEQ_PROGRAMCHANGE, /**< Program change message */
|
||||
FLUID_SEQ_PROGRAMSELECT, /**< Program select message */
|
||||
FLUID_SEQ_PITCHBEND, /**< Pitch bend message */
|
||||
FLUID_SEQ_PITCHWHEELSENS, /**< Pitch wheel sensitivity set message @since 1.1.0 was misspelled previously */
|
||||
FLUID_SEQ_MODULATION, /**< Modulation controller event */
|
||||
FLUID_SEQ_SUSTAIN, /**< Sustain controller event */
|
||||
FLUID_SEQ_CONTROLCHANGE, /**< MIDI control change event */
|
||||
FLUID_SEQ_PAN, /**< Stereo pan set event */
|
||||
FLUID_SEQ_VOLUME, /**< Volume set event */
|
||||
FLUID_SEQ_REVERBSEND, /**< Reverb send set event */
|
||||
FLUID_SEQ_CHORUSSEND, /**< Chorus send set event */
|
||||
FLUID_SEQ_TIMER, /**< Timer event (useful for giving a callback at a certain time) */
|
||||
FLUID_SEQ_CHANNELPRESSURE, /**< Channel aftertouch event @since 1.1.0 */
|
||||
FLUID_SEQ_KEYPRESSURE, /**< Polyphonic aftertouch event @since 2.0.0 */
|
||||
FLUID_SEQ_SYSTEMRESET, /**< System reset event @since 1.1.0 */
|
||||
FLUID_SEQ_UNREGISTERING, /**< Called when a sequencer client is being unregistered. @since 1.1.0 */
|
||||
FLUID_SEQ_SCALE, /**< Sets a new time scale for the sequencer @since 2.2.0 */
|
||||
FLUID_SEQ_LASTEVENT /**< @internal Defines the count of events enums @warning This symbol
|
||||
is not part of the public API and ABI stability guarantee and
|
||||
may change at any time! */
|
||||
};
|
||||
|
||||
/* Event alloc/free */
|
||||
/** @startlifecycle{Sequencer Event} */
|
||||
FLUIDSYNTH_API fluid_event_t *new_fluid_event(void);
|
||||
FLUIDSYNTH_API void delete_fluid_event(fluid_event_t *evt);
|
||||
/** @endlifecycle */
|
||||
|
||||
/* Initializing events */
|
||||
FLUIDSYNTH_API void fluid_event_set_source(fluid_event_t *evt, fluid_seq_id_t src);
|
||||
FLUIDSYNTH_API void fluid_event_set_dest(fluid_event_t *evt, fluid_seq_id_t dest);
|
||||
|
||||
/* Timer events */
|
||||
FLUIDSYNTH_API void fluid_event_timer(fluid_event_t *evt, void *data);
|
||||
|
||||
/* Note events */
|
||||
FLUIDSYNTH_API void fluid_event_note(fluid_event_t *evt, int channel,
|
||||
short key, short vel,
|
||||
unsigned int duration);
|
||||
|
||||
FLUIDSYNTH_API void fluid_event_noteon(fluid_event_t *evt, int channel, short key, short vel);
|
||||
FLUIDSYNTH_API void fluid_event_noteoff(fluid_event_t *evt, int channel, short key);
|
||||
FLUIDSYNTH_API void fluid_event_all_sounds_off(fluid_event_t *evt, int channel);
|
||||
FLUIDSYNTH_API void fluid_event_all_notes_off(fluid_event_t *evt, int channel);
|
||||
|
||||
/* Instrument selection */
|
||||
FLUIDSYNTH_API void fluid_event_bank_select(fluid_event_t *evt, int channel, short bank_num);
|
||||
FLUIDSYNTH_API void fluid_event_program_change(fluid_event_t *evt, int channel, int preset_num);
|
||||
FLUIDSYNTH_API void fluid_event_program_select(fluid_event_t *evt, int channel, unsigned int sfont_id, short bank_num, short preset_num);
|
||||
|
||||
/* Real-time generic instrument controllers */
|
||||
FLUIDSYNTH_API
|
||||
void fluid_event_control_change(fluid_event_t *evt, int channel, short control, int val);
|
||||
|
||||
/* Real-time instrument controllers shortcuts */
|
||||
FLUIDSYNTH_API void fluid_event_pitch_bend(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_pitch_wheelsens(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_modulation(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_sustain(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_pan(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_volume(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_reverb_send(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_chorus_send(fluid_event_t *evt, int channel, int val);
|
||||
|
||||
FLUIDSYNTH_API void fluid_event_key_pressure(fluid_event_t *evt, int channel, short key, int val);
|
||||
FLUIDSYNTH_API void fluid_event_channel_pressure(fluid_event_t *evt, int channel, int val);
|
||||
FLUIDSYNTH_API void fluid_event_system_reset(fluid_event_t *evt);
|
||||
|
||||
/* Only when unregistering clients */
|
||||
FLUIDSYNTH_API void fluid_event_unregistering(fluid_event_t *evt);
|
||||
|
||||
FLUIDSYNTH_API void fluid_event_scale(fluid_event_t *evt, double new_scale);
|
||||
FLUIDSYNTH_API int fluid_event_from_midi_event(fluid_event_t *, const fluid_midi_event_t *);
|
||||
|
||||
/* Accessing event data */
|
||||
FLUIDSYNTH_API int fluid_event_get_type(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API fluid_seq_id_t fluid_event_get_source(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API fluid_seq_id_t fluid_event_get_dest(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_event_get_channel(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API short fluid_event_get_key(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API short fluid_event_get_velocity(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API short fluid_event_get_control(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_event_get_value(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_event_get_program(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API void *fluid_event_get_data(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API unsigned int fluid_event_get_duration(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API short fluid_event_get_bank(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_event_get_pitch(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API double fluid_event_get_scale(fluid_event_t *evt);
|
||||
FLUIDSYNTH_API unsigned int fluid_event_get_sfont_id(fluid_event_t *evt);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FLUIDSYNTH_EVENT_H */
|
134
thirdparty/fluidsynth/include/fluidsynth/gen.h
vendored
Normal file
134
thirdparty/fluidsynth/include/fluidsynth/gen.h
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_GEN_H
|
||||
#define _FLUIDSYNTH_GEN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup generators SoundFont Generators
|
||||
* @ingroup soundfonts
|
||||
*
|
||||
* Functions and defines for SoundFont generator effects.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generator (effect) numbers (Soundfont 2.01 specifications section 8.1.3)
|
||||
*/
|
||||
enum fluid_gen_type
|
||||
{
|
||||
GEN_STARTADDROFS, /**< Sample start address offset (0-32767) */
|
||||
GEN_ENDADDROFS, /**< Sample end address offset (-32767-0) */
|
||||
GEN_STARTLOOPADDROFS, /**< Sample loop start address offset (-32767-32767) */
|
||||
GEN_ENDLOOPADDROFS, /**< Sample loop end address offset (-32767-32767) */
|
||||
GEN_STARTADDRCOARSEOFS, /**< Sample start address coarse offset (X 32768) */
|
||||
GEN_MODLFOTOPITCH, /**< Modulation LFO to pitch */
|
||||
GEN_VIBLFOTOPITCH, /**< Vibrato LFO to pitch */
|
||||
GEN_MODENVTOPITCH, /**< Modulation envelope to pitch */
|
||||
GEN_FILTERFC, /**< Filter cutoff */
|
||||
GEN_FILTERQ, /**< Filter Q */
|
||||
GEN_MODLFOTOFILTERFC, /**< Modulation LFO to filter cutoff */
|
||||
GEN_MODENVTOFILTERFC, /**< Modulation envelope to filter cutoff */
|
||||
GEN_ENDADDRCOARSEOFS, /**< Sample end address coarse offset (X 32768) */
|
||||
GEN_MODLFOTOVOL, /**< Modulation LFO to volume */
|
||||
GEN_UNUSED1, /**< Unused */
|
||||
GEN_CHORUSSEND, /**< Chorus send amount */
|
||||
GEN_REVERBSEND, /**< Reverb send amount */
|
||||
GEN_PAN, /**< Stereo panning */
|
||||
GEN_UNUSED2, /**< Unused */
|
||||
GEN_UNUSED3, /**< Unused */
|
||||
GEN_UNUSED4, /**< Unused */
|
||||
GEN_MODLFODELAY, /**< Modulation LFO delay */
|
||||
GEN_MODLFOFREQ, /**< Modulation LFO frequency */
|
||||
GEN_VIBLFODELAY, /**< Vibrato LFO delay */
|
||||
GEN_VIBLFOFREQ, /**< Vibrato LFO frequency */
|
||||
GEN_MODENVDELAY, /**< Modulation envelope delay */
|
||||
GEN_MODENVATTACK, /**< Modulation envelope attack */
|
||||
GEN_MODENVHOLD, /**< Modulation envelope hold */
|
||||
GEN_MODENVDECAY, /**< Modulation envelope decay */
|
||||
GEN_MODENVSUSTAIN, /**< Modulation envelope sustain */
|
||||
GEN_MODENVRELEASE, /**< Modulation envelope release */
|
||||
GEN_KEYTOMODENVHOLD, /**< Key to modulation envelope hold */
|
||||
GEN_KEYTOMODENVDECAY, /**< Key to modulation envelope decay */
|
||||
GEN_VOLENVDELAY, /**< Volume envelope delay */
|
||||
GEN_VOLENVATTACK, /**< Volume envelope attack */
|
||||
GEN_VOLENVHOLD, /**< Volume envelope hold */
|
||||
GEN_VOLENVDECAY, /**< Volume envelope decay */
|
||||
GEN_VOLENVSUSTAIN, /**< Volume envelope sustain */
|
||||
GEN_VOLENVRELEASE, /**< Volume envelope release */
|
||||
GEN_KEYTOVOLENVHOLD, /**< Key to volume envelope hold */
|
||||
GEN_KEYTOVOLENVDECAY, /**< Key to volume envelope decay */
|
||||
GEN_INSTRUMENT, /**< Instrument ID (shouldn't be set by user) */
|
||||
GEN_RESERVED1, /**< Reserved */
|
||||
GEN_KEYRANGE, /**< MIDI note range */
|
||||
GEN_VELRANGE, /**< MIDI velocity range */
|
||||
GEN_STARTLOOPADDRCOARSEOFS, /**< Sample start loop address coarse offset (X 32768) */
|
||||
GEN_KEYNUM, /**< Fixed MIDI note number */
|
||||
GEN_VELOCITY, /**< Fixed MIDI velocity value */
|
||||
GEN_ATTENUATION, /**< Initial volume attenuation */
|
||||
GEN_RESERVED2, /**< Reserved */
|
||||
GEN_ENDLOOPADDRCOARSEOFS, /**< Sample end loop address coarse offset (X 32768) */
|
||||
GEN_COARSETUNE, /**< Coarse tuning */
|
||||
GEN_FINETUNE, /**< Fine tuning */
|
||||
GEN_SAMPLEID, /**< Sample ID (shouldn't be set by user) */
|
||||
GEN_SAMPLEMODE, /**< Sample mode flags */
|
||||
GEN_RESERVED3, /**< Reserved */
|
||||
GEN_SCALETUNE, /**< Scale tuning */
|
||||
GEN_EXCLUSIVECLASS, /**< Exclusive class number */
|
||||
GEN_OVERRIDEROOTKEY, /**< Sample root note override */
|
||||
|
||||
/**
|
||||
* Initial Pitch
|
||||
*
|
||||
* @note This is not "standard" SoundFont generator, because it is not
|
||||
* mentioned in the list of generators in the SF2 specifications.
|
||||
* It is used by FluidSynth internally to compute the nominal pitch of
|
||||
* a note on note-on event. By nature it shouldn't be allowed to be modulated,
|
||||
* however the specification defines a default modulator having "Initial Pitch"
|
||||
* as destination (cf. SF2.01 page 57 section 8.4.10 MIDI Pitch Wheel to Initial Pitch).
|
||||
* Thus it is impossible to cancel this default modulator, which would be required
|
||||
* to let the MIDI Pitch Wheel controller modulate a different generator.
|
||||
* In order to provide this flexibility, FluidSynth >= 2.1.0 uses a default modulator
|
||||
* "Pitch Wheel to Fine Tune", rather than Initial Pitch. The same "compromise" can
|
||||
* be found on the Audigy 2 ZS for instance.
|
||||
*/
|
||||
GEN_PITCH,
|
||||
|
||||
GEN_CUSTOM_BALANCE, /**< Balance @note Not a real SoundFont generator */
|
||||
/* non-standard generator for an additional custom high- or low-pass filter */
|
||||
GEN_CUSTOM_FILTERFC, /**< Custom filter cutoff frequency */
|
||||
GEN_CUSTOM_FILTERQ, /**< Custom filter Q */
|
||||
|
||||
GEN_LAST /**< @internal Value defines the count of generators (#fluid_gen_type)
|
||||
@warning This symbol is not part of the public API and ABI
|
||||
stability guarantee and may change at any time! */
|
||||
};
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FLUIDSYNTH_GEN_H */
|
||||
|
69
thirdparty/fluidsynth/include/fluidsynth/ladspa.h
vendored
Normal file
69
thirdparty/fluidsynth/include/fluidsynth/ladspa.h
vendored
Normal file
|
@ -0,0 +1,69 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_LADSPA_H
|
||||
#define _FLUIDSYNTH_LADSPA_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup ladspa Effect - LADSPA
|
||||
* @ingroup synth
|
||||
*
|
||||
* Functions for configuring the LADSPA effects unit
|
||||
*
|
||||
* This header defines useful functions for programmatically manipulating the ladspa
|
||||
* effects unit of the synth that can be retrieved via fluid_synth_get_ladspa_fx().
|
||||
*
|
||||
* Using any of those functions requires fluidsynth to be compiled with LADSPA support.
|
||||
* Else all of those functions are useless dummies.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API int fluid_ladspa_is_active(fluid_ladspa_fx_t *fx);
|
||||
FLUIDSYNTH_API int fluid_ladspa_activate(fluid_ladspa_fx_t *fx);
|
||||
FLUIDSYNTH_API int fluid_ladspa_deactivate(fluid_ladspa_fx_t *fx);
|
||||
FLUIDSYNTH_API int fluid_ladspa_reset(fluid_ladspa_fx_t *fx);
|
||||
FLUIDSYNTH_API int fluid_ladspa_check(fluid_ladspa_fx_t *fx, char *err, int err_size);
|
||||
|
||||
FLUIDSYNTH_API int fluid_ladspa_host_port_exists(fluid_ladspa_fx_t *fx, const char *name);
|
||||
|
||||
FLUIDSYNTH_API int fluid_ladspa_add_buffer(fluid_ladspa_fx_t *fx, const char *name);
|
||||
FLUIDSYNTH_API int fluid_ladspa_buffer_exists(fluid_ladspa_fx_t *fx, const char *name);
|
||||
|
||||
FLUIDSYNTH_API int fluid_ladspa_add_effect(fluid_ladspa_fx_t *fx, const char *effect_name,
|
||||
const char *lib_name, const char *plugin_name);
|
||||
FLUIDSYNTH_API int fluid_ladspa_effect_can_mix(fluid_ladspa_fx_t *fx, const char *name);
|
||||
FLUIDSYNTH_API int fluid_ladspa_effect_set_mix(fluid_ladspa_fx_t *fx, const char *name, int mix, float gain);
|
||||
FLUIDSYNTH_API int fluid_ladspa_effect_port_exists(fluid_ladspa_fx_t *fx, const char *effect_name, const char *port_name);
|
||||
FLUIDSYNTH_API int fluid_ladspa_effect_set_control(fluid_ladspa_fx_t *fx, const char *effect_name,
|
||||
const char *port_name, float val);
|
||||
FLUIDSYNTH_API int fluid_ladspa_effect_link(fluid_ladspa_fx_t *fx, const char *effect_name,
|
||||
const char *port_name, const char *name);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_LADSPA_H */
|
||||
|
97
thirdparty/fluidsynth/include/fluidsynth/log.h
vendored
Normal file
97
thirdparty/fluidsynth/include/fluidsynth/log.h
vendored
Normal file
|
@ -0,0 +1,97 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_LOG_H
|
||||
#define _FLUIDSYNTH_LOG_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup logging Logging
|
||||
*
|
||||
* Logging interface
|
||||
*
|
||||
* The default logging function of the fluidsynth prints its messages to the
|
||||
* stderr. The synthesizer uses five level of messages: #FLUID_PANIC,
|
||||
* #FLUID_ERR, #FLUID_WARN, #FLUID_INFO, and #FLUID_DBG.
|
||||
*
|
||||
* A client application can install a new log function to handle the messages
|
||||
* differently. In the following example, the application sets a callback
|
||||
* function to display #FLUID_PANIC messages in a dialog, and ignores all other
|
||||
* messages by setting the log function to NULL:
|
||||
*
|
||||
* @code
|
||||
* fluid_set_log_function(FLUID_PANIC, show_dialog, (void*) root_window);
|
||||
* fluid_set_log_function(FLUID_ERR, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_WARN, NULL, NULL);
|
||||
* fluid_set_log_function(FLUID_DBG, NULL, NULL);
|
||||
* @endcode
|
||||
*
|
||||
* @note The logging configuration is global and not tied to a specific
|
||||
* synthesizer instance. That means that all synthesizer instances created in
|
||||
* the same process share the same logging configuration.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* FluidSynth log levels.
|
||||
*/
|
||||
enum fluid_log_level
|
||||
{
|
||||
FLUID_PANIC, /**< The synth can't function correctly any more */
|
||||
FLUID_ERR, /**< Serious error occurred */
|
||||
FLUID_WARN, /**< Warning */
|
||||
FLUID_INFO, /**< Verbose informational messages */
|
||||
FLUID_DBG, /**< Debugging messages */
|
||||
LAST_LOG_LEVEL /**< @internal This symbol is not part of the public API and ABI
|
||||
stability guarantee and may change at any time! */
|
||||
};
|
||||
|
||||
/**
|
||||
* Log function handler callback type used by fluid_set_log_function().
|
||||
*
|
||||
* @param level Log level (#fluid_log_level)
|
||||
* @param message Log message text
|
||||
* @param data User data pointer supplied to fluid_set_log_function().
|
||||
*/
|
||||
typedef void (*fluid_log_function_t)(int level, const char *message, void *data);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
fluid_log_function_t fluid_set_log_function(int level, fluid_log_function_t fun, void *data);
|
||||
|
||||
FLUIDSYNTH_API void fluid_default_log_function(int level, const char *message, void *data);
|
||||
|
||||
FLUIDSYNTH_API int fluid_log(int level, const char *fmt, ...)
|
||||
#if defined(__clang__) || defined(__GNUC__) || defined(__GNUG__)
|
||||
__attribute__ ((format (printf, 2, 3)))
|
||||
#endif
|
||||
;
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_LOG_H */
|
294
thirdparty/fluidsynth/include/fluidsynth/midi.h
vendored
Normal file
294
thirdparty/fluidsynth/include/fluidsynth/midi.h
vendored
Normal file
|
@ -0,0 +1,294 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_MIDI_H
|
||||
#define _FLUIDSYNTH_MIDI_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup midi_input MIDI Input
|
||||
*
|
||||
* MIDI Input Subsystem
|
||||
*
|
||||
* There are multiple ways to send MIDI events to the synthesizer. They can come
|
||||
* from MIDI files, from external MIDI sequencers or raw MIDI event sources,
|
||||
* can be modified via MIDI routers and also generated manually.
|
||||
*
|
||||
* The interface connecting all sources and sinks of MIDI events in libfluidsynth
|
||||
* is \ref handle_midi_event_func_t.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Generic callback function for MIDI event handler.
|
||||
*
|
||||
* @param data User defined data pointer
|
||||
* @param event The MIDI event
|
||||
* @return Should return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
*
|
||||
* This callback is used to pass MIDI events
|
||||
* - from \ref midi_player, \ref midi_router or \ref midi_driver
|
||||
* - to \ref midi_router via fluid_midi_router_handle_midi_event()
|
||||
* - or to \ref synth via fluid_synth_handle_midi_event().
|
||||
*
|
||||
* Additionally, there is a translation layer to pass MIDI events to
|
||||
* a \ref sequencer via fluid_sequencer_add_midi_event_to_buffer().
|
||||
*/
|
||||
typedef int (*handle_midi_event_func_t)(void *data, fluid_midi_event_t *event);
|
||||
|
||||
/**
|
||||
* Generic callback function fired once by MIDI tick change.
|
||||
*
|
||||
* @param data User defined data pointer
|
||||
* @param tick The current (zero-based) tick, which triggered the callback
|
||||
* @return Should return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
*
|
||||
* This callback is fired at a constant rate depending on the current BPM and PPQ.
|
||||
* e.g. for PPQ = 192 and BPM = 140 the callback is fired 192 * 140 times per minute (448/sec).
|
||||
*
|
||||
* It can be used to sync external elements with the beat,
|
||||
* or stop / loop the song on a given tick.
|
||||
* Ticks being BPM-dependent, you can manipulate values such as bars or beats,
|
||||
* without having to care about BPM.
|
||||
*
|
||||
* For example, this callback loops the song whenever it reaches the 5th bar :
|
||||
*
|
||||
* @code{.cpp}
|
||||
int handle_tick(void *data, int tick)
|
||||
{
|
||||
fluid_player_t *player = (fluid_player_t *)data;
|
||||
int ppq = 192; // From MIDI header
|
||||
int beatsPerBar = 4; // From the song's time signature
|
||||
int loopBar = 5;
|
||||
int loopTick = (loopBar - 1) * ppq * beatsPerBar;
|
||||
|
||||
if (tick == loopTick)
|
||||
{
|
||||
return fluid_player_seek(player, 0);
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
* @endcode
|
||||
*/
|
||||
typedef int (*handle_midi_tick_func_t)(void *data, int tick);
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @defgroup midi_events MIDI Events
|
||||
* @ingroup midi_input
|
||||
*
|
||||
* Functions to create, modify, query and delete MIDI events.
|
||||
*
|
||||
* These functions are intended to be used in MIDI routers and other filtering
|
||||
* and processing functions in the MIDI event path. If you want to simply
|
||||
* send MIDI messages to the synthesizer, you can use the more convenient
|
||||
* \ref midi_messages interface.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
/** @startlifecycle{MIDI Event} */
|
||||
FLUIDSYNTH_API fluid_midi_event_t *new_fluid_midi_event(void);
|
||||
FLUIDSYNTH_API void delete_fluid_midi_event(fluid_midi_event_t *event);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_type(fluid_midi_event_t *evt, int type);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_type(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_channel(fluid_midi_event_t *evt, int chan);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_channel(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_key(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_key(fluid_midi_event_t *evt, int key);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_velocity(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_velocity(fluid_midi_event_t *evt, int vel);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_control(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_control(fluid_midi_event_t *evt, int ctrl);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_value(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_value(fluid_midi_event_t *evt, int val);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_program(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_program(fluid_midi_event_t *evt, int val);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_pitch(const fluid_midi_event_t *evt);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_pitch(fluid_midi_event_t *evt, int val);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_sysex(fluid_midi_event_t *evt, void *data,
|
||||
int size, int dynamic);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_text(fluid_midi_event_t *evt,
|
||||
void *data, int size, int dynamic);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_text(fluid_midi_event_t *evt,
|
||||
void **data, int *size);
|
||||
FLUIDSYNTH_API int fluid_midi_event_set_lyrics(fluid_midi_event_t *evt,
|
||||
void *data, int size, int dynamic);
|
||||
FLUIDSYNTH_API int fluid_midi_event_get_lyrics(fluid_midi_event_t *evt,
|
||||
void **data, int *size);
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @defgroup midi_router MIDI Router
|
||||
* @ingroup midi_input
|
||||
*
|
||||
* Rule based transformation and filtering of MIDI events.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIDI router rule type.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
FLUID_MIDI_ROUTER_RULE_NOTE, /**< MIDI note rule */
|
||||
FLUID_MIDI_ROUTER_RULE_CC, /**< MIDI controller rule */
|
||||
FLUID_MIDI_ROUTER_RULE_PROG_CHANGE, /**< MIDI program change rule */
|
||||
FLUID_MIDI_ROUTER_RULE_PITCH_BEND, /**< MIDI pitch bend rule */
|
||||
FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE, /**< MIDI channel pressure rule */
|
||||
FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE, /**< MIDI key pressure rule */
|
||||
FLUID_MIDI_ROUTER_RULE_COUNT /**< @internal Total count of rule types. This symbol
|
||||
is not part of the public API and ABI stability
|
||||
guarantee and may change at any time!*/
|
||||
} fluid_midi_router_rule_type;
|
||||
|
||||
|
||||
/** @startlifecycle{MIDI Router} */
|
||||
FLUIDSYNTH_API fluid_midi_router_t *new_fluid_midi_router(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
FLUIDSYNTH_API void delete_fluid_midi_router(fluid_midi_router_t *handler);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_midi_router_set_default_rules(fluid_midi_router_t *router);
|
||||
FLUIDSYNTH_API int fluid_midi_router_clear_rules(fluid_midi_router_t *router);
|
||||
FLUIDSYNTH_API int fluid_midi_router_add_rule(fluid_midi_router_t *router,
|
||||
fluid_midi_router_rule_t *rule, int type);
|
||||
|
||||
|
||||
/** @startlifecycle{MIDI Router Rule} */
|
||||
FLUIDSYNTH_API fluid_midi_router_rule_t *new_fluid_midi_router_rule(void);
|
||||
FLUIDSYNTH_API void delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API void fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule,
|
||||
int min, int max, float mul, int add);
|
||||
FLUIDSYNTH_API void fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule,
|
||||
int min, int max, float mul, int add);
|
||||
FLUIDSYNTH_API void fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t *rule,
|
||||
int min, int max, float mul, int add);
|
||||
FLUIDSYNTH_API int fluid_midi_router_handle_midi_event(void *data, fluid_midi_event_t *event);
|
||||
FLUIDSYNTH_API int fluid_midi_dump_prerouter(void *data, fluid_midi_event_t *event);
|
||||
FLUIDSYNTH_API int fluid_midi_dump_postrouter(void *data, fluid_midi_event_t *event);
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @defgroup midi_driver MIDI Driver
|
||||
* @ingroup midi_input
|
||||
*
|
||||
* Functions for managing MIDI drivers.
|
||||
*
|
||||
* The available MIDI drivers depend on your platform. See \ref settings_midi for all
|
||||
* available configuration options.
|
||||
*
|
||||
* To create a MIDI driver, you need to specify a source for the MIDI events to be
|
||||
* forwarded to via the \ref fluid_midi_event_t callback. Normally this will be
|
||||
* either a \ref midi_router via fluid_midi_router_handle_midi_event() or the synthesizer
|
||||
* via fluid_synth_handle_midi_event().
|
||||
*
|
||||
* But you can also write your own handler function that preprocesses the events and
|
||||
* forwards them on to the router or synthesizer instead.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @startlifecycle{MIDI Driver} */
|
||||
FLUIDSYNTH_API
|
||||
fluid_midi_driver_t *new_fluid_midi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
|
||||
FLUIDSYNTH_API void delete_fluid_midi_driver(fluid_midi_driver_t *driver);
|
||||
/** @endlifecycle */
|
||||
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @defgroup midi_player MIDI File Player
|
||||
* @ingroup midi_input
|
||||
*
|
||||
* Parse standard MIDI files and emit MIDI events.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* MIDI File Player status enum.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
enum fluid_player_status
|
||||
{
|
||||
FLUID_PLAYER_READY, /**< Player is ready */
|
||||
FLUID_PLAYER_PLAYING, /**< Player is currently playing */
|
||||
FLUID_PLAYER_STOPPING, /**< Player is stopping, but hasn't finished yet (currently unused) */
|
||||
FLUID_PLAYER_DONE /**< Player is finished playing */
|
||||
};
|
||||
|
||||
/**
|
||||
* MIDI File Player tempo enum.
|
||||
* @since 2.2.0
|
||||
*/
|
||||
enum fluid_player_set_tempo_type
|
||||
{
|
||||
FLUID_PLAYER_TEMPO_INTERNAL, /**< Use midi file tempo set in midi file (120 bpm by default). Multiplied by a factor */
|
||||
FLUID_PLAYER_TEMPO_EXTERNAL_BPM, /**< Set player tempo in bpm, supersede midi file tempo */
|
||||
FLUID_PLAYER_TEMPO_EXTERNAL_MIDI, /**< Set player tempo in us per quarter note, supersede midi file tempo */
|
||||
FLUID_PLAYER_TEMPO_NBR /**< @internal Value defines the count of player tempo type (#fluid_player_set_tempo_type) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
|
||||
};
|
||||
|
||||
/** @startlifecycle{MIDI File Player} */
|
||||
FLUIDSYNTH_API fluid_player_t *new_fluid_player(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API void delete_fluid_player(fluid_player_t *player);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_player_add(fluid_player_t *player, const char *midifile);
|
||||
FLUIDSYNTH_API int fluid_player_add_mem(fluid_player_t *player, const void *buffer, size_t len);
|
||||
FLUIDSYNTH_API int fluid_player_play(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_stop(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_join(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_set_loop(fluid_player_t *player, int loop);
|
||||
FLUIDSYNTH_API int fluid_player_set_tempo(fluid_player_t *player, int tempo_type, double tempo);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_player_set_midi_tempo(fluid_player_t *player, int tempo);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_player_set_bpm(fluid_player_t *player, int bpm);
|
||||
FLUIDSYNTH_API int fluid_player_set_playback_callback(fluid_player_t *player, handle_midi_event_func_t handler, void *handler_data);
|
||||
FLUIDSYNTH_API int fluid_player_set_tick_callback(fluid_player_t *player, handle_midi_tick_func_t handler, void *handler_data);
|
||||
|
||||
FLUIDSYNTH_API int fluid_player_get_status(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_get_current_tick(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_get_total_ticks(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_get_bpm(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_get_midi_tempo(fluid_player_t *player);
|
||||
FLUIDSYNTH_API int fluid_player_seek(fluid_player_t *player, int ticks);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_MIDI_H */
|
77
thirdparty/fluidsynth/include/fluidsynth/misc.h
vendored
Normal file
77
thirdparty/fluidsynth/include/fluidsynth/misc.h
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_MISC_H
|
||||
#define _FLUIDSYNTH_MISC_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup misc Miscellaneous
|
||||
*
|
||||
* Miscellaneous utility functions and defines
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Value that indicates success, used by most libfluidsynth functions.
|
||||
*
|
||||
* @note This was not publicly defined prior to libfluidsynth 1.1.0. When
|
||||
* writing code which should also be compatible with older versions, something
|
||||
* like the following can be used:
|
||||
*
|
||||
* @code
|
||||
* #include <fluidsynth.h>
|
||||
*
|
||||
* #ifndef FLUID_OK
|
||||
* #define FLUID_OK (0)
|
||||
* #define FLUID_FAILED (-1)
|
||||
* #endif
|
||||
* @endcode
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
#define FLUID_OK (0)
|
||||
|
||||
/**
|
||||
* Value that indicates failure, used by most libfluidsynth functions.
|
||||
*
|
||||
* @note See #FLUID_OK for more details.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
#define FLUID_FAILED (-1)
|
||||
|
||||
|
||||
FLUIDSYNTH_API int fluid_is_soundfont(const char *filename);
|
||||
FLUIDSYNTH_API int fluid_is_midifile(const char *filename);
|
||||
FLUIDSYNTH_API void fluid_free(void* ptr);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_MISC_H */
|
105
thirdparty/fluidsynth/include/fluidsynth/mod.h
vendored
Normal file
105
thirdparty/fluidsynth/include/fluidsynth/mod.h
vendored
Normal file
|
@ -0,0 +1,105 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_MOD_H
|
||||
#define _FLUIDSYNTH_MOD_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup modulators SoundFont Modulators
|
||||
* @ingroup soundfonts
|
||||
*
|
||||
* SoundFont modulator functions and constants.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Flags defining the polarity, mapping function and type of a modulator source.
|
||||
* Compare with SoundFont 2.04 PDF section 8.2.
|
||||
*
|
||||
* Note: Bit values do not correspond to the SoundFont spec! Also note that
|
||||
* #FLUID_MOD_GC and #FLUID_MOD_CC are in the flags field instead of the source field.
|
||||
*/
|
||||
enum fluid_mod_flags
|
||||
{
|
||||
FLUID_MOD_POSITIVE = 0, /**< Mapping function is positive */
|
||||
FLUID_MOD_NEGATIVE = 1, /**< Mapping function is negative */
|
||||
FLUID_MOD_UNIPOLAR = 0, /**< Mapping function is unipolar */
|
||||
FLUID_MOD_BIPOLAR = 2, /**< Mapping function is bipolar */
|
||||
FLUID_MOD_LINEAR = 0, /**< Linear mapping function */
|
||||
FLUID_MOD_CONCAVE = 4, /**< Concave mapping function */
|
||||
FLUID_MOD_CONVEX = 8, /**< Convex mapping function */
|
||||
FLUID_MOD_SWITCH = 12, /**< Switch (on/off) mapping function */
|
||||
FLUID_MOD_GC = 0, /**< General controller source type (#fluid_mod_src) */
|
||||
FLUID_MOD_CC = 16, /**< MIDI CC controller (source will be a MIDI CC number) */
|
||||
|
||||
FLUID_MOD_SIN = 0x80, /**< Custom non-standard sinus mapping function */
|
||||
};
|
||||
|
||||
/**
|
||||
* General controller (if #FLUID_MOD_GC in flags). This
|
||||
* corresponds to SoundFont 2.04 PDF section 8.2.1
|
||||
*/
|
||||
enum fluid_mod_src
|
||||
{
|
||||
FLUID_MOD_NONE = 0, /**< No source controller */
|
||||
FLUID_MOD_VELOCITY = 2, /**< MIDI note-on velocity */
|
||||
FLUID_MOD_KEY = 3, /**< MIDI note-on note number */
|
||||
FLUID_MOD_KEYPRESSURE = 10, /**< MIDI key pressure */
|
||||
FLUID_MOD_CHANNELPRESSURE = 13, /**< MIDI channel pressure */
|
||||
FLUID_MOD_PITCHWHEEL = 14, /**< Pitch wheel */
|
||||
FLUID_MOD_PITCHWHEELSENS = 16 /**< Pitch wheel sensitivity */
|
||||
};
|
||||
|
||||
/** @startlifecycle{Modulator} */
|
||||
FLUIDSYNTH_API fluid_mod_t *new_fluid_mod(void);
|
||||
FLUIDSYNTH_API void delete_fluid_mod(fluid_mod_t *mod);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API size_t fluid_mod_sizeof(void);
|
||||
|
||||
FLUIDSYNTH_API void fluid_mod_set_source1(fluid_mod_t *mod, int src, int flags);
|
||||
FLUIDSYNTH_API void fluid_mod_set_source2(fluid_mod_t *mod, int src, int flags);
|
||||
FLUIDSYNTH_API void fluid_mod_set_dest(fluid_mod_t *mod, int dst);
|
||||
FLUIDSYNTH_API void fluid_mod_set_amount(fluid_mod_t *mod, double amount);
|
||||
|
||||
FLUIDSYNTH_API int fluid_mod_get_source1(const fluid_mod_t *mod);
|
||||
FLUIDSYNTH_API int fluid_mod_get_flags1(const fluid_mod_t *mod);
|
||||
FLUIDSYNTH_API int fluid_mod_get_source2(const fluid_mod_t *mod);
|
||||
FLUIDSYNTH_API int fluid_mod_get_flags2(const fluid_mod_t *mod);
|
||||
FLUIDSYNTH_API int fluid_mod_get_dest(const fluid_mod_t *mod);
|
||||
FLUIDSYNTH_API double fluid_mod_get_amount(const fluid_mod_t *mod);
|
||||
|
||||
FLUIDSYNTH_API int fluid_mod_test_identity(const fluid_mod_t *mod1, const fluid_mod_t *mod2);
|
||||
FLUIDSYNTH_API int fluid_mod_has_source(const fluid_mod_t *mod, int cc, int ctrl);
|
||||
FLUIDSYNTH_API int fluid_mod_has_dest(const fluid_mod_t *mod, int gen);
|
||||
|
||||
FLUIDSYNTH_API void fluid_mod_clone(fluid_mod_t *mod, const fluid_mod_t *src);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FLUIDSYNTH_MOD_H */
|
||||
|
92
thirdparty/fluidsynth/include/fluidsynth/seq.h
vendored
Normal file
92
thirdparty/fluidsynth/include/fluidsynth/seq.h
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_SEQ_H
|
||||
#define _FLUIDSYNTH_SEQ_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup sequencer MIDI Sequencer
|
||||
*
|
||||
* MIDI event sequencer.
|
||||
*
|
||||
* The MIDI sequencer can be used to play MIDI events in a more flexible way than
|
||||
* using the MIDI file player, which expects the events to be stored as
|
||||
* Standard MIDI Files. Using the sequencer, you can provide the events one by
|
||||
* one, with an optional timestamp for scheduling.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Event callback prototype for destination clients.
|
||||
*
|
||||
* @param time Current sequencer tick value (see fluid_sequencer_get_tick()).
|
||||
* @param event The event being received
|
||||
* @param seq The sequencer instance
|
||||
* @param data User defined data registered with the client
|
||||
*
|
||||
* @note @p time may not be of the same tick value as the scheduled event! In fact, depending on
|
||||
* the sequencer's scale and the synth's sample-rate, @p time may be a few ticks too late. Although this
|
||||
* itself is inaudible, it is important to consider,
|
||||
* when you use this callback for enqueuing additional events over and over again with
|
||||
* fluid_sequencer_send_at(): If you enqueue new events with a relative tick value you might introduce
|
||||
* a timing error, which causes your sequence to sound e.g. slower than it's supposed to be. If this is
|
||||
* your use-case, make sure to enqueue events with an absolute tick value.
|
||||
*/
|
||||
typedef void (*fluid_event_callback_t)(unsigned int time, fluid_event_t *event,
|
||||
fluid_sequencer_t *seq, void *data);
|
||||
|
||||
|
||||
/** @startlifecycle{MIDI Sequencer} */
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API fluid_sequencer_t *new_fluid_sequencer(void);
|
||||
FLUIDSYNTH_API fluid_sequencer_t *new_fluid_sequencer2(int use_system_timer);
|
||||
FLUIDSYNTH_API void delete_fluid_sequencer(fluid_sequencer_t *seq);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_sequencer_get_use_system_timer(fluid_sequencer_t *seq);
|
||||
FLUIDSYNTH_API
|
||||
fluid_seq_id_t fluid_sequencer_register_client(fluid_sequencer_t *seq, const char *name,
|
||||
fluid_event_callback_t callback, void *data);
|
||||
FLUIDSYNTH_API void fluid_sequencer_unregister_client(fluid_sequencer_t *seq, fluid_seq_id_t id);
|
||||
FLUIDSYNTH_API int fluid_sequencer_count_clients(fluid_sequencer_t *seq);
|
||||
FLUIDSYNTH_API fluid_seq_id_t fluid_sequencer_get_client_id(fluid_sequencer_t *seq, int index);
|
||||
FLUIDSYNTH_API char *fluid_sequencer_get_client_name(fluid_sequencer_t *seq, fluid_seq_id_t id);
|
||||
FLUIDSYNTH_API int fluid_sequencer_client_is_dest(fluid_sequencer_t *seq, fluid_seq_id_t id);
|
||||
FLUIDSYNTH_API void fluid_sequencer_process(fluid_sequencer_t *seq, unsigned int msec);
|
||||
FLUIDSYNTH_API void fluid_sequencer_send_now(fluid_sequencer_t *seq, fluid_event_t *evt);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_sequencer_send_at(fluid_sequencer_t *seq, fluid_event_t *evt,
|
||||
unsigned int time, int absolute);
|
||||
FLUIDSYNTH_API
|
||||
void fluid_sequencer_remove_events(fluid_sequencer_t *seq, fluid_seq_id_t source, fluid_seq_id_t dest, int type);
|
||||
FLUIDSYNTH_API unsigned int fluid_sequencer_get_tick(fluid_sequencer_t *seq);
|
||||
FLUIDSYNTH_API void fluid_sequencer_set_time_scale(fluid_sequencer_t *seq, double scale);
|
||||
FLUIDSYNTH_API double fluid_sequencer_get_time_scale(fluid_sequencer_t *seq);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_SEQ_H */
|
45
thirdparty/fluidsynth/include/fluidsynth/seqbind.h
vendored
Normal file
45
thirdparty/fluidsynth/include/fluidsynth/seqbind.h
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_SEQBIND_H
|
||||
#define _FLUIDSYNTH_SEQBIND_H
|
||||
|
||||
#include "seq.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup sequencer
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API
|
||||
fluid_seq_id_t fluid_sequencer_register_fluidsynth(fluid_sequencer_t *seq, fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_sequencer_add_midi_event_to_buffer(void *data, fluid_midi_event_t *event);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FLUIDSYNTH_SEQBIND_H */
|
||||
|
194
thirdparty/fluidsynth/include/fluidsynth/settings.h
vendored
Normal file
194
thirdparty/fluidsynth/include/fluidsynth/settings.h
vendored
Normal file
|
@ -0,0 +1,194 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_SETTINGS_H
|
||||
#define _FLUIDSYNTH_SETTINGS_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup settings Settings
|
||||
*
|
||||
* Functions for settings management
|
||||
*
|
||||
* To create a synthesizer object you will have to specify its
|
||||
* settings. These settings are stored in a fluid_settings_t object.
|
||||
* @code
|
||||
* void
|
||||
* my_synthesizer ()
|
||||
* {
|
||||
* fluid_settings_t *settings;
|
||||
* fluid_synth_t *synth;
|
||||
* fluid_audio_driver_t *adriver;
|
||||
*
|
||||
* settings = new_fluid_settings ();
|
||||
* fluid_settings_setstr(settings, "audio.driver", "alsa");
|
||||
* // ... change settings ...
|
||||
* synth = new_fluid_synth (settings);
|
||||
* adriver = new_fluid_audio_driver (settings, synth);
|
||||
* // ...
|
||||
* }
|
||||
* @endcode
|
||||
* @sa @ref CreatingSettings
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Hint FLUID_HINT_BOUNDED_BELOW indicates that the LowerBound field
|
||||
* of the FLUID_PortRangeHint should be considered meaningful. The
|
||||
* value in this field should be considered the (inclusive) lower
|
||||
* bound of the valid range. If FLUID_HINT_SAMPLE_RATE is also
|
||||
* specified then the value of LowerBound should be multiplied by the
|
||||
* sample rate.
|
||||
*/
|
||||
#define FLUID_HINT_BOUNDED_BELOW 0x1
|
||||
|
||||
/** Hint FLUID_HINT_BOUNDED_ABOVE indicates that the UpperBound field
|
||||
of the FLUID_PortRangeHint should be considered meaningful. The
|
||||
value in this field should be considered the (inclusive) upper
|
||||
bound of the valid range. If FLUID_HINT_SAMPLE_RATE is also
|
||||
specified then the value of UpperBound should be multiplied by the
|
||||
sample rate. */
|
||||
#define FLUID_HINT_BOUNDED_ABOVE 0x2
|
||||
|
||||
/**
|
||||
* Hint FLUID_HINT_TOGGLED indicates that the data item should be
|
||||
* considered a Boolean toggle. Data less than or equal to zero should
|
||||
* be considered `off' or `false,' and data above zero should be
|
||||
* considered `on' or `true.' FLUID_HINT_TOGGLED may not be used in
|
||||
* conjunction with any other hint.
|
||||
*/
|
||||
#define FLUID_HINT_TOGGLED 0x4
|
||||
|
||||
#define FLUID_HINT_OPTIONLIST 0x02 /**< Setting is a list of string options */
|
||||
|
||||
|
||||
/**
|
||||
* Settings type
|
||||
*
|
||||
* Each setting has a defined type: numeric (double), integer, string or a
|
||||
* set of values. The type of each setting can be retrieved using the
|
||||
* function fluid_settings_get_type()
|
||||
*/
|
||||
enum fluid_types_enum
|
||||
{
|
||||
FLUID_NO_TYPE = -1, /**< Undefined type */
|
||||
FLUID_NUM_TYPE, /**< Numeric (double) */
|
||||
FLUID_INT_TYPE, /**< Integer */
|
||||
FLUID_STR_TYPE, /**< String */
|
||||
FLUID_SET_TYPE /**< Set of values */
|
||||
};
|
||||
|
||||
/** @startlifecycle{Settings} */
|
||||
FLUIDSYNTH_API fluid_settings_t *new_fluid_settings(void);
|
||||
FLUIDSYNTH_API void delete_fluid_settings(fluid_settings_t *settings);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_get_type(fluid_settings_t *settings, const char *name);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_get_hints(fluid_settings_t *settings, const char *name, int *val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_is_realtime(fluid_settings_t *settings, const char *name);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_setstr(fluid_settings_t *settings, const char *name, const char *str);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_copystr(fluid_settings_t *settings, const char *name, char *str, int len);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_dupstr(fluid_settings_t *settings, const char *name, char **str);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getstr_default(fluid_settings_t *settings, const char *name, char **def);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_str_equal(fluid_settings_t *settings, const char *name, const char *value);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_setnum(fluid_settings_t *settings, const char *name, double val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getnum(fluid_settings_t *settings, const char *name, double *val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getnum_default(fluid_settings_t *settings, const char *name, double *val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getnum_range(fluid_settings_t *settings, const char *name,
|
||||
double *min, double *max);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_setint(fluid_settings_t *settings, const char *name, int val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getint(fluid_settings_t *settings, const char *name, int *val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getint_default(fluid_settings_t *settings, const char *name, int *val);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_getint_range(fluid_settings_t *settings, const char *name,
|
||||
int *min, int *max);
|
||||
|
||||
/**
|
||||
* Callback function type used with fluid_settings_foreach_option()
|
||||
*
|
||||
* @param data User defined data pointer
|
||||
* @param name Setting name
|
||||
* @param option A string option for this setting (iterates through the list)
|
||||
*/
|
||||
typedef void (*fluid_settings_foreach_option_t)(void *data, const char *name, const char *option);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
void fluid_settings_foreach_option(fluid_settings_t *settings,
|
||||
const char *name, void *data,
|
||||
fluid_settings_foreach_option_t func);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_settings_option_count(fluid_settings_t *settings, const char *name);
|
||||
FLUIDSYNTH_API char *fluid_settings_option_concat(fluid_settings_t *settings,
|
||||
const char *name,
|
||||
const char *separator);
|
||||
|
||||
/**
|
||||
* Callback function type used with fluid_settings_foreach()
|
||||
*
|
||||
* @param data User defined data pointer
|
||||
* @param name Setting name
|
||||
* @param type Setting type (#fluid_types_enum)
|
||||
*/
|
||||
typedef void (*fluid_settings_foreach_t)(void *data, const char *name, int type);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
void fluid_settings_foreach(fluid_settings_t *settings, void *data,
|
||||
fluid_settings_foreach_t func);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_SETTINGS_H */
|
362
thirdparty/fluidsynth/include/fluidsynth/sfont.h
vendored
Normal file
362
thirdparty/fluidsynth/include/fluidsynth/sfont.h
vendored
Normal file
|
@ -0,0 +1,362 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_SFONT_H
|
||||
#define _FLUIDSYNTH_SFONT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup soundfonts SoundFonts
|
||||
*
|
||||
* SoundFont related functions
|
||||
*
|
||||
* This part of the API contains functions, defines and types that are mostly
|
||||
* only used by internal or custom SoundFont loaders or client code that
|
||||
* modifies loaded presets, SoundFonts or voices directly.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup soundfont_loader SoundFont Loader
|
||||
* @ingroup soundfonts
|
||||
*
|
||||
* Create custom SoundFont loaders
|
||||
*
|
||||
* It is possible to add new SoundFont loaders to the
|
||||
* synthesizer. This API allows for virtual SoundFont files to be loaded
|
||||
* and synthesized, which may not actually be SoundFont files, as long as they
|
||||
* can be represented by the SoundFont synthesis model.
|
||||
*
|
||||
* To add a new SoundFont loader to the synthesizer, call
|
||||
* fluid_synth_add_sfloader() and pass a pointer to an
|
||||
* #fluid_sfloader_t instance created by new_fluid_sfloader().
|
||||
* On creation, you must specify a callback function \p load
|
||||
* that will be called for every file attempting to load it and
|
||||
* if successful returns a #fluid_sfont_t instance, or NULL if it fails.
|
||||
*
|
||||
* The #fluid_sfont_t structure contains a callback to obtain the
|
||||
* name of the SoundFont. It contains two functions to iterate
|
||||
* though the contained presets, and one function to obtain a
|
||||
* preset corresponding to a bank and preset number. This
|
||||
* function should return a #fluid_preset_t instance.
|
||||
*
|
||||
* The #fluid_preset_t instance contains some functions to obtain
|
||||
* information from the preset (name, bank, number). The most
|
||||
* important callback is the noteon function. The noteon function
|
||||
* is called by fluidsynth internally and
|
||||
* should call fluid_synth_alloc_voice() for every sample that has
|
||||
* to be played. fluid_synth_alloc_voice() expects a pointer to a
|
||||
* #fluid_sample_t instance and returns a pointer to the opaque
|
||||
* #fluid_voice_t structure. To set or increment the values of a
|
||||
* generator, use fluid_voice_gen_set() or fluid_voice_gen_incr(). When you are
|
||||
* finished initializing the voice call fluid_voice_start() to
|
||||
* start playing the synthesis voice.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Some notification enums for presets and samples.
|
||||
*/
|
||||
enum
|
||||
{
|
||||
FLUID_PRESET_SELECTED, /**< Preset selected notify */
|
||||
FLUID_PRESET_UNSELECTED, /**< Preset unselected notify */
|
||||
FLUID_SAMPLE_DONE, /**< Sample no longer needed notify */
|
||||
FLUID_PRESET_PIN, /**< Request to pin preset samples to cache */
|
||||
FLUID_PRESET_UNPIN /**< Request to unpin preset samples from cache */
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates the type of a sample used by the _fluid_sample_t::sampletype field.
|
||||
*
|
||||
* This enum corresponds to the \c SFSampleLink enum in the SoundFont spec.
|
||||
* One \c flag may be bit-wise OR-ed with one \c value.
|
||||
*/
|
||||
enum fluid_sample_type
|
||||
{
|
||||
FLUID_SAMPLETYPE_MONO = 0x1, /**< Value used for mono samples */
|
||||
FLUID_SAMPLETYPE_RIGHT = 0x2, /**< Value used for right samples of a stereo pair */
|
||||
FLUID_SAMPLETYPE_LEFT = 0x4, /**< Value used for left samples of a stereo pair */
|
||||
FLUID_SAMPLETYPE_LINKED = 0x8, /**< Value used for linked sample, which is currently not supported */
|
||||
FLUID_SAMPLETYPE_OGG_VORBIS = 0x10, /**< Flag used for Ogg Vorbis compressed samples (non-standard compliant extension) as found in the program "sftools" developed by Werner Schweer from MuseScore @since 1.1.7 */
|
||||
FLUID_SAMPLETYPE_ROM = 0x8000 /**< Flag that indicates ROM samples, causing the sample to be ignored */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Method to load an instrument file (does not actually need to be a real file name,
|
||||
* could be another type of string identifier that the \a loader understands).
|
||||
*
|
||||
* @param loader SoundFont loader
|
||||
* @param filename File name or other string identifier
|
||||
* @return The loaded instrument file (SoundFont) or NULL if an error occurred.
|
||||
*/
|
||||
typedef fluid_sfont_t *(*fluid_sfloader_load_t)(fluid_sfloader_t *loader, const char *filename);
|
||||
|
||||
/**
|
||||
* The free method should free the memory allocated for a fluid_sfloader_t instance in
|
||||
* addition to any private data.
|
||||
*
|
||||
* @param loader SoundFont loader
|
||||
*
|
||||
* Any custom user provided cleanup function must ultimately call
|
||||
* delete_fluid_sfloader() to ensure proper cleanup of the #fluid_sfloader_t struct. If no private data
|
||||
* needs to be freed, setting this to delete_fluid_sfloader() is sufficient.
|
||||
*
|
||||
*/
|
||||
typedef void (*fluid_sfloader_free_t)(fluid_sfloader_t *loader);
|
||||
|
||||
|
||||
/** @startlifecycle{SoundFont Loader} */
|
||||
FLUIDSYNTH_API fluid_sfloader_t *new_fluid_sfloader(fluid_sfloader_load_t load, fluid_sfloader_free_t free);
|
||||
FLUIDSYNTH_API void delete_fluid_sfloader(fluid_sfloader_t *loader);
|
||||
|
||||
FLUIDSYNTH_API fluid_sfloader_t *new_fluid_defsfloader(fluid_settings_t *settings);
|
||||
/** @endlifecycle */
|
||||
|
||||
/**
|
||||
* Opens the file or memory indicated by \c filename in binary read mode.
|
||||
*
|
||||
* @return returns a file handle on success, NULL otherwise
|
||||
*
|
||||
* \c filename matches the string provided during the fluid_synth_sfload() call.
|
||||
*/
|
||||
typedef void *(* fluid_sfloader_callback_open_t)(const char *filename);
|
||||
|
||||
/**
|
||||
* Reads \c count bytes to the specified buffer \c buf.
|
||||
*
|
||||
* @return returns #FLUID_OK if exactly \c count bytes were successfully read, else returns #FLUID_FAILED and leaves \a buf unmodified.
|
||||
*/
|
||||
typedef int (* fluid_sfloader_callback_read_t)(void *buf, fluid_long_long_t count, void *handle);
|
||||
|
||||
/**
|
||||
* Same purpose and behaviour as fseek.
|
||||
*
|
||||
* @param origin either \c SEEK_SET, \c SEEK_CUR or \c SEEK_END
|
||||
* @return returns #FLUID_OK if the seek was successfully performed while not seeking beyond a buffer or file, #FLUID_FAILED otherwise
|
||||
*/
|
||||
typedef int (* fluid_sfloader_callback_seek_t)(void *handle, fluid_long_long_t offset, int origin);
|
||||
|
||||
/**
|
||||
* Closes the handle returned by #fluid_sfloader_callback_open_t and frees used resources.
|
||||
*
|
||||
* @return returns #FLUID_OK on success, #FLUID_FAILED on error
|
||||
*/
|
||||
typedef int (* fluid_sfloader_callback_close_t)(void *handle);
|
||||
|
||||
/** @return returns current file offset or #FLUID_FAILED on error */
|
||||
typedef fluid_long_long_t (* fluid_sfloader_callback_tell_t)(void *handle);
|
||||
|
||||
|
||||
FLUIDSYNTH_API int fluid_sfloader_set_callbacks(fluid_sfloader_t *loader,
|
||||
fluid_sfloader_callback_open_t open,
|
||||
fluid_sfloader_callback_read_t read,
|
||||
fluid_sfloader_callback_seek_t seek,
|
||||
fluid_sfloader_callback_tell_t tell,
|
||||
fluid_sfloader_callback_close_t close);
|
||||
|
||||
FLUIDSYNTH_API int fluid_sfloader_set_data(fluid_sfloader_t *loader, void *data);
|
||||
FLUIDSYNTH_API void *fluid_sfloader_get_data(fluid_sfloader_t *loader);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Method to return the name of a virtual SoundFont.
|
||||
*
|
||||
* @param sfont Virtual SoundFont
|
||||
* @return The name of the virtual SoundFont.
|
||||
*/
|
||||
typedef const char *(*fluid_sfont_get_name_t)(fluid_sfont_t *sfont);
|
||||
|
||||
/**
|
||||
* Get a virtual SoundFont preset by bank and program numbers.
|
||||
*
|
||||
* @param sfont Virtual SoundFont
|
||||
* @param bank MIDI bank number (0-16383)
|
||||
* @param prenum MIDI preset number (0-127)
|
||||
* @return Should return an allocated virtual preset or NULL if it could not
|
||||
* be found.
|
||||
*/
|
||||
typedef fluid_preset_t *(*fluid_sfont_get_preset_t)(fluid_sfont_t *sfont, int bank, int prenum);
|
||||
|
||||
/**
|
||||
* Start virtual SoundFont preset iteration method.
|
||||
*
|
||||
* @param sfont Virtual SoundFont
|
||||
*
|
||||
* Starts/re-starts virtual preset iteration in a SoundFont.
|
||||
*/
|
||||
typedef void (*fluid_sfont_iteration_start_t)(fluid_sfont_t *sfont);
|
||||
|
||||
/**
|
||||
* Virtual SoundFont preset iteration function.
|
||||
*
|
||||
* @param sfont Virtual SoundFont
|
||||
* @return NULL when no more presets are available, otherwise the a pointer to the current preset
|
||||
*
|
||||
* Returns preset information to the caller. The returned buffer is only valid until a subsequent
|
||||
* call to this function.
|
||||
*/
|
||||
typedef fluid_preset_t *(*fluid_sfont_iteration_next_t)(fluid_sfont_t *sfont);
|
||||
|
||||
/**
|
||||
* Method to free a virtual SoundFont bank.
|
||||
*
|
||||
* @param sfont Virtual SoundFont to free.
|
||||
* @return Should return 0 when it was able to free all resources or non-zero
|
||||
* if some of the samples could not be freed because they are still in use,
|
||||
* in which case the free will be tried again later, until success.
|
||||
*
|
||||
* Any custom user provided cleanup function must ultimately call
|
||||
* delete_fluid_sfont() to ensure proper cleanup of the #fluid_sfont_t struct. If no private data
|
||||
* needs to be freed, setting this to delete_fluid_sfont() is sufficient.
|
||||
*/
|
||||
typedef int (*fluid_sfont_free_t)(fluid_sfont_t *sfont);
|
||||
|
||||
|
||||
/** @startlifecycle{SoundFont} */
|
||||
FLUIDSYNTH_API fluid_sfont_t *new_fluid_sfont(fluid_sfont_get_name_t get_name,
|
||||
fluid_sfont_get_preset_t get_preset,
|
||||
fluid_sfont_iteration_start_t iter_start,
|
||||
fluid_sfont_iteration_next_t iter_next,
|
||||
fluid_sfont_free_t free);
|
||||
|
||||
FLUIDSYNTH_API int delete_fluid_sfont(fluid_sfont_t *sfont);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_sfont_set_data(fluid_sfont_t *sfont, void *data);
|
||||
FLUIDSYNTH_API void *fluid_sfont_get_data(fluid_sfont_t *sfont);
|
||||
|
||||
FLUIDSYNTH_API int fluid_sfont_get_id(fluid_sfont_t *sfont);
|
||||
FLUIDSYNTH_API const char *fluid_sfont_get_name(fluid_sfont_t *sfont);
|
||||
FLUIDSYNTH_API fluid_preset_t *fluid_sfont_get_preset(fluid_sfont_t *sfont, int bank, int prenum);
|
||||
FLUIDSYNTH_API void fluid_sfont_iteration_start(fluid_sfont_t *sfont);
|
||||
FLUIDSYNTH_API fluid_preset_t *fluid_sfont_iteration_next(fluid_sfont_t *sfont);
|
||||
|
||||
/**
|
||||
* Method to get a virtual SoundFont preset name.
|
||||
*
|
||||
* @param preset Virtual SoundFont preset
|
||||
* @return Should return the name of the preset. The returned string must be
|
||||
* valid for the duration of the virtual preset (or the duration of the
|
||||
* SoundFont, in the case of preset iteration).
|
||||
*/
|
||||
typedef const char *(*fluid_preset_get_name_t)(fluid_preset_t *preset);
|
||||
|
||||
/**
|
||||
* Method to get a virtual SoundFont preset MIDI bank number.
|
||||
*
|
||||
* @param preset Virtual SoundFont preset
|
||||
* @param return The bank number of the preset
|
||||
*/
|
||||
typedef int (*fluid_preset_get_banknum_t)(fluid_preset_t *preset);
|
||||
|
||||
/**
|
||||
* Method to get a virtual SoundFont preset MIDI program number.
|
||||
*
|
||||
* @param preset Virtual SoundFont preset
|
||||
* @param return The program number of the preset
|
||||
*/
|
||||
typedef int (*fluid_preset_get_num_t)(fluid_preset_t *preset);
|
||||
|
||||
/**
|
||||
* Method to handle a noteon event (synthesize the instrument).
|
||||
*
|
||||
* @param preset Virtual SoundFont preset
|
||||
* @param synth Synthesizer instance
|
||||
* @param chan MIDI channel number of the note on event
|
||||
* @param key MIDI note number (0-127)
|
||||
* @param vel MIDI velocity (0-127)
|
||||
* @return #FLUID_OK on success (0) or #FLUID_FAILED (-1) otherwise
|
||||
*
|
||||
* This method may be called from within synthesis context and therefore
|
||||
* should be as efficient as possible and not perform any operations considered
|
||||
* bad for realtime audio output (memory allocations and other OS calls).
|
||||
*
|
||||
* Call fluid_synth_alloc_voice() for every sample that has
|
||||
* to be played. fluid_synth_alloc_voice() expects a pointer to a
|
||||
* #fluid_sample_t structure and returns a pointer to the opaque
|
||||
* #fluid_voice_t structure. To set or increment the values of a
|
||||
* generator, use fluid_voice_gen_set() or fluid_voice_gen_incr(). When you are
|
||||
* finished initializing the voice call fluid_voice_start() to
|
||||
* start playing the synthesis voice. Starting with FluidSynth 1.1.0 all voices
|
||||
* created will be started at the same time.
|
||||
*/
|
||||
typedef int (*fluid_preset_noteon_t)(fluid_preset_t *preset, fluid_synth_t *synth, int chan, int key, int vel);
|
||||
|
||||
/**
|
||||
* Method to free a virtual SoundFont preset.
|
||||
*
|
||||
* @param preset Virtual SoundFont preset
|
||||
* @return Should return 0
|
||||
*
|
||||
* Any custom user provided cleanup function must ultimately call
|
||||
* delete_fluid_preset() to ensure proper cleanup of the #fluid_preset_t struct. If no private data
|
||||
* needs to be freed, setting this to delete_fluid_preset() is sufficient.
|
||||
*/
|
||||
typedef void (*fluid_preset_free_t)(fluid_preset_t *preset);
|
||||
|
||||
/** @startlifecycle{Preset} */
|
||||
FLUIDSYNTH_API fluid_preset_t *new_fluid_preset(fluid_sfont_t *parent_sfont,
|
||||
fluid_preset_get_name_t get_name,
|
||||
fluid_preset_get_banknum_t get_bank,
|
||||
fluid_preset_get_num_t get_num,
|
||||
fluid_preset_noteon_t noteon,
|
||||
fluid_preset_free_t free);
|
||||
FLUIDSYNTH_API void delete_fluid_preset(fluid_preset_t *preset);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API int fluid_preset_set_data(fluid_preset_t *preset, void *data);
|
||||
FLUIDSYNTH_API void *fluid_preset_get_data(fluid_preset_t *preset);
|
||||
|
||||
FLUIDSYNTH_API const char *fluid_preset_get_name(fluid_preset_t *preset);
|
||||
FLUIDSYNTH_API int fluid_preset_get_banknum(fluid_preset_t *preset);
|
||||
FLUIDSYNTH_API int fluid_preset_get_num(fluid_preset_t *preset);
|
||||
FLUIDSYNTH_API fluid_sfont_t *fluid_preset_get_sfont(fluid_preset_t *preset);
|
||||
|
||||
/** @startlifecycle{Sample} */
|
||||
FLUIDSYNTH_API fluid_sample_t *new_fluid_sample(void);
|
||||
FLUIDSYNTH_API void delete_fluid_sample(fluid_sample_t *sample);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API size_t fluid_sample_sizeof(void);
|
||||
|
||||
FLUIDSYNTH_API int fluid_sample_set_name(fluid_sample_t *sample, const char *name);
|
||||
FLUIDSYNTH_API int fluid_sample_set_sound_data(fluid_sample_t *sample,
|
||||
short *data,
|
||||
char *data24,
|
||||
unsigned int nbframes,
|
||||
unsigned int sample_rate,
|
||||
short copy_data);
|
||||
|
||||
FLUIDSYNTH_API int fluid_sample_set_loop(fluid_sample_t *sample, unsigned int loop_start, unsigned int loop_end);
|
||||
FLUIDSYNTH_API int fluid_sample_set_pitch(fluid_sample_t *sample, int root_key, int fine_tune);
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_SFONT_H */
|
150
thirdparty/fluidsynth/include/fluidsynth/shell.h
vendored
Normal file
150
thirdparty/fluidsynth/include/fluidsynth/shell.h
vendored
Normal file
|
@ -0,0 +1,150 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_SHELL_H
|
||||
#define _FLUIDSYNTH_SHELL_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup command_interface Command Interface
|
||||
*
|
||||
* Control and configuration interface
|
||||
*
|
||||
* The command interface allows you to send textual commands to
|
||||
* the synthesizer, to parse a command file, or to read commands
|
||||
* from the stdin or other input streams (like a TCP socket).
|
||||
*
|
||||
* For a full list of available commands, type \c help in the
|
||||
* \ref command_shell or send the same command via a command handler.
|
||||
* Further documentation can be found at
|
||||
* https://github.com/FluidSynth/fluidsynth/wiki/UserManual#shell-commands
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API fluid_istream_t fluid_get_stdin(void);
|
||||
FLUIDSYNTH_API fluid_ostream_t fluid_get_stdout(void);
|
||||
FLUIDSYNTH_API char *fluid_get_userconf(char *buf, int len);
|
||||
FLUIDSYNTH_API char *fluid_get_sysconf(char *buf, int len);
|
||||
/* @} */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup command_handler Command Handler
|
||||
* @ingroup command_interface
|
||||
* @brief Handles text commands and reading of configuration files
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @startlifecycle{Command Handler} */
|
||||
FLUIDSYNTH_API
|
||||
fluid_cmd_handler_t *new_fluid_cmd_handler(fluid_synth_t *synth, fluid_midi_router_t *router);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
fluid_cmd_handler_t *new_fluid_cmd_handler2(fluid_settings_t *settings, fluid_synth_t *synth,
|
||||
fluid_midi_router_t *router, fluid_player_t *player);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
void delete_fluid_cmd_handler(fluid_cmd_handler_t *handler);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API
|
||||
void fluid_cmd_handler_set_synth(fluid_cmd_handler_t *handler, fluid_synth_t *synth);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_command(fluid_cmd_handler_t *handler, const char *cmd, fluid_ostream_t out);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_source(fluid_cmd_handler_t *handler, const char *filename);
|
||||
/* @} */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup command_shell Command Shell
|
||||
* @ingroup command_interface
|
||||
*
|
||||
* Interactive shell to control and configure a synthesizer instance.
|
||||
*
|
||||
* If you need a platform independent way to get the standard input
|
||||
* and output streams, use fluid_get_stdin() and fluid_get_stdout().
|
||||
*
|
||||
* For a full list of available commands, type \c help in the shell.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @startlifecycle{Command Shell} */
|
||||
FLUIDSYNTH_API
|
||||
fluid_shell_t *new_fluid_shell(fluid_settings_t *settings, fluid_cmd_handler_t *handler,
|
||||
fluid_istream_t in, fluid_ostream_t out, int thread);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
void fluid_usershell(fluid_settings_t *settings, fluid_cmd_handler_t *handler);
|
||||
|
||||
FLUIDSYNTH_API void delete_fluid_shell(fluid_shell_t *shell);
|
||||
/** @endlifecycle */
|
||||
|
||||
/* @} */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup command_server Command Server
|
||||
* @ingroup command_interface
|
||||
*
|
||||
* TCP socket server for a command handler.
|
||||
*
|
||||
* The socket server will open the TCP port set by \ref settings_shell_port
|
||||
* (default 9800) and starts a new thread and \ref command_handler for each
|
||||
* incoming connection.
|
||||
*
|
||||
* @note The server is only available if libfluidsynth has been compiled
|
||||
* with network support (enable-network). Without network support, all related
|
||||
* functions will return FLUID_FAILED or NULL.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @startlifecycle{Command Server} */
|
||||
FLUIDSYNTH_API
|
||||
fluid_server_t *new_fluid_server(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth, fluid_midi_router_t *router);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
fluid_server_t *new_fluid_server2(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth, fluid_midi_router_t *router,
|
||||
fluid_player_t *player);
|
||||
|
||||
FLUIDSYNTH_API void delete_fluid_server(fluid_server_t *server);
|
||||
|
||||
FLUIDSYNTH_API int fluid_server_join(fluid_server_t *server);
|
||||
/** @endlifecycle */
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_SHELL_H */
|
552
thirdparty/fluidsynth/include/fluidsynth/synth.h
vendored
Normal file
552
thirdparty/fluidsynth/include/fluidsynth/synth.h
vendored
Normal file
|
@ -0,0 +1,552 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_SYNTH_H
|
||||
#define _FLUIDSYNTH_SYNTH_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup synth Synthesizer
|
||||
*
|
||||
* SoundFont synthesizer
|
||||
*
|
||||
* You create a new synthesizer with new_fluid_synth() and you destroy
|
||||
* it with delete_fluid_synth(). Use the fluid_settings_t structure to specify
|
||||
* the synthesizer characteristics.
|
||||
*
|
||||
* You have to load a SoundFont in order to hear any sound. For that
|
||||
* you use the fluid_synth_sfload() function.
|
||||
*
|
||||
* You can use the audio driver functions to open
|
||||
* the audio device and create a background audio thread.
|
||||
*
|
||||
* The API for sending MIDI events is probably what you expect:
|
||||
* fluid_synth_noteon(), fluid_synth_noteoff(), ...
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @startlifecycle{Synthesizer} */
|
||||
FLUIDSYNTH_API fluid_synth_t *new_fluid_synth(fluid_settings_t *settings);
|
||||
FLUIDSYNTH_API void delete_fluid_synth(fluid_synth_t *synth);
|
||||
/** @endlifecycle */
|
||||
|
||||
FLUIDSYNTH_API double fluid_synth_get_cpu_load(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API const char *fluid_synth_error(fluid_synth_t *synth);
|
||||
/* @} */
|
||||
|
||||
/**
|
||||
* @defgroup midi_messages MIDI Channel Messages
|
||||
* @ingroup synth
|
||||
*
|
||||
* The MIDI channel message functions are mostly directly named after their
|
||||
* counterpart MIDI messages. They are a high-level interface to controlling
|
||||
* the synthesizer, playing notes and changing note and channel parameters.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API int fluid_synth_noteon(fluid_synth_t *synth, int chan, int key, int vel);
|
||||
FLUIDSYNTH_API int fluid_synth_noteoff(fluid_synth_t *synth, int chan, int key);
|
||||
FLUIDSYNTH_API int fluid_synth_cc(fluid_synth_t *synth, int chan, int ctrl, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_get_cc(fluid_synth_t *synth, int chan, int ctrl, int *pval);
|
||||
FLUIDSYNTH_API int fluid_synth_sysex(fluid_synth_t *synth, const char *data, int len,
|
||||
char *response, int *response_len, int *handled, int dryrun);
|
||||
FLUIDSYNTH_API int fluid_synth_pitch_bend(fluid_synth_t *synth, int chan, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_get_pitch_bend(fluid_synth_t *synth, int chan, int *ppitch_bend);
|
||||
FLUIDSYNTH_API int fluid_synth_pitch_wheel_sens(fluid_synth_t *synth, int chan, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_get_pitch_wheel_sens(fluid_synth_t *synth, int chan, int *pval);
|
||||
FLUIDSYNTH_API int fluid_synth_program_change(fluid_synth_t *synth, int chan, int program);
|
||||
FLUIDSYNTH_API int fluid_synth_channel_pressure(fluid_synth_t *synth, int chan, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_key_pressure(fluid_synth_t *synth, int chan, int key, int val);
|
||||
FLUIDSYNTH_API int fluid_synth_bank_select(fluid_synth_t *synth, int chan, int bank);
|
||||
FLUIDSYNTH_API int fluid_synth_sfont_select(fluid_synth_t *synth, int chan, int sfont_id);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_program_select(fluid_synth_t *synth, int chan, int sfont_id,
|
||||
int bank_num, int preset_num);
|
||||
FLUIDSYNTH_API int
|
||||
fluid_synth_program_select_by_sfont_name(fluid_synth_t *synth, int chan,
|
||||
const char *sfont_name, int bank_num,
|
||||
int preset_num);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_get_program(fluid_synth_t *synth, int chan, int *sfont_id,
|
||||
int *bank_num, int *preset_num);
|
||||
FLUIDSYNTH_API int fluid_synth_unset_program(fluid_synth_t *synth, int chan);
|
||||
FLUIDSYNTH_API int fluid_synth_program_reset(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_system_reset(fluid_synth_t *synth);
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_all_notes_off(fluid_synth_t *synth, int chan);
|
||||
FLUIDSYNTH_API int fluid_synth_all_sounds_off(fluid_synth_t *synth, int chan);
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_gen(fluid_synth_t *synth, int chan,
|
||||
int param, float value);
|
||||
FLUIDSYNTH_API float fluid_synth_get_gen(fluid_synth_t *synth, int chan, int param);
|
||||
/* @} MIDI Channel Messages */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup voice_control Synthesis Voice Control
|
||||
* @ingroup synth
|
||||
*
|
||||
* Low-level access to synthesis voices.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API int fluid_synth_start(fluid_synth_t *synth, unsigned int id,
|
||||
fluid_preset_t *preset, int audio_chan,
|
||||
int midi_chan, int key, int vel);
|
||||
FLUIDSYNTH_API int fluid_synth_stop(fluid_synth_t *synth, unsigned int id);
|
||||
|
||||
FLUIDSYNTH_API fluid_voice_t *fluid_synth_alloc_voice(fluid_synth_t *synth,
|
||||
fluid_sample_t *sample,
|
||||
int channum, int key, int vel);
|
||||
FLUIDSYNTH_API void fluid_synth_start_voice(fluid_synth_t *synth, fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API void fluid_synth_get_voicelist(fluid_synth_t *synth,
|
||||
fluid_voice_t *buf[], int bufsize, int ID);
|
||||
/* @} Voice Control */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup soundfont_management SoundFont Management
|
||||
* @ingroup synth
|
||||
*
|
||||
* Functions to load and unload SoundFonts.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_sfload(fluid_synth_t *synth, const char *filename, int reset_presets);
|
||||
FLUIDSYNTH_API int fluid_synth_sfreload(fluid_synth_t *synth, int id);
|
||||
FLUIDSYNTH_API int fluid_synth_sfunload(fluid_synth_t *synth, int id, int reset_presets);
|
||||
FLUIDSYNTH_API int fluid_synth_add_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont);
|
||||
FLUIDSYNTH_API int fluid_synth_remove_sfont(fluid_synth_t *synth, fluid_sfont_t *sfont);
|
||||
FLUIDSYNTH_API int fluid_synth_sfcount(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont(fluid_synth_t *synth, unsigned int num);
|
||||
FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont_by_id(fluid_synth_t *synth, int id);
|
||||
FLUIDSYNTH_API fluid_sfont_t *fluid_synth_get_sfont_by_name(fluid_synth_t *synth,
|
||||
const char *name);
|
||||
FLUIDSYNTH_API int fluid_synth_set_bank_offset(fluid_synth_t *synth, int sfont_id, int offset);
|
||||
FLUIDSYNTH_API int fluid_synth_get_bank_offset(fluid_synth_t *synth, int sfont_id);
|
||||
/* @} Soundfont Management */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup reverb_effect Effect - Reverb
|
||||
* @ingroup synth
|
||||
*
|
||||
* Functions for configuring the built-in reverb effect
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API void fluid_synth_set_reverb_on(fluid_synth_t *synth, int on);
|
||||
FLUIDSYNTH_API int fluid_synth_reverb_on(fluid_synth_t *synth, int fx_group, int on);
|
||||
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb(fluid_synth_t *synth, double roomsize,
|
||||
double damping, double width, double level);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_roomsize(fluid_synth_t *synth, double roomsize);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_damp(fluid_synth_t *synth, double damping);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_width(fluid_synth_t *synth, double width);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_reverb_level(fluid_synth_t *synth, double level);
|
||||
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_roomsize(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_damp(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_level(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_reverb_width(fluid_synth_t *synth);
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_reverb_group_roomsize(fluid_synth_t *synth, int fx_group, double roomsize);
|
||||
FLUIDSYNTH_API int fluid_synth_set_reverb_group_damp(fluid_synth_t *synth, int fx_group, double damping);
|
||||
FLUIDSYNTH_API int fluid_synth_set_reverb_group_width(fluid_synth_t *synth, int fx_group, double width);
|
||||
FLUIDSYNTH_API int fluid_synth_set_reverb_group_level(fluid_synth_t *synth, int fx_group, double level);
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_get_reverb_group_roomsize(fluid_synth_t *synth, int fx_group, double *roomsize);
|
||||
FLUIDSYNTH_API int fluid_synth_get_reverb_group_damp(fluid_synth_t *synth, int fx_group, double *damping);
|
||||
FLUIDSYNTH_API int fluid_synth_get_reverb_group_width(fluid_synth_t *synth, int fx_group, double *width);
|
||||
FLUIDSYNTH_API int fluid_synth_get_reverb_group_level(fluid_synth_t *synth, int fx_group, double *level);
|
||||
/* @} Reverb */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup chorus_effect Effect - Chorus
|
||||
* @ingroup synth
|
||||
*
|
||||
* Functions for configuring the built-in chorus effect
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Chorus modulation waveform type.
|
||||
*/
|
||||
enum fluid_chorus_mod
|
||||
{
|
||||
FLUID_CHORUS_MOD_SINE = 0, /**< Sine wave chorus modulation */
|
||||
FLUID_CHORUS_MOD_TRIANGLE = 1 /**< Triangle wave chorus modulation */
|
||||
};
|
||||
|
||||
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API void fluid_synth_set_chorus_on(fluid_synth_t *synth, int on);
|
||||
FLUIDSYNTH_API int fluid_synth_chorus_on(fluid_synth_t *synth, int fx_group, int on);
|
||||
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus(fluid_synth_t *synth, int nr, double level,
|
||||
double speed, double depth_ms, int type);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_nr(fluid_synth_t *synth, int nr);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_level(fluid_synth_t *synth, double level);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_speed(fluid_synth_t *synth, double speed);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_depth(fluid_synth_t *synth, double depth_ms);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_set_chorus_type(fluid_synth_t *synth, int type);
|
||||
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_get_chorus_nr(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_chorus_level(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_chorus_speed(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API double fluid_synth_get_chorus_depth(fluid_synth_t *synth);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_get_chorus_type(fluid_synth_t *synth); /* see fluid_chorus_mod */
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_chorus_group_nr(fluid_synth_t *synth, int fx_group, int nr);
|
||||
FLUIDSYNTH_API int fluid_synth_set_chorus_group_level(fluid_synth_t *synth, int fx_group, double level);
|
||||
FLUIDSYNTH_API int fluid_synth_set_chorus_group_speed(fluid_synth_t *synth, int fx_group, double speed);
|
||||
FLUIDSYNTH_API int fluid_synth_set_chorus_group_depth(fluid_synth_t *synth, int fx_group, double depth_ms);
|
||||
FLUIDSYNTH_API int fluid_synth_set_chorus_group_type(fluid_synth_t *synth, int fx_group, int type);
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_get_chorus_group_nr(fluid_synth_t *synth, int fx_group, int *nr);
|
||||
FLUIDSYNTH_API int fluid_synth_get_chorus_group_level(fluid_synth_t *synth, int fx_group, double *level);
|
||||
FLUIDSYNTH_API int fluid_synth_get_chorus_group_speed(fluid_synth_t *synth, int fx_group, double *speed);
|
||||
FLUIDSYNTH_API int fluid_synth_get_chorus_group_depth(fluid_synth_t *synth, int fx_group, double *depth_ms);
|
||||
FLUIDSYNTH_API int fluid_synth_get_chorus_group_type(fluid_synth_t *synth, int fx_group, int *type);
|
||||
/* @} Chorus */
|
||||
|
||||
/**
|
||||
* @defgroup synthesis_params Synthesis Parameters
|
||||
* @ingroup synth
|
||||
*
|
||||
* Functions to control and query synthesis parameters like gain and
|
||||
* polyphony count.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API int fluid_synth_count_midi_channels(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_count_audio_channels(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_count_audio_groups(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_count_effects_channels(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_count_effects_groups(fluid_synth_t *synth);
|
||||
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API void fluid_synth_set_sample_rate(fluid_synth_t *synth, float sample_rate);
|
||||
FLUIDSYNTH_API void fluid_synth_set_gain(fluid_synth_t *synth, float gain);
|
||||
FLUIDSYNTH_API float fluid_synth_get_gain(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_set_polyphony(fluid_synth_t *synth, int polyphony);
|
||||
FLUIDSYNTH_API int fluid_synth_get_polyphony(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_get_active_voice_count(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API int fluid_synth_get_internal_bufsize(fluid_synth_t *synth);
|
||||
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_set_interp_method(fluid_synth_t *synth, int chan, int interp_method);
|
||||
|
||||
/**
|
||||
* Synthesis interpolation method.
|
||||
*/
|
||||
enum fluid_interp
|
||||
{
|
||||
FLUID_INTERP_NONE = 0, /**< No interpolation: Fastest, but questionable audio quality */
|
||||
FLUID_INTERP_LINEAR = 1, /**< Straight-line interpolation: A bit slower, reasonable audio quality */
|
||||
FLUID_INTERP_4THORDER = 4, /**< Fourth-order interpolation, good quality, the default */
|
||||
FLUID_INTERP_7THORDER = 7, /**< Seventh-order interpolation */
|
||||
|
||||
FLUID_INTERP_DEFAULT = FLUID_INTERP_4THORDER, /**< Default interpolation method */
|
||||
FLUID_INTERP_HIGHEST = FLUID_INTERP_7THORDER, /**< Highest interpolation method */
|
||||
};
|
||||
|
||||
/**
|
||||
* Enum used with fluid_synth_add_default_mod() to specify how to handle duplicate modulators.
|
||||
*/
|
||||
enum fluid_synth_add_mod
|
||||
{
|
||||
FLUID_SYNTH_OVERWRITE, /**< Overwrite any existing matching modulator */
|
||||
FLUID_SYNTH_ADD, /**< Sum up modulator amounts */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_add_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod, int mode);
|
||||
FLUIDSYNTH_API int fluid_synth_remove_default_mod(fluid_synth_t *synth, const fluid_mod_t *mod);
|
||||
/* @} Synthesis Parameters */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup tuning MIDI Tuning
|
||||
* @ingroup synth
|
||||
*
|
||||
* The functions in this section implement the MIDI Tuning Standard interface.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_activate_key_tuning(fluid_synth_t *synth, int bank, int prog,
|
||||
const char *name, const double *pitch, int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_activate_octave_tuning(fluid_synth_t *synth, int bank, int prog,
|
||||
const char *name, const double *pitch, int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_tune_notes(fluid_synth_t *synth, int bank, int prog,
|
||||
int len, const int *keys, const double *pitch, int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_activate_tuning(fluid_synth_t *synth, int chan, int bank, int prog,
|
||||
int apply);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_deactivate_tuning(fluid_synth_t *synth, int chan, int apply);
|
||||
FLUIDSYNTH_API void fluid_synth_tuning_iteration_start(fluid_synth_t *synth);
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_tuning_iteration_next(fluid_synth_t *synth, int *bank, int *prog);
|
||||
FLUIDSYNTH_API int fluid_synth_tuning_dump(fluid_synth_t *synth, int bank, int prog,
|
||||
char *name, int len, double *pitch);
|
||||
/* @} MIDI Tuning */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup audio_rendering Audio Rendering
|
||||
* @ingroup synth
|
||||
*
|
||||
* The functions in this section can be used to render audio directly to
|
||||
* memory buffers. They are used internally by the \ref audio_driver and \ref file_renderer,
|
||||
* but can also be used manually for custom processing of the rendered audio.
|
||||
*
|
||||
* @note Please note that all following functions block during rendering. If your goal is to
|
||||
* render real-time audio, ensure that you call these functions from a high-priority
|
||||
* thread with little to no other duties other than calling the rendering functions.
|
||||
*
|
||||
* @warning
|
||||
* If a concurrently running thread calls any other sound affecting synth function
|
||||
* (e.g. fluid_synth_noteon(), fluid_synth_cc(), etc.) it is unspecified whether the event triggered by such a call
|
||||
* will be effective in the recently synthesized audio. While this is inaudible when only requesting small chunks from the
|
||||
* synth with every call (cf. fluid_synth_get_internal_bufsize()), it will become evident when requesting larger sample chunks:
|
||||
* With larger sample chunks it will get harder for the synth to react on those spontaneously occurring events in time
|
||||
* (like events received from a MIDI driver, or directly made synth API calls).
|
||||
* In those real-time scenarios, prefer requesting smaller
|
||||
* sample chunks from the synth with each call, to avoid poor quantization of your events in the synthesized audio.
|
||||
* This issue is not applicable when using the MIDI player or sequencer for event dispatching. Also
|
||||
* refer to the documentation of \setting{audio_period-size}.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
FLUIDSYNTH_API int fluid_synth_write_s16(fluid_synth_t *synth, int len,
|
||||
void *lout, int loff, int lincr,
|
||||
void *rout, int roff, int rincr);
|
||||
FLUIDSYNTH_API int fluid_synth_write_float(fluid_synth_t *synth, int len,
|
||||
void *lout, int loff, int lincr,
|
||||
void *rout, int roff, int rincr);
|
||||
FLUID_DEPRECATED FLUIDSYNTH_API int fluid_synth_nwrite_float(fluid_synth_t *synth, int len,
|
||||
float **left, float **right,
|
||||
float **fx_left, float **fx_right);
|
||||
FLUIDSYNTH_API int fluid_synth_process(fluid_synth_t *synth, int len,
|
||||
int nfx, float *fx[],
|
||||
int nout, float *out[]);
|
||||
/* @} Audio Rendering */
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup iir_filter Effect - IIR Filter
|
||||
* @ingroup synth
|
||||
*
|
||||
* Functions for configuring the built-in IIR filter effect
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Specifies the type of filter to use for the custom IIR filter
|
||||
*/
|
||||
enum fluid_iir_filter_type
|
||||
{
|
||||
FLUID_IIR_DISABLED = 0, /**< Custom IIR filter is not operating */
|
||||
FLUID_IIR_LOWPASS, /**< Custom IIR filter is operating as low-pass filter */
|
||||
FLUID_IIR_HIGHPASS, /**< Custom IIR filter is operating as high-pass filter */
|
||||
FLUID_IIR_LAST /**< @internal Value defines the count of filter types (#fluid_iir_filter_type) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies optional settings to use for the custom IIR filter. Can be bitwise ORed.
|
||||
*/
|
||||
enum fluid_iir_filter_flags
|
||||
{
|
||||
FLUID_IIR_Q_LINEAR = 1 << 0, /**< The Soundfont spec requires the filter Q to be interpreted in dB. If this flag is set the filter Q is instead assumed to be in a linear range */
|
||||
FLUID_IIR_Q_ZERO_OFF = 1 << 1, /**< If this flag the filter is switched off if Q == 0 (prior to any transformation) */
|
||||
FLUID_IIR_NO_GAIN_AMP = 1 << 2 /**< The Soundfont spec requires to correct the gain of the filter depending on the filter's Q. If this flag is set the filter gain will not be corrected. */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_custom_filter(fluid_synth_t *, int type, int flags);
|
||||
/* @} IIR Filter */
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup channel_setup MIDI Channel Setup
|
||||
* @ingroup synth
|
||||
*
|
||||
* The functions in this section provide interfaces to change the channel type
|
||||
* and to configure basic channels, legato and portamento setups.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @name Channel Type
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* The midi channel type used by fluid_synth_set_channel_type()
|
||||
*/
|
||||
enum fluid_midi_channel_type
|
||||
{
|
||||
CHANNEL_TYPE_MELODIC = 0, /**< Melodic midi channel */
|
||||
CHANNEL_TYPE_DRUM = 1 /**< Drum midi channel */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_channel_type(fluid_synth_t *synth, int chan, int type);
|
||||
/** @} Channel Type */
|
||||
|
||||
|
||||
/** @name Basic Channel Mode
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Channel mode bits OR-ed together so that it matches with the midi spec: poly omnion (0), mono omnion (1), poly omnioff (2), mono omnioff (3)
|
||||
*/
|
||||
enum fluid_channel_mode_flags
|
||||
{
|
||||
FLUID_CHANNEL_POLY_OFF = 0x01, /**< if flag is set, the basic channel is in mono on state, if not set poly is on */
|
||||
FLUID_CHANNEL_OMNI_OFF = 0x02, /**< if flag is set, the basic channel is in omni off state, if not set omni is on */
|
||||
};
|
||||
|
||||
/**
|
||||
* Indicates the mode a basic channel is set to
|
||||
*/
|
||||
enum fluid_basic_channel_modes
|
||||
{
|
||||
FLUID_CHANNEL_MODE_MASK = (FLUID_CHANNEL_OMNI_OFF | FLUID_CHANNEL_POLY_OFF), /**< Mask Poly and Omni bits of #fluid_channel_mode_flags, usually only used internally */
|
||||
FLUID_CHANNEL_MODE_OMNION_POLY = FLUID_CHANNEL_MODE_MASK & (~FLUID_CHANNEL_OMNI_OFF & ~FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 0 */
|
||||
FLUID_CHANNEL_MODE_OMNION_MONO = FLUID_CHANNEL_MODE_MASK & (~FLUID_CHANNEL_OMNI_OFF & FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 1 */
|
||||
FLUID_CHANNEL_MODE_OMNIOFF_POLY = FLUID_CHANNEL_MODE_MASK & (FLUID_CHANNEL_OMNI_OFF & ~FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 2 */
|
||||
FLUID_CHANNEL_MODE_OMNIOFF_MONO = FLUID_CHANNEL_MODE_MASK & (FLUID_CHANNEL_OMNI_OFF | FLUID_CHANNEL_POLY_OFF), /**< corresponds to MIDI mode 3 */
|
||||
FLUID_CHANNEL_MODE_LAST /**< @internal Value defines the count of basic channel modes (#fluid_basic_channel_modes) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_reset_basic_channel(fluid_synth_t *synth, int chan);
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_get_basic_channel(fluid_synth_t *synth, int chan,
|
||||
int *basic_chan_out,
|
||||
int *mode_chan_out,
|
||||
int *basic_val_out);
|
||||
FLUIDSYNTH_API int fluid_synth_set_basic_channel(fluid_synth_t *synth, int chan, int mode, int val);
|
||||
|
||||
/** @} Basic Channel Mode */
|
||||
|
||||
/** @name Legato Mode
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates the legato mode a channel is set to
|
||||
* n1,n2,n3,.. is a legato passage. n1 is the first note, and n2,n3,n4 are played legato with previous note. */
|
||||
enum fluid_channel_legato_mode
|
||||
{
|
||||
FLUID_CHANNEL_LEGATO_MODE_RETRIGGER, /**< Mode 0 - Release previous note, start a new note */
|
||||
FLUID_CHANNEL_LEGATO_MODE_MULTI_RETRIGGER, /**< Mode 1 - On contiguous notes retrigger in attack section using current value, shape attack using current dynamic and make use of previous voices if any */
|
||||
FLUID_CHANNEL_LEGATO_MODE_LAST /**< @internal Value defines the count of legato modes (#fluid_channel_legato_mode) @warning This symbol is not part of the public API and ABI stability guarantee and may change at any time! */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_legato_mode(fluid_synth_t *synth, int chan, int legatomode);
|
||||
FLUIDSYNTH_API int fluid_synth_get_legato_mode(fluid_synth_t *synth, int chan, int *legatomode);
|
||||
/** @} Legato Mode */
|
||||
|
||||
/** @name Portamento Mode
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates the portamento mode a channel is set to
|
||||
*/
|
||||
enum fluid_channel_portamento_mode
|
||||
{
|
||||
FLUID_CHANNEL_PORTAMENTO_MODE_EACH_NOTE, /**< Mode 0 - Portamento on each note (staccato or legato) */
|
||||
FLUID_CHANNEL_PORTAMENTO_MODE_LEGATO_ONLY, /**< Mode 1 - Portamento only on legato note */
|
||||
FLUID_CHANNEL_PORTAMENTO_MODE_STACCATO_ONLY, /**< Mode 2 - Portamento only on staccato note */
|
||||
FLUID_CHANNEL_PORTAMENTO_MODE_LAST /**< @internal Value defines the count of portamento modes
|
||||
@warning This symbol is not part of the public API and ABI
|
||||
stability guarantee and may change at any time! */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_portamento_mode(fluid_synth_t *synth,
|
||||
int chan, int portamentomode);
|
||||
FLUIDSYNTH_API int fluid_synth_get_portamento_mode(fluid_synth_t *synth,
|
||||
int chan, int *portamentomode);
|
||||
/** @} Portamento Mode */
|
||||
|
||||
/**@name Breath Mode
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Indicates the breath mode a channel is set to
|
||||
*/
|
||||
enum fluid_channel_breath_flags
|
||||
{
|
||||
FLUID_CHANNEL_BREATH_POLY = 0x10, /**< when channel is poly, this flag indicates that the default velocity to initial attenuation modulator is replaced by a breath to initial attenuation modulator */
|
||||
FLUID_CHANNEL_BREATH_MONO = 0x20, /**< when channel is mono, this flag indicates that the default velocity to initial attenuation modulator is replaced by a breath modulator */
|
||||
FLUID_CHANNEL_BREATH_SYNC = 0x40, /**< when channel is mono, this flag indicates that the breath controller(MSB)triggers noteon/noteoff on the running note */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API int fluid_synth_set_breath_mode(fluid_synth_t *synth,
|
||||
int chan, int breathmode);
|
||||
FLUIDSYNTH_API int fluid_synth_get_breath_mode(fluid_synth_t *synth,
|
||||
int chan, int *breathmode);
|
||||
/** @} Breath Mode */
|
||||
/* @} MIDI Channel Setup */
|
||||
|
||||
|
||||
/** @ingroup settings */
|
||||
FLUIDSYNTH_API fluid_settings_t *fluid_synth_get_settings(fluid_synth_t *synth);
|
||||
|
||||
/** @ingroup soundfont_loader */
|
||||
FLUIDSYNTH_API void fluid_synth_add_sfloader(fluid_synth_t *synth, fluid_sfloader_t *loader);
|
||||
|
||||
/** @ingroup soundfont_loader */
|
||||
FLUIDSYNTH_API fluid_preset_t *fluid_synth_get_channel_preset(fluid_synth_t *synth, int chan);
|
||||
|
||||
/** @ingroup midi_input */
|
||||
FLUIDSYNTH_API int fluid_synth_handle_midi_event(void *data, fluid_midi_event_t *event);
|
||||
|
||||
/** @ingroup soundfonts */
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_pin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num);
|
||||
|
||||
/** @ingroup soundfonts */
|
||||
FLUIDSYNTH_API
|
||||
int fluid_synth_unpin_preset(fluid_synth_t *synth, int sfont_id, int bank_num, int preset_num);
|
||||
|
||||
/** @ingroup ladspa */
|
||||
FLUIDSYNTH_API fluid_ladspa_fx_t *fluid_synth_get_ladspa_fx(fluid_synth_t *synth);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_SYNTH_H */
|
85
thirdparty/fluidsynth/include/fluidsynth/types.h
vendored
Normal file
85
thirdparty/fluidsynth/include/fluidsynth/types.h
vendored
Normal file
|
@ -0,0 +1,85 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_TYPES_H
|
||||
#define _FLUIDSYNTH_TYPES_H
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup Types Types
|
||||
* @brief Type declarations
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
typedef struct _fluid_hashtable_t fluid_settings_t; /**< Configuration settings instance */
|
||||
typedef struct _fluid_synth_t fluid_synth_t; /**< Synthesizer instance */
|
||||
typedef struct _fluid_voice_t fluid_voice_t; /**< Synthesis voice instance */
|
||||
typedef struct _fluid_sfloader_t fluid_sfloader_t; /**< SoundFont loader plugin */
|
||||
typedef struct _fluid_sfont_t fluid_sfont_t; /**< SoundFont */
|
||||
typedef struct _fluid_preset_t fluid_preset_t; /**< SoundFont preset */
|
||||
typedef struct _fluid_sample_t fluid_sample_t; /**< SoundFont sample */
|
||||
typedef struct _fluid_mod_t fluid_mod_t; /**< SoundFont modulator */
|
||||
typedef struct _fluid_audio_driver_t fluid_audio_driver_t; /**< Audio driver instance */
|
||||
typedef struct _fluid_file_renderer_t fluid_file_renderer_t; /**< Audio file renderer instance */
|
||||
typedef struct _fluid_player_t fluid_player_t; /**< MIDI player instance */
|
||||
typedef struct _fluid_midi_event_t fluid_midi_event_t; /**< MIDI event */
|
||||
typedef struct _fluid_midi_driver_t fluid_midi_driver_t; /**< MIDI driver instance */
|
||||
typedef struct _fluid_midi_router_t fluid_midi_router_t; /**< MIDI router instance */
|
||||
typedef struct _fluid_midi_router_rule_t fluid_midi_router_rule_t; /**< MIDI router rule */
|
||||
typedef struct _fluid_hashtable_t fluid_cmd_hash_t; /**< Command handler hash table */
|
||||
typedef struct _fluid_shell_t fluid_shell_t; /**< Command shell */
|
||||
typedef struct _fluid_server_t fluid_server_t; /**< TCP/IP shell server instance */
|
||||
typedef struct _fluid_event_t fluid_event_t; /**< Sequencer event */
|
||||
typedef struct _fluid_sequencer_t fluid_sequencer_t; /**< Sequencer instance */
|
||||
typedef struct _fluid_ramsfont_t fluid_ramsfont_t; /**< RAM SoundFont */
|
||||
typedef struct _fluid_rampreset_t fluid_rampreset_t; /**< RAM SoundFont preset */
|
||||
typedef struct _fluid_cmd_handler_t fluid_cmd_handler_t; /**< Shell Command Handler */
|
||||
typedef struct _fluid_ladspa_fx_t fluid_ladspa_fx_t; /**< LADSPA effects instance */
|
||||
typedef struct _fluid_file_callbacks_t fluid_file_callbacks_t; /**< Callback struct to perform custom file loading of soundfonts */
|
||||
|
||||
typedef int fluid_istream_t; /**< Input stream descriptor */
|
||||
typedef int fluid_ostream_t; /**< Output stream descriptor */
|
||||
|
||||
typedef short fluid_seq_id_t; /**< Unique client IDs used by the sequencer and #fluid_event_t, obtained by fluid_sequencer_register_client() and fluid_sequencer_register_fluidsynth() */
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER < 1800)
|
||||
typedef __int64 fluid_long_long_t; // even on 32bit windows
|
||||
#else
|
||||
/**
|
||||
* A typedef for C99's type long long, which is at least 64-bit wide, as guaranteed by the C99.
|
||||
* @p __int64 will be used as replacement for VisualStudio 2010 and older.
|
||||
*/
|
||||
typedef long long fluid_long_long_t;
|
||||
#endif
|
||||
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_TYPES_H */
|
47
thirdparty/fluidsynth/include/fluidsynth/version.h
vendored
Normal file
47
thirdparty/fluidsynth/include/fluidsynth/version.h
vendored
Normal file
|
@ -0,0 +1,47 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_VERSION_H
|
||||
#define _FLUIDSYNTH_VERSION_H
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @addtogroup misc
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
#define FLUIDSYNTH_VERSION "2.2.8" /**< String constant of libfluidsynth version. */
|
||||
#define FLUIDSYNTH_VERSION_MAJOR 2 /**< libfluidsynth major version integer constant. */
|
||||
#define FLUIDSYNTH_VERSION_MINOR 2 /**< libfluidsynth minor version integer constant. */
|
||||
#define FLUIDSYNTH_VERSION_MICRO 8 /**< libfluidsynth micro version integer constant. */
|
||||
|
||||
FLUIDSYNTH_API void fluid_version(int *major, int *minor, int *micro);
|
||||
FLUIDSYNTH_API char* fluid_version_str(void);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUIDSYNTH_VERSION_H */
|
77
thirdparty/fluidsynth/include/fluidsynth/voice.h
vendored
Normal file
77
thirdparty/fluidsynth/include/fluidsynth/voice.h
vendored
Normal file
|
@ -0,0 +1,77 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUIDSYNTH_VOICE_H
|
||||
#define _FLUIDSYNTH_VOICE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @defgroup voices Voice Manipulation
|
||||
* @ingroup soundfonts
|
||||
*
|
||||
* Synthesis voice manipulation functions.
|
||||
*
|
||||
* The interface to the synthesizer's voices.
|
||||
* Examples on using them can be found in the source code of the default SoundFont
|
||||
* loader (fluid_defsfont.c).
|
||||
*
|
||||
* Most of these functions should only be called from within synthesis context,
|
||||
* such as the SoundFont loader's noteon method.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* Enum used with fluid_voice_add_mod() to specify how to handle duplicate modulators.
|
||||
*/
|
||||
enum fluid_voice_add_mod
|
||||
{
|
||||
FLUID_VOICE_OVERWRITE, /**< Overwrite any existing matching modulator */
|
||||
FLUID_VOICE_ADD, /**< Add (sum) modulator amounts */
|
||||
FLUID_VOICE_DEFAULT /**< For default modulators only, no need to check for duplicates */
|
||||
};
|
||||
|
||||
FLUIDSYNTH_API void fluid_voice_add_mod(fluid_voice_t *voice, fluid_mod_t *mod, int mode);
|
||||
FLUIDSYNTH_API float fluid_voice_gen_get(fluid_voice_t *voice, int gen);
|
||||
FLUIDSYNTH_API void fluid_voice_gen_set(fluid_voice_t *voice, int gen, float val);
|
||||
FLUIDSYNTH_API void fluid_voice_gen_incr(fluid_voice_t *voice, int gen, float val);
|
||||
|
||||
FLUIDSYNTH_API unsigned int fluid_voice_get_id(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_get_channel(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_get_key(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_get_actual_key(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_get_velocity(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_get_actual_velocity(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_is_playing(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_is_on(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_is_sustained(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_is_sostenuto(const fluid_voice_t *voice);
|
||||
FLUIDSYNTH_API int fluid_voice_optimize_sample(fluid_sample_t *s);
|
||||
FLUIDSYNTH_API void fluid_voice_update_param(fluid_voice_t *voice, int gen);
|
||||
/* @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _FLUIDSYNTH_VOICE_H */
|
||||
|
162
thirdparty/fluidsynth/src/CMakeLists.txt
vendored
Normal file
162
thirdparty/fluidsynth/src/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,162 @@
|
|||
# FluidSynth - A Software Synthesizer
|
||||
#
|
||||
# Copyright (C) 2003-2010 Peter Hanappe and others.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU Lesser General Public License
|
||||
# as published by the Free Software Foundation; either version 2.1 of
|
||||
# the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this library; if not, write to the Free
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
|
||||
# 02111-1307, USA
|
||||
|
||||
# CMake based build system. Pedro Lopez-Cabanillas <plcl@users.sf.net>
|
||||
|
||||
# ************ library ************
|
||||
|
||||
if ( LIBINSTPATCH_SUPPORT )
|
||||
set ( fluid_libinstpatch_SOURCES sfloader/fluid_instpatch.c sfloader/fluid_instpatch.h )
|
||||
endif ( LIBINSTPATCH_SUPPORT )
|
||||
|
||||
|
||||
set ( fluidsynth_SOURCES
|
||||
config.h
|
||||
utils/fluid_conv.c
|
||||
utils/fluid_conv.h
|
||||
utils/fluid_hash.c
|
||||
utils/fluid_hash.h
|
||||
utils/fluid_list.c
|
||||
utils/fluid_list.h
|
||||
utils/fluid_ringbuffer.c
|
||||
utils/fluid_ringbuffer.h
|
||||
utils/fluid_settings.c
|
||||
utils/fluid_settings.h
|
||||
utils/fluidsynth_priv.h
|
||||
utils/fluid_sys.c
|
||||
utils/fluid_sys.h
|
||||
sfloader/fluid_defsfont.c
|
||||
sfloader/fluid_defsfont.h
|
||||
sfloader/fluid_sfont.h
|
||||
sfloader/fluid_sfont.c
|
||||
sfloader/fluid_sffile.c
|
||||
sfloader/fluid_sffile.h
|
||||
sfloader/fluid_samplecache.c
|
||||
sfloader/fluid_samplecache.h
|
||||
rvoice/fluid_adsr_env.c
|
||||
rvoice/fluid_adsr_env.h
|
||||
rvoice/fluid_chorus.c
|
||||
rvoice/fluid_chorus.h
|
||||
rvoice/fluid_iir_filter.c
|
||||
rvoice/fluid_iir_filter.h
|
||||
rvoice/fluid_lfo.c
|
||||
rvoice/fluid_lfo.h
|
||||
rvoice/fluid_rvoice.h
|
||||
rvoice/fluid_rvoice.c
|
||||
rvoice/fluid_rvoice_dsp.c
|
||||
rvoice/fluid_rvoice_event.h
|
||||
rvoice/fluid_rvoice_event.c
|
||||
rvoice/fluid_rvoice_mixer.h
|
||||
rvoice/fluid_rvoice_mixer.c
|
||||
rvoice/fluid_phase.h
|
||||
rvoice/fluid_rev.c
|
||||
rvoice/fluid_rev.h
|
||||
synth/fluid_chan.c
|
||||
synth/fluid_chan.h
|
||||
synth/fluid_event.c
|
||||
synth/fluid_event.h
|
||||
synth/fluid_gen.c
|
||||
synth/fluid_gen.h
|
||||
synth/fluid_mod.c
|
||||
synth/fluid_mod.h
|
||||
synth/fluid_synth.c
|
||||
synth/fluid_synth.h
|
||||
synth/fluid_synth_monopoly.c
|
||||
synth/fluid_tuning.c
|
||||
synth/fluid_tuning.h
|
||||
synth/fluid_voice.c
|
||||
synth/fluid_voice.h
|
||||
midi/fluid_midi.c
|
||||
midi/fluid_midi.h
|
||||
midi/fluid_midi_router.c
|
||||
midi/fluid_midi_router.h
|
||||
midi/fluid_seqbind.c
|
||||
midi/fluid_seqbind_notes.cpp
|
||||
midi/fluid_seq.c
|
||||
midi/fluid_seq_queue.cpp
|
||||
drivers/fluid_adriver.c
|
||||
drivers/fluid_adriver.h
|
||||
drivers/fluid_mdriver.c
|
||||
drivers/fluid_mdriver.h
|
||||
bindings/fluid_filerenderer.c
|
||||
bindings/fluid_ladspa.c
|
||||
bindings/fluid_ladspa.h
|
||||
)
|
||||
|
||||
if ( WIN32 )
|
||||
set( fluidsynth_SOURCES
|
||||
${fluidsynth_SOURCES}
|
||||
utils/win32_glibstubs.c
|
||||
utils/win32_glibstubs.h
|
||||
)
|
||||
endif ( WIN32 )
|
||||
|
||||
set ( public_HEADERS
|
||||
../include/fluidsynth/audio.h
|
||||
../include/fluidsynth/event.h
|
||||
../include/fluidsynth/gen.h
|
||||
../include/fluidsynth/ladspa.h
|
||||
../include/fluidsynth/log.h
|
||||
../include/fluidsynth/midi.h
|
||||
../include/fluidsynth/misc.h
|
||||
../include/fluidsynth/mod.h
|
||||
../include/fluidsynth/seq.h
|
||||
../include/fluidsynth/seqbind.h
|
||||
../include/fluidsynth/settings.h
|
||||
../include/fluidsynth/sfont.h
|
||||
../include/fluidsynth/shell.h
|
||||
../include/fluidsynth/synth.h
|
||||
../include/fluidsynth/types.h
|
||||
../include/fluidsynth/voice.h
|
||||
../include/fluidsynth/version.h
|
||||
)
|
||||
|
||||
set ( public_main_HEADER
|
||||
../include/fluidsynth.h
|
||||
)
|
||||
|
||||
add_library ( fluidsynth OBJECT
|
||||
${config_SOURCES}
|
||||
${fluidsynth_SOURCES}
|
||||
${public_HEADERS}
|
||||
${public_main_HEADER}
|
||||
)
|
||||
|
||||
target_include_directories ( fluidsynth PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/drivers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/synth
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/rvoice
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/midi
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utils
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/sfloader
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/bindings
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../include
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../..
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../../source/decoder
|
||||
)
|
||||
|
||||
|
||||
if (NOT WIN32)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_search_module(GLIB REQUIRED glib-2.0)
|
||||
target_include_directories ( fluidsynth PUBLIC ${GLIB_INCLUDE_DIRS} )
|
||||
target_link_libraries ( fluidsynth PUBLIC ${pkgcfg_lib_GLIB_glib-2.0} )
|
||||
|
||||
endif()
|
590
thirdparty/fluidsynth/src/bindings/fluid_filerenderer.c
vendored
Normal file
590
thirdparty/fluidsynth/src/bindings/fluid_filerenderer.c
vendored
Normal file
|
@ -0,0 +1,590 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
/*
|
||||
* Low-level routines for file output.
|
||||
*/
|
||||
|
||||
#include "fluid_sys.h"
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
#include <sndfile.h>
|
||||
#endif
|
||||
|
||||
struct _fluid_file_renderer_t
|
||||
{
|
||||
fluid_synth_t *synth;
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
SNDFILE *sndfile;
|
||||
float *buf;
|
||||
#else
|
||||
FILE *file;
|
||||
short *buf;
|
||||
#endif
|
||||
|
||||
int period_size;
|
||||
int buf_size;
|
||||
};
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
|
||||
/* Default file type used, if none specified and auto extension search fails */
|
||||
#define FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE SF_FORMAT_WAV
|
||||
|
||||
/* File audio format names.
|
||||
* !! Keep in sync with format_ids[] */
|
||||
static const char *const format_names[] =
|
||||
{
|
||||
"s8",
|
||||
"s16",
|
||||
"s24",
|
||||
"s32",
|
||||
"u8",
|
||||
"float",
|
||||
"double"
|
||||
};
|
||||
|
||||
|
||||
/* File audio format IDs.
|
||||
* !! Keep in sync with format_names[] */
|
||||
static const int format_ids[] =
|
||||
{
|
||||
SF_FORMAT_PCM_S8,
|
||||
SF_FORMAT_PCM_16,
|
||||
SF_FORMAT_PCM_24,
|
||||
SF_FORMAT_PCM_32,
|
||||
SF_FORMAT_PCM_U8,
|
||||
SF_FORMAT_FLOAT,
|
||||
SF_FORMAT_DOUBLE
|
||||
};
|
||||
|
||||
/* File endian byte order names.
|
||||
* !! Keep in sync with endian_ids[] */
|
||||
static const char *const endian_names[] =
|
||||
{
|
||||
"auto",
|
||||
"little",
|
||||
"big",
|
||||
"cpu"
|
||||
};
|
||||
|
||||
/* File endian byte order ids.
|
||||
* !! Keep in sync with endian_names[] */
|
||||
static const int endian_ids[] =
|
||||
{
|
||||
SF_ENDIAN_FILE,
|
||||
SF_ENDIAN_LITTLE,
|
||||
SF_ENDIAN_BIG,
|
||||
SF_ENDIAN_CPU
|
||||
};
|
||||
|
||||
static int fluid_file_renderer_parse_options(char *filetype, char *format,
|
||||
char *endian, char *filename, SF_INFO *info);
|
||||
static int fluid_file_renderer_find_file_type(char *extension, int *type);
|
||||
static int fluid_file_renderer_find_valid_format(SF_INFO *info);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
void
|
||||
fluid_file_renderer_settings(fluid_settings_t *settings)
|
||||
{
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
SF_FORMAT_INFO finfo, cmpinfo;
|
||||
int major_count;
|
||||
int i, i2;
|
||||
unsigned int n;
|
||||
|
||||
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.wav", 0);
|
||||
fluid_settings_register_str(settings, "audio.file.type", "auto", 0);
|
||||
fluid_settings_register_str(settings, "audio.file.format", "s16", 0);
|
||||
fluid_settings_register_str(settings, "audio.file.endian", "auto", 0);
|
||||
|
||||
fluid_settings_add_option(settings, "audio.file.type", "auto");
|
||||
|
||||
sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof(int));
|
||||
|
||||
for(i = 0; i < major_count; i++)
|
||||
{
|
||||
finfo.format = i;
|
||||
sf_command(NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof(finfo));
|
||||
|
||||
/* Check for duplicates */
|
||||
for(i2 = 0; i2 < i; i2++)
|
||||
{
|
||||
cmpinfo.format = i2;
|
||||
sf_command(NULL, SFC_GET_FORMAT_MAJOR, &cmpinfo, sizeof(cmpinfo));
|
||||
|
||||
if(FLUID_STRCMP(cmpinfo.extension, finfo.extension) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i2 == i)
|
||||
{
|
||||
fluid_settings_add_option(settings, "audio.file.type", finfo.extension);
|
||||
}
|
||||
}
|
||||
|
||||
for(n = 0; n < FLUID_N_ELEMENTS(format_names); n++)
|
||||
{
|
||||
fluid_settings_add_option(settings, "audio.file.format", format_names[n]);
|
||||
}
|
||||
|
||||
for(n = 0; n < FLUID_N_ELEMENTS(endian_names); n++)
|
||||
{
|
||||
fluid_settings_add_option(settings, "audio.file.endian", endian_names[n]);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
fluid_settings_register_str(settings, "audio.file.name", "fluidsynth.raw", 0);
|
||||
fluid_settings_register_str(settings, "audio.file.type", "raw", 0);
|
||||
fluid_settings_add_option(settings, "audio.file.type", "raw");
|
||||
fluid_settings_register_str(settings, "audio.file.format", "s16", 0);
|
||||
fluid_settings_add_option(settings, "audio.file.format", "s16");
|
||||
fluid_settings_register_str(settings, "audio.file.endian", "cpu", 0);
|
||||
fluid_settings_add_option(settings, "audio.file.endian", "cpu");
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new file renderer and open the file.
|
||||
*
|
||||
* @param synth The synth that creates audio data.
|
||||
* @return the new object, or NULL on failure
|
||||
*
|
||||
* @note Available file types and formats depends on if libfluidsynth was
|
||||
* built with libsndfile support or not. If not then only RAW 16 bit output is
|
||||
* supported.
|
||||
*
|
||||
* Uses the following settings from the synth object:
|
||||
* - \ref settings_audio_file_name : Output filename
|
||||
* - \ref settings_audio_file_type : File type, "auto" tries to determine type from filename
|
||||
* extension with fallback to "wav".
|
||||
* - \ref settings_audio_file_format : Audio format
|
||||
* - \ref settings_audio_file_endian : Endian byte order, "auto" for file type's default byte order
|
||||
* - \ref settings_audio_period-size : Size of audio blocks to process
|
||||
* - \ref settings_synth_sample-rate : Sample rate to use
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
fluid_file_renderer_t *
|
||||
new_fluid_file_renderer(fluid_synth_t *synth)
|
||||
{
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
char *type, *format, *endian;
|
||||
SF_INFO info;
|
||||
double samplerate;
|
||||
int retval;
|
||||
#endif
|
||||
int audio_channels;
|
||||
char *filename = NULL;
|
||||
fluid_file_renderer_t *dev;
|
||||
|
||||
fluid_return_val_if_fail(synth != NULL, NULL);
|
||||
fluid_return_val_if_fail(synth->settings != NULL, NULL);
|
||||
|
||||
dev = FLUID_NEW(fluid_file_renderer_t);
|
||||
|
||||
if(dev == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(dev, 0, sizeof(fluid_file_renderer_t));
|
||||
|
||||
dev->synth = synth;
|
||||
fluid_settings_getint(synth->settings, "audio.period-size", &dev->period_size);
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
dev->buf_size = 2 * dev->period_size * sizeof(float);
|
||||
dev->buf = FLUID_ARRAY(float, 2 * dev->period_size);
|
||||
#else
|
||||
dev->buf_size = 2 * dev->period_size * sizeof(short);
|
||||
dev->buf = FLUID_ARRAY(short, 2 * dev->period_size);
|
||||
#endif
|
||||
|
||||
if(dev->buf == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
fluid_settings_dupstr(synth->settings, "audio.file.name", &filename);
|
||||
fluid_settings_getint(synth->settings, "synth.audio-channels", &audio_channels);
|
||||
|
||||
if(filename == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "No file name specified");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
memset(&info, 0, sizeof(info));
|
||||
|
||||
info.format = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE | SF_FORMAT_PCM_16;
|
||||
|
||||
fluid_settings_dupstr(synth->settings, "audio.file.type", &type);
|
||||
fluid_settings_dupstr(synth->settings, "audio.file.format", &format);
|
||||
fluid_settings_dupstr(synth->settings, "audio.file.endian", &endian);
|
||||
|
||||
retval = fluid_file_renderer_parse_options(type, format, endian, filename, &info);
|
||||
|
||||
if(type)
|
||||
{
|
||||
FLUID_FREE(type);
|
||||
}
|
||||
|
||||
if(format)
|
||||
{
|
||||
FLUID_FREE(format);
|
||||
}
|
||||
|
||||
if(endian)
|
||||
{
|
||||
FLUID_FREE(endian);
|
||||
}
|
||||
|
||||
if(!retval)
|
||||
{
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
fluid_settings_getnum(synth->settings, "synth.sample-rate", &samplerate);
|
||||
info.samplerate = samplerate + 0.5;
|
||||
info.channels = 2;
|
||||
|
||||
/* Search for valid format for given file type, if invalid and no format was specified.
|
||||
* To handle Ogg/Vorbis and possibly future file types with new formats.
|
||||
* Checking if format is SF_FORMAT_PCM_16 isn't a fool proof way to check if
|
||||
* format was specified or not (if user specifies "s16" itself), but should suffice. */
|
||||
if(!sf_format_check(&info)
|
||||
&& ((info.format & SF_FORMAT_SUBMASK) != SF_FORMAT_PCM_16
|
||||
|| !fluid_file_renderer_find_valid_format(&info)))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file format settings");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
dev->sndfile = sf_open(filename, SFM_WRITE, &info);
|
||||
|
||||
if(!dev->sndfile)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to open audio file '%s' for writing", filename);
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
/* Turn on clipping and normalization of floats (-1.0 - 1.0) */
|
||||
sf_command(dev->sndfile, SFC_SET_CLIPPING, NULL, SF_TRUE);
|
||||
sf_command(dev->sndfile, SFC_SET_NORM_FLOAT, NULL, SF_TRUE);
|
||||
|
||||
#else
|
||||
dev->file = FLUID_FOPEN(filename, "wb");
|
||||
|
||||
if(dev->file == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to open the file '%s'", filename);
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
if(audio_channels != 1)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "The file-renderer currently only supports a single stereo channel. You have provided %d stereo channels. Audio may sound strange or incomplete.", audio_channels);
|
||||
}
|
||||
|
||||
FLUID_FREE(filename);
|
||||
return dev;
|
||||
|
||||
error_recovery:
|
||||
|
||||
FLUID_FREE(filename);
|
||||
delete_fluid_file_renderer(dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set vbr encoding quality (only available with libsndfile support)
|
||||
* @param dev File renderer object.
|
||||
* @param q The encoding quality, see libsndfile documentation of \c SFC_SET_VBR_ENCODING_QUALITY
|
||||
* @return #FLUID_OK if the quality has been successfully set, #FLUID_FAILED otherwise
|
||||
* @since 1.1.7
|
||||
*/
|
||||
int
|
||||
fluid_file_set_encoding_quality(fluid_file_renderer_t *dev, double q)
|
||||
{
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
|
||||
if(sf_command(dev->sndfile, SFC_SET_VBR_ENCODING_QUALITY, &q, sizeof(double)) == SF_TRUE)
|
||||
{
|
||||
return FLUID_OK;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close file and destroy a file renderer object.
|
||||
* @param dev File renderer object.
|
||||
* @since 1.1.0
|
||||
*/
|
||||
void delete_fluid_file_renderer(fluid_file_renderer_t *dev)
|
||||
{
|
||||
fluid_return_if_fail(dev != NULL);
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
|
||||
if(dev->sndfile != NULL)
|
||||
{
|
||||
int retval = sf_close(dev->sndfile);
|
||||
|
||||
if(retval != 0)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "Error closing audio file: %s", sf_error_number(retval));
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
if(dev->file != NULL)
|
||||
{
|
||||
fclose(dev->file);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FLUID_FREE(dev->buf);
|
||||
FLUID_FREE(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write period_size samples to file.
|
||||
* @param dev File renderer instance
|
||||
* @return #FLUID_OK or #FLUID_FAILED if an error occurred
|
||||
* @since 1.1.0
|
||||
*/
|
||||
int
|
||||
fluid_file_renderer_process_block(fluid_file_renderer_t *dev)
|
||||
{
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
int n;
|
||||
|
||||
fluid_synth_write_float(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
|
||||
|
||||
n = sf_writef_float(dev->sndfile, dev->buf, dev->period_size);
|
||||
|
||||
if(n != dev->period_size)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Audio file write error: %s",
|
||||
sf_strerror(dev->sndfile));
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
|
||||
#else /* No libsndfile support */
|
||||
|
||||
size_t res, nmemb = dev->buf_size;
|
||||
|
||||
fluid_synth_write_s16(dev->synth, dev->period_size, dev->buf, 0, 2, dev->buf, 1, 2);
|
||||
|
||||
res = fwrite(dev->buf, 1, nmemb, dev->file);
|
||||
|
||||
if(res < nmemb)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Audio output file write error: %s",
|
||||
strerror(errno));
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#if LIBSNDFILE_SUPPORT
|
||||
|
||||
/**
|
||||
* Parse a colon separated format string and configure an SF_INFO structure accordingly.
|
||||
* @param filetype File type string (NULL or "auto" to attempt to identify format
|
||||
* by filename extension, with fallback to "wav")
|
||||
* @param format File audio format string or NULL to use "s16"
|
||||
* @param endian File endian string or NULL to use "auto" which uses the file type's
|
||||
* default endian byte order.
|
||||
* @param filename File name (used by "auto" type to determine type, based on extension)
|
||||
* @param info Audio file info structure to configure
|
||||
* @return TRUE on success, FALSE otherwise
|
||||
*/
|
||||
static int
|
||||
fluid_file_renderer_parse_options(char *filetype, char *format, char *endian,
|
||||
char *filename, SF_INFO *info)
|
||||
{
|
||||
int type = -1; /* -1 indicates "auto" type */
|
||||
char *s;
|
||||
unsigned int i;
|
||||
|
||||
/* If "auto" type, then use extension to search for a match */
|
||||
if(!filetype || FLUID_STRCMP(filetype, "auto") == 0)
|
||||
{
|
||||
type = FLUID_FILE_RENDERER_DEFAULT_FILE_TYPE;
|
||||
s = FLUID_STRRCHR(filename, '.');
|
||||
|
||||
if(s && s[1] != '\0')
|
||||
{
|
||||
if(!fluid_file_renderer_find_file_type(s + 1, &type))
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "Failed to determine audio file type from filename, defaulting to WAV");
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(!fluid_file_renderer_find_file_type(filetype, &type))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid or unsupported audio file type '%s'", filetype);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
info->format = (info->format & ~SF_FORMAT_TYPEMASK) | type;
|
||||
|
||||
/* Look for subtype */
|
||||
if(format)
|
||||
{
|
||||
for(i = 0; i < FLUID_N_ELEMENTS(format_names); i++)
|
||||
{
|
||||
if(FLUID_STRCMP(format, format_names[i]) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i >= FLUID_N_ELEMENTS(format_names))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid or unsupported file audio format '%s'", format);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_ids[i];
|
||||
}
|
||||
|
||||
#if LIBSNDFILE_HASVORBIS
|
||||
|
||||
/* Force subformat to vorbis as nothing else would make sense currently */
|
||||
if((info->format & SF_FORMAT_TYPEMASK) == SF_FORMAT_OGG)
|
||||
{
|
||||
info->format = (info->format & ~SF_FORMAT_SUBMASK) | SF_FORMAT_VORBIS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Look for endian */
|
||||
if(endian)
|
||||
{
|
||||
for(i = 0; i < FLUID_N_ELEMENTS(endian_names); i++)
|
||||
{
|
||||
if(FLUID_STRCMP(endian, endian_names[i]) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i >= FLUID_N_ELEMENTS(endian_names))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Invalid or unsupported endian byte order '%s'", endian);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
info->format = (info->format & ~SF_FORMAT_ENDMASK) | endian_ids[i];
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for a supported libsndfile file type by extension.
|
||||
* @param extension The extension string
|
||||
* @param type Location to store the type (unmodified if not found)
|
||||
* @return TRUE if found, FALSE otherwise
|
||||
*/
|
||||
static int
|
||||
fluid_file_renderer_find_file_type(char *extension, int *type)
|
||||
{
|
||||
SF_FORMAT_INFO finfo;
|
||||
int major_count;
|
||||
int i;
|
||||
|
||||
sf_command(NULL, SFC_GET_FORMAT_MAJOR_COUNT, &major_count, sizeof(int));
|
||||
|
||||
for(i = 0; i < major_count; i++)
|
||||
{
|
||||
finfo.format = i;
|
||||
sf_command(NULL, SFC_GET_FORMAT_MAJOR, &finfo, sizeof(finfo));
|
||||
|
||||
if(FLUID_STRCMP(extension, finfo.extension) == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i < major_count)
|
||||
{
|
||||
*type = finfo.format;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Search for a valid audio format for a given file type */
|
||||
static int
|
||||
fluid_file_renderer_find_valid_format(SF_INFO *info)
|
||||
{
|
||||
SF_FORMAT_INFO format_info;
|
||||
int count, i;
|
||||
|
||||
sf_command(NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof(int));
|
||||
|
||||
for(i = 0; i < count; i++)
|
||||
{
|
||||
format_info.format = i;
|
||||
|
||||
sf_command(NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof(format_info));
|
||||
|
||||
info->format = (info->format & ~SF_FORMAT_SUBMASK) | format_info.format;
|
||||
|
||||
if(sf_format_check(info))
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#endif
|
1882
thirdparty/fluidsynth/src/bindings/fluid_ladspa.c
vendored
Normal file
1882
thirdparty/fluidsynth/src/bindings/fluid_ladspa.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
36
thirdparty/fluidsynth/src/bindings/fluid_ladspa.h
vendored
Normal file
36
thirdparty/fluidsynth/src/bindings/fluid_ladspa.h
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUID_LADSPA_H
|
||||
#define _FLUID_LADSPA_H
|
||||
|
||||
#include "fluid_sys.h"
|
||||
|
||||
fluid_ladspa_fx_t *new_fluid_ladspa_fx(fluid_real_t sample_rate, int buffer_size);
|
||||
void delete_fluid_ladspa_fx(fluid_ladspa_fx_t *fx);
|
||||
|
||||
int fluid_ladspa_set_sample_rate(fluid_ladspa_fx_t *fx, fluid_real_t sample_rate);
|
||||
|
||||
void fluid_ladspa_run(fluid_ladspa_fx_t *fx, int block_count, int block_size);
|
||||
|
||||
int fluid_ladspa_add_host_ports(fluid_ladspa_fx_t *fx, const char *prefix,
|
||||
int num_buffers, fluid_real_t buffers[], int buf_stride);
|
||||
|
||||
#endif /* _FLUID_LADSPA_H */
|
280
thirdparty/fluidsynth/src/config.h
vendored
Normal file
280
thirdparty/fluidsynth/src/config.h
vendored
Normal file
|
@ -0,0 +1,280 @@
|
|||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
/* Define to enable ALSA driver */
|
||||
/* #undef ALSA_SUPPORT */
|
||||
|
||||
/* Define to activate sound output to files */
|
||||
/* #undef AUFILE_SUPPORT */
|
||||
|
||||
/* whether or not we are supporting CoreAudio */
|
||||
/* #undef COREAUDIO_SUPPORT */
|
||||
|
||||
/* whether or not we are supporting CoreMIDI */
|
||||
/* #undef COREMIDI_SUPPORT */
|
||||
|
||||
/* whether or not we are supporting DART */
|
||||
/* #undef DART_SUPPORT */
|
||||
|
||||
/* Define if building for Mac OS X Darwin */
|
||||
/* #undef DARWIN */
|
||||
|
||||
/* Define if D-Bus support is enabled */
|
||||
/* #undef DBUS_SUPPORT */
|
||||
|
||||
/* Soundfont to load automatically in some use cases */
|
||||
#define DEFAULT_SOUNDFONT "C:\\ProgramData\\soundfonts\\default.sf2"
|
||||
|
||||
/* Define to enable FPE checks */
|
||||
/* #undef FPE_CHECK */
|
||||
|
||||
/* Define to 1 if you have the <arpa/inet.h> header file. */
|
||||
/* #undef HAVE_ARPA_INET_H */
|
||||
|
||||
/* Define to 1 if you have the <errno.h> header file. */
|
||||
#define HAVE_ERRNO_H 1
|
||||
|
||||
/* Define to 1 if you have the <fcntl.h> header file. */
|
||||
#define HAVE_FCNTL_H 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
/* #undef HAVE_INTTYPES_H */
|
||||
|
||||
/* Define to 1 if you have the <io.h> header file. */
|
||||
#ifdef _WIN32
|
||||
#define HAVE_IO_H 1
|
||||
#endif
|
||||
|
||||
/* whether or not we are supporting lash */
|
||||
/* #undef HAVE_LASH */
|
||||
|
||||
/* Define if systemd support is enabled */
|
||||
/* #undef SYSTEMD_SUPPORT */
|
||||
|
||||
/* Define to 1 if you have the <limits.h> header file. */
|
||||
#define HAVE_LIMITS_H 1
|
||||
|
||||
/* Define to 1 if you have the <linux/soundcard.h> header file. */
|
||||
/* #undef HAVE_LINUX_SOUNDCARD_H */
|
||||
|
||||
/* Define to 1 if you have the <machine/soundcard.h> header file. */
|
||||
/* #undef HAVE_MACHINE_SOUNDCARD_H */
|
||||
|
||||
/* Define to 1 if you have the <math.h> header file. */
|
||||
#define HAVE_MATH_H 1
|
||||
|
||||
/* Define to 1 if you have the <netinet/in.h> header file. */
|
||||
/* #undef HAVE_NETINET_IN_H */
|
||||
|
||||
/* Define to 1 if you have the <netinet/tcp.h> header file. */
|
||||
/* #undef HAVE_NETINET_TCP_H */
|
||||
|
||||
/* Define if compiling the mixer with multi-thread support */
|
||||
#define ENABLE_MIXER_THREADS 1
|
||||
|
||||
/* Define if compiling with openMP to enable parallel audio rendering */
|
||||
/* #undef HAVE_OPENMP */
|
||||
|
||||
/* Define to 1 if you have the <pthread.h> header file. */
|
||||
/* #undef HAVE_PTHREAD_H */
|
||||
|
||||
/* Define to 1 if you have the <signal.h> header file. */
|
||||
#define HAVE_SIGNAL_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdarg.h> header file. */
|
||||
#define HAVE_STDARG_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdio.h> header file. */
|
||||
#define HAVE_STDIO_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
/* #undef HAVE_STRINGS_H */
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/mman.h> header file. */
|
||||
/* #undef HAVE_SYS_MMAN_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/socket.h> header file. */
|
||||
/* #undef HAVE_SYS_SOCKET_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/soundcard.h> header file. */
|
||||
/* #undef HAVE_SYS_SOUNDCARD_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
/* #undef HAVE_SYS_TIME_H */
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#ifndef _WIN32
|
||||
#define HAVE_UNISTD_H 1
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the <windows.h> header file. */
|
||||
#define HAVE_WINDOWS_H 1
|
||||
|
||||
/* Define to 1 if you have the <getopt.h> header file. */
|
||||
/* #undef HAVE_GETOPT_H */
|
||||
|
||||
/* Define to 1 if you have the inet_ntop() function. */
|
||||
/* #undef HAVE_INETNTOP */
|
||||
|
||||
/* Define to enable JACK driver */
|
||||
/* #undef JACK_SUPPORT */
|
||||
|
||||
/* Define to enable PipeWire driver */
|
||||
/* #undef PIPEWIRE_SUPPORT */
|
||||
|
||||
/* Include the LADSPA Fx unit */
|
||||
/* #undef LADSPA */
|
||||
|
||||
/* Define to enable IPV6 support */
|
||||
/* #undef IPV6_SUPPORT */
|
||||
|
||||
/* Define to enable network support */
|
||||
/* #undef NETWORK_SUPPORT */
|
||||
|
||||
/* Defined when fluidsynth is build in an automated environment, where no MSVC++ Runtime Debug Assertion dialogs should pop up */
|
||||
/* #undef NO_GUI */
|
||||
|
||||
/* libinstpatch for DLS and GIG */
|
||||
/* #undef LIBINSTPATCH_SUPPORT */
|
||||
|
||||
/* libsndfile has ogg vorbis support */
|
||||
/* #undef LIBSNDFILE_HASVORBIS */
|
||||
|
||||
/* Define to enable libsndfile support */
|
||||
/* #undef LIBSNDFILE_SUPPORT */
|
||||
|
||||
/* Define to enable MidiShare driver */
|
||||
/* #undef MIDISHARE_SUPPORT */
|
||||
|
||||
/* Define if using the MinGW32 environment */
|
||||
/* #undef MINGW32 */
|
||||
|
||||
/* Define to enable OSS driver */
|
||||
/* #undef OSS_SUPPORT */
|
||||
|
||||
/* Define to enable OPENSLES driver */
|
||||
/* #undef OPENSLES_SUPPORT */
|
||||
|
||||
/* Define to enable Oboe driver */
|
||||
/* #undef OBOE_SUPPORT */
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "fluidsynth"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
/* #undef PACKAGE_BUGREPORT */
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
/* #undef PACKAGE_NAME */
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
/* #undef PACKAGE_STRING */
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
/* #undef PACKAGE_TARNAME */
|
||||
|
||||
/* Define to the version of this package. */
|
||||
/* #undef PACKAGE_VERSION */
|
||||
|
||||
/* Define to enable PortAudio driver */
|
||||
/* #undef PORTAUDIO_SUPPORT */
|
||||
|
||||
/* Define to enable PulseAudio driver */
|
||||
/* #undef PULSE_SUPPORT */
|
||||
|
||||
/* Define to enable DirectSound driver */
|
||||
/* #undef DSOUND_SUPPORT */
|
||||
|
||||
/* Define to enable Windows WASAPI driver */
|
||||
/* #undef WASAPI_SUPPORT */
|
||||
|
||||
/* Define to enable Windows WaveOut driver */
|
||||
/* #undef WAVEOUT_SUPPORT */
|
||||
|
||||
/* Define to enable Windows MIDI driver */
|
||||
/* #undef WINMIDI_SUPPORT */
|
||||
|
||||
/* Define to enable SDL2 audio driver */
|
||||
/* #undef SDL2_SUPPORT */
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
/* #undef STDC_HEADERS */
|
||||
|
||||
/* Soundfont to load for unit testing */
|
||||
#define TEST_SOUNDFONT "C:/Programming/Projects/fluidsynth/sf2/VintageDreamsWaves-v2.sf2"
|
||||
|
||||
/* Soundfont to load for UTF-8 unit testing */
|
||||
#define TEST_SOUNDFONT_UTF8_1 "C:/Programming/Projects/fluidsynth/sf2/\xE2\x96\xA0VintageDreamsWaves-v2\xE2\x96\xA0.sf2"
|
||||
#define TEST_SOUNDFONT_UTF8_2 "C:/Programming/Projects/fluidsynth/sf2/Vìntà gèDrèà msWà vès-v2.sf2"
|
||||
#define TEST_MIDI_UTF8 "C:/Programming/Projects/fluidsynth/test/èmpty.mid"
|
||||
|
||||
/* SF3 Soundfont to load for unit testing */
|
||||
#define TEST_SOUNDFONT_SF3 "C:/Programming/Projects/fluidsynth/sf2/VintageDreamsWaves-v2.sf3"
|
||||
|
||||
/* Define to enable SIGFPE assertions */
|
||||
/* #undef TRAP_ON_FPE */
|
||||
|
||||
/* Define to do all DSP in single floating point precision */
|
||||
/* #undef WITH_FLOAT */
|
||||
|
||||
/* Define to profile the DSP code */
|
||||
/* #undef WITH_PROFILING */
|
||||
|
||||
/* Define to use the readline library for line editing */
|
||||
/* #undef WITH_READLINE */
|
||||
|
||||
/* Define if the compiler supports VLA */
|
||||
/* #undef SUPPORTS_VLA */
|
||||
|
||||
/* Define to 1 if your processor stores words with the most significant byte
|
||||
first (like Motorola and SPARC, unlike Intel and VAX). */
|
||||
/* #undef WORDS_BIGENDIAN */
|
||||
|
||||
/* Define to `__inline__' or `__inline' if that's what the C compiler
|
||||
calls it, or to nothing if 'inline' is not supported under any name. */
|
||||
#ifndef __cplusplus
|
||||
/* #undef inline */
|
||||
#endif
|
||||
|
||||
/* Define to 1 if you have the sinf() function. */
|
||||
#define HAVE_SINF 1
|
||||
|
||||
/* Define to 1 if you have the cosf() function. */
|
||||
#define HAVE_COSF 1
|
||||
|
||||
/* Define to 1 if you have the fabsf() function. */
|
||||
#define HAVE_FABSF 1
|
||||
|
||||
/* Define to 1 if you have the powf() function. */
|
||||
#define HAVE_POWF 1
|
||||
|
||||
/* Define to 1 if you have the sqrtf() function. */
|
||||
#define HAVE_SQRTF 1
|
||||
|
||||
/* Define to 1 if you have the logf() function. */
|
||||
#define HAVE_LOGF 1
|
||||
|
||||
/* Define to 1 if you have the socklen_t type. */
|
||||
#define HAVE_SOCKLEN_T 1
|
||||
|
||||
/* Define if using glib stubs instead of real glib. */
|
||||
#ifdef _WIN32
|
||||
#define WITH_GLIB_STUBS
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_H */
|
495
thirdparty/fluidsynth/src/drivers/fluid_adriver.c
vendored
Normal file
495
thirdparty/fluidsynth/src/drivers/fluid_adriver.c
vendored
Normal file
|
@ -0,0 +1,495 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "fluid_adriver.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
/*
|
||||
* fluid_adriver_definition_t
|
||||
*/
|
||||
|
||||
struct _fluid_audriver_definition_t
|
||||
{
|
||||
const char *name;
|
||||
fluid_audio_driver_t *(*new)(fluid_settings_t *settings, fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *(*new2)(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
void (*free)(fluid_audio_driver_t *driver);
|
||||
void (*settings)(fluid_settings_t *settings);
|
||||
};
|
||||
|
||||
/* Available audio drivers, listed in order of preference */
|
||||
static const fluid_audriver_definition_t fluid_audio_drivers[] =
|
||||
{
|
||||
#if ALSA_SUPPORT
|
||||
{
|
||||
"alsa",
|
||||
new_fluid_alsa_audio_driver,
|
||||
new_fluid_alsa_audio_driver2,
|
||||
delete_fluid_alsa_audio_driver,
|
||||
fluid_alsa_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if JACK_SUPPORT
|
||||
{
|
||||
"jack",
|
||||
new_fluid_jack_audio_driver,
|
||||
new_fluid_jack_audio_driver2,
|
||||
delete_fluid_jack_audio_driver,
|
||||
fluid_jack_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if PULSE_SUPPORT
|
||||
{
|
||||
"pulseaudio",
|
||||
new_fluid_pulse_audio_driver,
|
||||
new_fluid_pulse_audio_driver2,
|
||||
delete_fluid_pulse_audio_driver,
|
||||
fluid_pulse_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
{
|
||||
"pipewire",
|
||||
new_fluid_pipewire_audio_driver,
|
||||
new_fluid_pipewire_audio_driver2,
|
||||
delete_fluid_pipewire_audio_driver,
|
||||
fluid_pipewire_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if OSS_SUPPORT
|
||||
{
|
||||
"oss",
|
||||
new_fluid_oss_audio_driver,
|
||||
new_fluid_oss_audio_driver2,
|
||||
delete_fluid_oss_audio_driver,
|
||||
fluid_oss_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if OBOE_SUPPORT
|
||||
{
|
||||
"oboe",
|
||||
new_fluid_oboe_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_oboe_audio_driver,
|
||||
fluid_oboe_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if OPENSLES_SUPPORT
|
||||
{
|
||||
"opensles",
|
||||
new_fluid_opensles_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_opensles_audio_driver,
|
||||
fluid_opensles_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if COREAUDIO_SUPPORT
|
||||
{
|
||||
"coreaudio",
|
||||
new_fluid_core_audio_driver,
|
||||
new_fluid_core_audio_driver2,
|
||||
delete_fluid_core_audio_driver,
|
||||
fluid_core_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if DSOUND_SUPPORT
|
||||
{
|
||||
"dsound",
|
||||
new_fluid_dsound_audio_driver,
|
||||
new_fluid_dsound_audio_driver2,
|
||||
delete_fluid_dsound_audio_driver,
|
||||
fluid_dsound_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if WASAPI_SUPPORT
|
||||
{
|
||||
"wasapi",
|
||||
new_fluid_wasapi_audio_driver,
|
||||
new_fluid_wasapi_audio_driver2,
|
||||
delete_fluid_wasapi_audio_driver,
|
||||
fluid_wasapi_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if WAVEOUT_SUPPORT
|
||||
{
|
||||
"waveout",
|
||||
new_fluid_waveout_audio_driver,
|
||||
new_fluid_waveout_audio_driver2,
|
||||
delete_fluid_waveout_audio_driver,
|
||||
fluid_waveout_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if SNDMAN_SUPPORT
|
||||
{
|
||||
"sndman",
|
||||
new_fluid_sndmgr_audio_driver,
|
||||
new_fluid_sndmgr_audio_driver2,
|
||||
delete_fluid_sndmgr_audio_driver,
|
||||
NULL
|
||||
},
|
||||
#endif
|
||||
|
||||
#if PORTAUDIO_SUPPORT
|
||||
{
|
||||
"portaudio",
|
||||
new_fluid_portaudio_driver,
|
||||
NULL,
|
||||
delete_fluid_portaudio_driver,
|
||||
fluid_portaudio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if DART_SUPPORT
|
||||
{
|
||||
"dart",
|
||||
new_fluid_dart_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_dart_audio_driver,
|
||||
fluid_dart_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if SDL2_SUPPORT
|
||||
{
|
||||
"sdl2",
|
||||
new_fluid_sdl2_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_sdl2_audio_driver,
|
||||
fluid_sdl2_audio_driver_settings
|
||||
},
|
||||
#endif
|
||||
|
||||
#if AUFILE_SUPPORT
|
||||
{
|
||||
"file",
|
||||
new_fluid_file_audio_driver,
|
||||
NULL,
|
||||
delete_fluid_file_audio_driver,
|
||||
NULL
|
||||
},
|
||||
#endif
|
||||
/* NULL terminator to avoid zero size array if no driver available */
|
||||
{ NULL, NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
#define ENABLE_AUDIO_DRIVER(_drv, _idx) \
|
||||
_drv[(_idx) / (sizeof(*(_drv))*8)] &= ~(1 << ((_idx) % (sizeof((*_drv))*8)))
|
||||
|
||||
#define IS_AUDIO_DRIVER_ENABLED(_drv, _idx) \
|
||||
(!(_drv[(_idx) / (sizeof(*(_drv))*8)] & (1 << ((_idx) % (sizeof((*_drv))*8)))))
|
||||
|
||||
static uint8_t fluid_adriver_disable_mask[(FLUID_N_ELEMENTS(fluid_audio_drivers) + 7) / 8] = {0};
|
||||
|
||||
void fluid_audio_driver_settings(fluid_settings_t *settings)
|
||||
{
|
||||
unsigned int i;
|
||||
const char *def_name = NULL;
|
||||
|
||||
fluid_settings_register_str(settings, "audio.sample-format", "16bits", 0);
|
||||
fluid_settings_add_option(settings, "audio.sample-format", "16bits");
|
||||
fluid_settings_add_option(settings, "audio.sample-format", "float");
|
||||
|
||||
#if defined(WIN32)
|
||||
fluid_settings_register_int(settings, "audio.period-size", 512, 64, 8192, 0);
|
||||
fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0);
|
||||
#elif defined(MACOS9)
|
||||
fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0);
|
||||
fluid_settings_register_int(settings, "audio.periods", 8, 2, 64, 0);
|
||||
#else
|
||||
fluid_settings_register_int(settings, "audio.period-size", 64, 64, 8192, 0);
|
||||
fluid_settings_register_int(settings, "audio.periods", 16, 2, 64, 0);
|
||||
#endif
|
||||
|
||||
fluid_settings_register_int(settings, "audio.realtime-prio",
|
||||
FLUID_DEFAULT_AUDIO_RT_PRIO, 0, 99, 0);
|
||||
|
||||
fluid_settings_register_str(settings, "audio.driver", "", 0);
|
||||
|
||||
for(i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers) - 1; i++)
|
||||
{
|
||||
/* Select the default driver */
|
||||
if (def_name == NULL)
|
||||
{
|
||||
def_name = fluid_audio_drivers[i].name;
|
||||
}
|
||||
|
||||
/* Add the driver to the list of options */
|
||||
fluid_settings_add_option(settings, "audio.driver", fluid_audio_drivers[i].name);
|
||||
|
||||
if(fluid_audio_drivers[i].settings != NULL &&
|
||||
IS_AUDIO_DRIVER_ENABLED(fluid_adriver_disable_mask, i))
|
||||
{
|
||||
fluid_audio_drivers[i].settings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the default driver, if any */
|
||||
if(def_name != NULL)
|
||||
{
|
||||
fluid_settings_setstr(settings, "audio.driver", def_name);
|
||||
}
|
||||
}
|
||||
|
||||
static const fluid_audriver_definition_t *
|
||||
find_fluid_audio_driver(fluid_settings_t *settings)
|
||||
{
|
||||
unsigned int i;
|
||||
char *name;
|
||||
char *allnames;
|
||||
|
||||
for(i = 0; i < FLUID_N_ELEMENTS(fluid_audio_drivers) - 1; i++)
|
||||
{
|
||||
/* If this driver is de-activated, just ignore it */
|
||||
if(!IS_AUDIO_DRIVER_ENABLED(fluid_adriver_disable_mask, i))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if(fluid_settings_str_equal(settings, "audio.driver", fluid_audio_drivers[i].name))
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Using '%s' audio driver", fluid_audio_drivers[i].name);
|
||||
return &fluid_audio_drivers[i];
|
||||
}
|
||||
}
|
||||
|
||||
fluid_settings_dupstr(settings, "audio.driver", &name); /* ++ alloc name */
|
||||
FLUID_LOG(FLUID_ERR, "Couldn't find the requested audio driver '%s'.", name ? name : "NULL");
|
||||
|
||||
allnames = fluid_settings_option_concat(settings, "audio.driver", NULL);
|
||||
if(allnames != NULL)
|
||||
{
|
||||
if(allnames[0] != '\0')
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "This build of fluidsynth supports the following audio drivers: %s", allnames);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "This build of fluidsynth doesn't support any audio drivers.");
|
||||
}
|
||||
|
||||
FLUID_FREE(allnames);
|
||||
}
|
||||
|
||||
FLUID_FREE(name);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audio driver.
|
||||
*
|
||||
* @param settings Configuration settings used to select and create the audio
|
||||
* driver.
|
||||
* @param synth Synthesizer instance for which the audio driver is created for.
|
||||
* @return The new audio driver instance or NULL on error
|
||||
*
|
||||
* Creates a new audio driver for a given \p synth instance with a defined set
|
||||
* of configuration \p settings. The \p settings instance must be the same that
|
||||
* you have passed to new_fluid_synth() when creating the \p synth instance.
|
||||
* Otherwise the behaviour is undefined.
|
||||
*
|
||||
* @note As soon as an audio driver is created, the \p synth starts rendering audio.
|
||||
* This means that all necessary initialization and sound-setup should have been
|
||||
* completed before calling this function.
|
||||
* Thus, of all object types in use (synth, midi player, sequencer, etc.) the audio
|
||||
* driver should always be the last one to be created and the first one to be deleted!
|
||||
* Also refer to the order of object creation in the code examples.
|
||||
*/
|
||||
fluid_audio_driver_t *
|
||||
new_fluid_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
||||
{
|
||||
const fluid_audriver_definition_t *def = find_fluid_audio_driver(settings);
|
||||
|
||||
if(def)
|
||||
{
|
||||
fluid_audio_driver_t *driver;
|
||||
double srate, midi_event_latency;
|
||||
int period_size;
|
||||
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &srate);
|
||||
|
||||
midi_event_latency = period_size / srate;
|
||||
if(midi_event_latency >= 0.05)
|
||||
{
|
||||
FLUID_LOG(FLUID_WARN, "You have chosen 'audio.period-size' to be %d samples. Given a sample rate of %.1f this results in a latency of %.1f ms, which will cause MIDI events to be poorly quantized (=untimed) in the synthesized audio (also known as the 'drunken-drummer' syndrome). To avoid that, you're strongly advised to increase 'audio.periods' instead, while keeping 'audio.period-size' small enough to make this warning disappear.", period_size, srate, midi_event_latency*1000.0);
|
||||
}
|
||||
|
||||
driver = (*def->new)(settings, synth);
|
||||
|
||||
if(driver)
|
||||
{
|
||||
driver->define = def;
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new audio driver.
|
||||
*
|
||||
* @param settings Configuration settings used to select and create the audio
|
||||
* driver.
|
||||
* @param func Function called to fill audio buffers for audio playback
|
||||
* @param data User defined data pointer to pass to \p func
|
||||
* @return The new audio driver instance or NULL on error
|
||||
*
|
||||
* Like new_fluid_audio_driver() but allows for custom audio processing before
|
||||
* audio is sent to audio driver. It is the responsibility of the callback
|
||||
* \p func to render the audio into the buffers. If \p func uses a fluid_synth_t \p synth,
|
||||
* the \p settings instance must be the same that you have passed to new_fluid_synth()
|
||||
* when creating the \p synth instance. Otherwise the behaviour is undefined.
|
||||
*
|
||||
* @note Not as efficient as new_fluid_audio_driver().
|
||||
*
|
||||
* @note As soon as an audio driver is created, a new thread is spawned starting to make
|
||||
* callbacks to \p func.
|
||||
* This means that all necessary sound-setup should be completed after this point,
|
||||
* thus of all object types in use (synth, midi player, sequencer, etc.) the audio
|
||||
* driver should always be the last one to be created and the first one to be deleted!
|
||||
* Also refer to the order of object creation in the code examples.
|
||||
*/
|
||||
fluid_audio_driver_t *
|
||||
new_fluid_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
|
||||
{
|
||||
const fluid_audriver_definition_t *def = find_fluid_audio_driver(settings);
|
||||
|
||||
if(def)
|
||||
{
|
||||
fluid_audio_driver_t *driver = NULL;
|
||||
|
||||
if(def->new2 == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Callback mode unsupported on '%s' audio driver", def->name);
|
||||
}
|
||||
else
|
||||
{
|
||||
driver = (*def->new2)(settings, func, data);
|
||||
|
||||
if(driver)
|
||||
{
|
||||
driver->define = def;
|
||||
}
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes an audio driver instance.
|
||||
*
|
||||
* @param driver Audio driver instance to delete
|
||||
*
|
||||
* Shuts down an audio driver and deletes its instance.
|
||||
*/
|
||||
void
|
||||
delete_fluid_audio_driver(fluid_audio_driver_t *driver)
|
||||
{
|
||||
fluid_return_if_fail(driver != NULL);
|
||||
driver->define->free(driver);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Registers audio drivers to use
|
||||
*
|
||||
* @param adrivers NULL-terminated array of audio drivers to register. Pass NULL to register all available drivers.
|
||||
* @return #FLUID_OK if all the audio drivers requested by the user are supported by fluidsynth and have been
|
||||
* successfully registered. Otherwise #FLUID_FAILED is returned and this function has no effect.
|
||||
*
|
||||
* When creating a settings instance with new_fluid_settings(), all audio drivers are initialized once.
|
||||
* In the past this has caused segfaults and application crashes due to buggy soundcard drivers.
|
||||
*
|
||||
* This function enables the user to only initialize specific audio drivers when settings instances are created.
|
||||
* Therefore pass a NULL-terminated array of C-strings containing the \c names of audio drivers to register
|
||||
* for the usage with fluidsynth.
|
||||
* The \c names are the same as being used for the \c audio.driver setting.
|
||||
*
|
||||
* By default all audio drivers fluidsynth has been compiled with are registered, so calling this function is optional.
|
||||
*
|
||||
* @warning This function may only be called if no thread is residing in fluidsynth's API and no instances of any kind
|
||||
* are alive (e.g. as it would be the case right after fluidsynth's initial creation). Else the behaviour is undefined.
|
||||
* Furtermore any attempt of using audio drivers that have not been registered is undefined behaviour!
|
||||
*
|
||||
* @note This function is not thread safe and will never be!
|
||||
*
|
||||
* @since 1.1.9
|
||||
*/
|
||||
int fluid_audio_driver_register(const char **adrivers)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t disable_mask[FLUID_N_ELEMENTS(fluid_adriver_disable_mask)];
|
||||
|
||||
if(adrivers == NULL)
|
||||
{
|
||||
/* Pass NULL to register all available drivers. */
|
||||
FLUID_MEMSET(fluid_adriver_disable_mask, 0, sizeof(fluid_adriver_disable_mask));
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(disable_mask, 0xFF, sizeof(disable_mask));
|
||||
|
||||
for(i = 0; adrivers[i] != NULL; i++)
|
||||
{
|
||||
unsigned int j;
|
||||
|
||||
/* search the requested audio driver in the template and enable it if found */
|
||||
for(j = 0; j < FLUID_N_ELEMENTS(fluid_audio_drivers) - 1; j++)
|
||||
{
|
||||
if(FLUID_STRCMP(adrivers[i], fluid_audio_drivers[j].name) == 0)
|
||||
{
|
||||
ENABLE_AUDIO_DRIVER(disable_mask, j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(j >= FLUID_N_ELEMENTS(fluid_audio_drivers) - 1)
|
||||
{
|
||||
/* requested driver not found, failure */
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update list of activated drivers */
|
||||
FLUID_MEMCPY(fluid_adriver_disable_mask, disable_mask, sizeof(disable_mask));
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
186
thirdparty/fluidsynth/src/drivers/fluid_adriver.h
vendored
Normal file
186
thirdparty/fluidsynth/src/drivers/fluid_adriver.h
vendored
Normal file
|
@ -0,0 +1,186 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUID_AUDRIVER_H
|
||||
#define _FLUID_AUDRIVER_H
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* fluid_audio_driver_t
|
||||
*/
|
||||
|
||||
typedef struct _fluid_audriver_definition_t fluid_audriver_definition_t;
|
||||
|
||||
struct _fluid_audio_driver_t
|
||||
{
|
||||
const fluid_audriver_definition_t *define;
|
||||
};
|
||||
|
||||
void fluid_audio_driver_settings(fluid_settings_t *settings);
|
||||
|
||||
/* Defined in fluid_filerenderer.c */
|
||||
void fluid_file_renderer_settings(fluid_settings_t *settings);
|
||||
|
||||
#if PULSE_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_pulse_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_pulse_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func, void *data);
|
||||
void delete_fluid_pulse_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_pulse_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if ALSA_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_alsa_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_alsa_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func, void *data);
|
||||
void delete_fluid_alsa_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_alsa_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if OSS_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_oss_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_oss_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func, void *data);
|
||||
void delete_fluid_oss_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_oss_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if OPENSLES_SUPPORT
|
||||
fluid_audio_driver_t*
|
||||
new_fluid_opensles_audio_driver(fluid_settings_t* settings,
|
||||
fluid_synth_t* synth);
|
||||
void delete_fluid_opensles_audio_driver(fluid_audio_driver_t* p);
|
||||
void fluid_opensles_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#if OBOE_SUPPORT
|
||||
fluid_audio_driver_t*
|
||||
new_fluid_oboe_audio_driver(fluid_settings_t* settings,
|
||||
fluid_synth_t* synth);
|
||||
void delete_fluid_oboe_audio_driver(fluid_audio_driver_t* p);
|
||||
void fluid_oboe_audio_driver_settings(fluid_settings_t* settings);
|
||||
#endif
|
||||
|
||||
#if COREAUDIO_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_core_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_core_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
void delete_fluid_core_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_core_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if DSOUND_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_dsound_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_dsound_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
void delete_fluid_dsound_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_dsound_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if WASAPI_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_wasapi_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_wasapi_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
void delete_fluid_wasapi_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_wasapi_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if WAVEOUT_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_waveout_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_waveout_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
void delete_fluid_waveout_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_waveout_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if PORTAUDIO_SUPPORT
|
||||
void fluid_portaudio_driver_settings(fluid_settings_t *settings);
|
||||
fluid_audio_driver_t *new_fluid_portaudio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
void delete_fluid_portaudio_driver(fluid_audio_driver_t *p);
|
||||
#endif
|
||||
|
||||
#if JACK_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_jack_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_jack_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func, void *data);
|
||||
void delete_fluid_jack_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_jack_audio_driver_settings(fluid_settings_t *settings);
|
||||
int fluid_jack_obtain_synth(fluid_settings_t *settings, fluid_synth_t **synth);
|
||||
#endif
|
||||
|
||||
#if PIPEWIRE_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_pipewire_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_pipewire_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func, void *data);
|
||||
void delete_fluid_pipewire_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_pipewire_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if SNDMAN_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_sndmgr_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
fluid_audio_driver_t *new_fluid_sndmgr_audio_driver2(fluid_settings_t *settings,
|
||||
fluid_audio_func_t func,
|
||||
void *data);
|
||||
void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t *p);
|
||||
#endif
|
||||
|
||||
#if DART_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_dart_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
void delete_fluid_dart_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_dart_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if SDL2_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_sdl2_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
void delete_fluid_sdl2_audio_driver(fluid_audio_driver_t *p);
|
||||
void fluid_sdl2_audio_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#if AUFILE_SUPPORT
|
||||
fluid_audio_driver_t *new_fluid_file_audio_driver(fluid_settings_t *settings,
|
||||
fluid_synth_t *synth);
|
||||
void delete_fluid_file_audio_driver(fluid_audio_driver_t *p);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _FLUID_AUDRIVER_H */
|
196
thirdparty/fluidsynth/src/drivers/fluid_mdriver.c
vendored
Normal file
196
thirdparty/fluidsynth/src/drivers/fluid_mdriver.c
vendored
Normal file
|
@ -0,0 +1,196 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "fluid_mdriver.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
|
||||
/*
|
||||
* fluid_mdriver_definition
|
||||
*/
|
||||
struct _fluid_mdriver_definition_t
|
||||
{
|
||||
const char *name;
|
||||
fluid_midi_driver_t *(*new)(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t event_handler,
|
||||
void *event_handler_data);
|
||||
void (*free)(fluid_midi_driver_t *p);
|
||||
void (*settings)(fluid_settings_t *settings);
|
||||
};
|
||||
|
||||
|
||||
static const fluid_mdriver_definition_t fluid_midi_drivers[] =
|
||||
{
|
||||
#if ALSA_SUPPORT
|
||||
{
|
||||
"alsa_seq",
|
||||
new_fluid_alsa_seq_driver,
|
||||
delete_fluid_alsa_seq_driver,
|
||||
fluid_alsa_seq_driver_settings
|
||||
},
|
||||
{
|
||||
"alsa_raw",
|
||||
new_fluid_alsa_rawmidi_driver,
|
||||
delete_fluid_alsa_rawmidi_driver,
|
||||
fluid_alsa_rawmidi_driver_settings
|
||||
},
|
||||
#endif
|
||||
#if JACK_SUPPORT
|
||||
{
|
||||
"jack",
|
||||
new_fluid_jack_midi_driver,
|
||||
delete_fluid_jack_midi_driver,
|
||||
fluid_jack_midi_driver_settings
|
||||
},
|
||||
#endif
|
||||
#if OSS_SUPPORT
|
||||
{
|
||||
"oss",
|
||||
new_fluid_oss_midi_driver,
|
||||
delete_fluid_oss_midi_driver,
|
||||
fluid_oss_midi_driver_settings
|
||||
},
|
||||
#endif
|
||||
#if WINMIDI_SUPPORT
|
||||
{
|
||||
"winmidi",
|
||||
new_fluid_winmidi_driver,
|
||||
delete_fluid_winmidi_driver,
|
||||
fluid_winmidi_midi_driver_settings
|
||||
},
|
||||
#endif
|
||||
#if MIDISHARE_SUPPORT
|
||||
{
|
||||
"midishare",
|
||||
new_fluid_midishare_midi_driver,
|
||||
delete_fluid_midishare_midi_driver,
|
||||
NULL
|
||||
},
|
||||
#endif
|
||||
#if COREMIDI_SUPPORT
|
||||
{
|
||||
"coremidi",
|
||||
new_fluid_coremidi_driver,
|
||||
delete_fluid_coremidi_driver,
|
||||
fluid_coremidi_driver_settings
|
||||
},
|
||||
#endif
|
||||
/* NULL terminator to avoid zero size array if no driver available */
|
||||
{ NULL, NULL, NULL, NULL }
|
||||
};
|
||||
|
||||
|
||||
void fluid_midi_driver_settings(fluid_settings_t *settings)
|
||||
{
|
||||
unsigned int i;
|
||||
const char *def_name = NULL;
|
||||
|
||||
fluid_settings_register_int(settings, "midi.autoconnect", 0, 0, 1, FLUID_HINT_TOGGLED);
|
||||
|
||||
fluid_settings_register_int(settings, "midi.realtime-prio",
|
||||
FLUID_DEFAULT_MIDI_RT_PRIO, 0, 99, 0);
|
||||
|
||||
fluid_settings_register_str(settings, "midi.driver", "", 0);
|
||||
|
||||
for(i = 0; i < FLUID_N_ELEMENTS(fluid_midi_drivers) - 1; i++)
|
||||
{
|
||||
/* Select the default driver */
|
||||
if (def_name == NULL)
|
||||
{
|
||||
def_name = fluid_midi_drivers[i].name;
|
||||
}
|
||||
|
||||
/* Add the driver to the list of options */
|
||||
fluid_settings_add_option(settings, "midi.driver", fluid_midi_drivers[i].name);
|
||||
|
||||
if(fluid_midi_drivers[i].settings != NULL)
|
||||
{
|
||||
fluid_midi_drivers[i].settings(settings);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the default driver, if any */
|
||||
if(def_name != NULL)
|
||||
{
|
||||
fluid_settings_setstr(settings, "midi.driver", def_name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MIDI driver instance.
|
||||
*
|
||||
* @param settings Settings used to configure new MIDI driver. See \ref settings_midi for available options.
|
||||
* @param handler MIDI handler callback (for example: fluid_midi_router_handle_midi_event()
|
||||
* for MIDI router)
|
||||
* @param event_handler_data Caller defined data to pass to 'handler'
|
||||
* @return New MIDI driver instance or NULL on error
|
||||
*
|
||||
* Which MIDI driver is actually created depends on the \ref settings_midi_driver option.
|
||||
*/
|
||||
fluid_midi_driver_t *new_fluid_midi_driver(fluid_settings_t *settings, handle_midi_event_func_t handler, void *event_handler_data)
|
||||
{
|
||||
fluid_midi_driver_t *driver = NULL;
|
||||
char *allnames;
|
||||
const fluid_mdriver_definition_t *def;
|
||||
|
||||
for(def = fluid_midi_drivers; def->name != NULL; def++)
|
||||
{
|
||||
if(fluid_settings_str_equal(settings, "midi.driver", def->name))
|
||||
{
|
||||
FLUID_LOG(FLUID_DBG, "Using '%s' midi driver", def->name);
|
||||
driver = def->new(settings, handler, event_handler_data);
|
||||
|
||||
if(driver)
|
||||
{
|
||||
driver->define = def;
|
||||
}
|
||||
|
||||
return driver;
|
||||
}
|
||||
}
|
||||
|
||||
FLUID_LOG(FLUID_ERR, "Couldn't find the requested midi driver.");
|
||||
allnames = fluid_settings_option_concat(settings, "midi.driver", NULL);
|
||||
if(allnames != NULL)
|
||||
{
|
||||
if(allnames[0] != '\0')
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "This build of fluidsynth supports the following MIDI drivers: %s", allnames);
|
||||
}
|
||||
else
|
||||
{
|
||||
FLUID_LOG(FLUID_INFO, "This build of fluidsynth doesn't support any MIDI drivers.");
|
||||
}
|
||||
|
||||
FLUID_FREE(allnames);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a MIDI driver instance.
|
||||
* @param driver MIDI driver to delete
|
||||
*/
|
||||
void delete_fluid_midi_driver(fluid_midi_driver_t *driver)
|
||||
{
|
||||
fluid_return_if_fail(driver != NULL);
|
||||
driver->define->free(driver);
|
||||
}
|
100
thirdparty/fluidsynth/src/drivers/fluid_mdriver.h
vendored
Normal file
100
thirdparty/fluidsynth/src/drivers/fluid_mdriver.h
vendored
Normal file
|
@ -0,0 +1,100 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUID_MDRIVER_H
|
||||
#define _FLUID_MDRIVER_H
|
||||
|
||||
#include "fluid_sys.h"
|
||||
|
||||
/*
|
||||
* fluid_midi_driver_t
|
||||
*/
|
||||
|
||||
typedef struct _fluid_mdriver_definition_t fluid_mdriver_definition_t;
|
||||
|
||||
struct _fluid_midi_driver_t
|
||||
{
|
||||
const fluid_mdriver_definition_t *define;
|
||||
handle_midi_event_func_t handler;
|
||||
void *data;
|
||||
};
|
||||
|
||||
void fluid_midi_driver_settings(fluid_settings_t *settings);
|
||||
|
||||
/* ALSA */
|
||||
#if ALSA_SUPPORT
|
||||
fluid_midi_driver_t *new_fluid_alsa_rawmidi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
void delete_fluid_alsa_rawmidi_driver(fluid_midi_driver_t *p);
|
||||
void fluid_alsa_rawmidi_driver_settings(fluid_settings_t *settings);
|
||||
|
||||
fluid_midi_driver_t *new_fluid_alsa_seq_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
void delete_fluid_alsa_seq_driver(fluid_midi_driver_t *p);
|
||||
void fluid_alsa_seq_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
/* JACK */
|
||||
#if JACK_SUPPORT
|
||||
void fluid_jack_midi_driver_settings(fluid_settings_t *settings);
|
||||
fluid_midi_driver_t *new_fluid_jack_midi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *data);
|
||||
void delete_fluid_jack_midi_driver(fluid_midi_driver_t *p);
|
||||
#endif
|
||||
|
||||
/* OSS */
|
||||
#if OSS_SUPPORT
|
||||
fluid_midi_driver_t *new_fluid_oss_midi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
void delete_fluid_oss_midi_driver(fluid_midi_driver_t *p);
|
||||
void fluid_oss_midi_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
/* Windows MIDI service */
|
||||
#if WINMIDI_SUPPORT
|
||||
fluid_midi_driver_t *new_fluid_winmidi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
void delete_fluid_winmidi_driver(fluid_midi_driver_t *p);
|
||||
void fluid_winmidi_midi_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
/* definitions for the MidiShare driver */
|
||||
#if MIDISHARE_SUPPORT
|
||||
fluid_midi_driver_t *new_fluid_midishare_midi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
void delete_fluid_midishare_midi_driver(fluid_midi_driver_t *p);
|
||||
#endif
|
||||
|
||||
/* definitions for the CoreMidi driver */
|
||||
#if COREMIDI_SUPPORT
|
||||
fluid_midi_driver_t *new_fluid_coremidi_driver(fluid_settings_t *settings,
|
||||
handle_midi_event_func_t handler,
|
||||
void *event_handler_data);
|
||||
void delete_fluid_coremidi_driver(fluid_midi_driver_t *p);
|
||||
void fluid_coremidi_driver_settings(fluid_settings_t *settings);
|
||||
#endif
|
||||
|
||||
#endif /* _FLUID_AUDRIVER_H */
|
368
thirdparty/fluidsynth/src/drivers/fluid_sndmgr.c
vendored
Normal file
368
thirdparty/fluidsynth/src/drivers/fluid_sndmgr.c
vendored
Normal file
|
@ -0,0 +1,368 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
|
||||
/* fluid_sndmgr.c
|
||||
*
|
||||
* Driver for MacOS Classic
|
||||
*/
|
||||
|
||||
#if SNDMAN_SUPPORT
|
||||
|
||||
#include "fluid_synth.h"
|
||||
#include "fluid_adriver.h"
|
||||
#include "fluid_settings.h"
|
||||
|
||||
#include <Sound.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
fluid_audio_driver_t driver;
|
||||
SndDoubleBufferHeader2 *doubleHeader;
|
||||
SndDoubleBackUPP doubleCallbackProc;
|
||||
SndChannelPtr channel;
|
||||
int callback_is_audio_func;
|
||||
void *data;
|
||||
fluid_audio_func_t callback;
|
||||
float *convbuffers[2];
|
||||
int bufferByteSize;
|
||||
int bufferFrameSize;
|
||||
} fluid_sndmgr_audio_driver_t;
|
||||
|
||||
void pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer);
|
||||
Fixed fluid_sndmgr_double_to_fix(long double theLD);
|
||||
|
||||
/*
|
||||
* generic new : returns error
|
||||
*/
|
||||
int
|
||||
start_fluid_sndmgr_audio_driver(fluid_settings_t *settings,
|
||||
fluid_sndmgr_audio_driver_t *dev,
|
||||
int buffer_size)
|
||||
{
|
||||
int i;
|
||||
SndDoubleBufferHeader2 *doubleHeader = NULL;
|
||||
SndDoubleBufferPtr doubleBuffer = NULL;
|
||||
OSErr err;
|
||||
SndChannelPtr channel = NULL;
|
||||
double sample_rate;
|
||||
|
||||
fluid_settings_getnum(settings, "synth.sample-rate", &sample_rate);
|
||||
|
||||
dev->doubleCallbackProc = NewSndDoubleBackProc(fluid_sndmgr_callback);
|
||||
|
||||
/* the channel */
|
||||
FLUID_LOG(FLUID_DBG, "FLUID-SndManager@2");
|
||||
err = SndNewChannel(&channel, sampledSynth, initStereo, NULL);
|
||||
|
||||
if((err != noErr) || (channel == NULL))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to allocate a sound channel (error %i)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* the double buffer struct */
|
||||
FLUID_LOG(FLUID_DBG, "FLUID-SndManager@3");
|
||||
doubleHeader = FLUID_NEW(SndDoubleBufferHeader2);
|
||||
|
||||
if(doubleHeader == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_PANIC, "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
doubleHeader->dbhBufferPtr[0] = NULL;
|
||||
doubleHeader->dbhBufferPtr[1] = NULL;
|
||||
doubleHeader->dbhNumChannels = 2;
|
||||
doubleHeader->dbhSampleSize = 16;
|
||||
doubleHeader->dbhCompressionID = 0;
|
||||
doubleHeader->dbhPacketSize = 0;
|
||||
doubleHeader->dbhSampleRate = fluid_sndmgr_double_to_fix((long double) sample_rate);
|
||||
doubleHeader->dbhDoubleBack = dev->doubleCallbackProc;
|
||||
doubleHeader->dbhFormat = 0;
|
||||
|
||||
/* prepare dev */
|
||||
FLUID_LOG(FLUID_DBG, "FLUID-SndManager@4");
|
||||
dev->doubleHeader = doubleHeader;
|
||||
dev->channel = channel;
|
||||
dev->bufferFrameSize = buffer_size;
|
||||
dev->bufferByteSize = buffer_size * 2 * 2;
|
||||
|
||||
/* the 2 doublebuffers */
|
||||
FLUID_LOG(FLUID_DBG, "FLUID-SndManager@5");
|
||||
|
||||
for(i = 0; i < 2; i++)
|
||||
{
|
||||
doubleBuffer = (SndDoubleBufferPtr) FLUID_MALLOC(sizeof(SndDoubleBuffer)
|
||||
+ dev->bufferByteSize);
|
||||
|
||||
if(doubleBuffer == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_PANIC, "Out of memory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
doubleBuffer->dbNumFrames = 0;
|
||||
doubleBuffer->dbFlags = 0;
|
||||
doubleBuffer->dbUserInfo[0] = (long) dev;
|
||||
doubleHeader->dbhBufferPtr[i] = doubleBuffer;
|
||||
CallSndDoubleBackProc(doubleHeader->dbhDoubleBack, channel, doubleBuffer);
|
||||
}
|
||||
|
||||
/* start */
|
||||
FLUID_LOG(FLUID_DBG, "FLUID-SndManager@6");
|
||||
|
||||
err = SndPlayDoubleBuffer(channel, (SndDoubleBufferHeader *)doubleHeader);
|
||||
|
||||
if(err != noErr)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Failed to start the sound driver (error %i)", err);
|
||||
return err;
|
||||
}
|
||||
|
||||
FLUID_LOG(FLUID_DBG, "FLUID-SndManager@7");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* new_fluid_sndmgr_audio_driver
|
||||
* This implementation used the 16bit format.
|
||||
*/
|
||||
fluid_audio_driver_t *
|
||||
new_fluid_sndmgr_audio_driver(fluid_settings_t *settings, fluid_synth_t *synth)
|
||||
{
|
||||
fluid_sndmgr_audio_driver_t *dev = NULL;
|
||||
int period_size, periods, buffer_size;
|
||||
|
||||
/* check the format */
|
||||
if(!fluid_settings_str_equal(settings, "audio.sample-format", "16bits"))
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Unhandled sample format");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* compute buffer size */
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getint(settings, "audio.periods", &periods);
|
||||
buffer_size = period_size * periods;
|
||||
|
||||
/* allocated dev */
|
||||
dev = FLUID_NEW(fluid_sndmgr_audio_driver_t);
|
||||
|
||||
if(dev == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_PANIC, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t));
|
||||
|
||||
dev->callback_is_audio_func = false;
|
||||
dev->data = (void *)synth;
|
||||
dev->callback = NULL;
|
||||
|
||||
if(start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0)
|
||||
{
|
||||
delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t *)dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (fluid_audio_driver_t *)dev;
|
||||
}
|
||||
|
||||
/*
|
||||
* new_fluid_sndmgr_audio_driver2
|
||||
*
|
||||
* This implementation used the audio_func float format, with
|
||||
* conversion from float to 16bits in the driver.
|
||||
*/
|
||||
fluid_audio_driver_t *
|
||||
new_fluid_sndmgr_audio_driver2(fluid_settings_t *settings, fluid_audio_func_t func, void *data)
|
||||
{
|
||||
fluid_sndmgr_audio_driver_t *dev = NULL;
|
||||
int period_size, periods, buffer_size;
|
||||
|
||||
/* compute buffer size */
|
||||
fluid_settings_getint(settings, "audio.period-size", &period_size);
|
||||
fluid_settings_getint(settings, "audio.periods", &periods);
|
||||
buffer_size = period_size * periods;
|
||||
|
||||
/* allocated dev */
|
||||
dev = FLUID_NEW(fluid_sndmgr_audio_driver_t);
|
||||
|
||||
if(dev == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_PANIC, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(dev, 0, sizeof(fluid_sndmgr_audio_driver_t));
|
||||
|
||||
/* allocate the conversion buffers */
|
||||
dev->convbuffers[0] = FLUID_ARRAY(float, buffer_size);
|
||||
dev->convbuffers[1] = FLUID_ARRAY(float, buffer_size);
|
||||
|
||||
if((dev->convbuffers[0] == NULL) || (dev->convbuffers[1] == NULL))
|
||||
{
|
||||
FLUID_LOG(FLUID_PANIC, "Out of memory");
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
dev->callback_is_audio_func = true;
|
||||
dev->data = data;
|
||||
dev->callback = func;
|
||||
|
||||
if(start_fluid_sndmgr_audio_driver(settings, dev, buffer_size) != 0)
|
||||
{
|
||||
goto error_recovery;
|
||||
}
|
||||
|
||||
return (fluid_audio_driver_t *)dev;
|
||||
|
||||
error_recovery:
|
||||
delete_fluid_sndmgr_audio_driver((fluid_audio_driver_t *)dev);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* delete_fluid_sndmgr_audio_driver
|
||||
*/
|
||||
void delete_fluid_sndmgr_audio_driver(fluid_audio_driver_t *p)
|
||||
{
|
||||
fluid_sndmgr_audio_driver_t *dev = (fluid_sndmgr_audio_driver_t *) p;
|
||||
fluid_return_if_fail(dev != NULL);
|
||||
|
||||
if(dev->channel != NULL)
|
||||
{
|
||||
SndDisposeChannel(dev->channel, 1);
|
||||
}
|
||||
|
||||
if(dev->doubleCallbackProc != NULL)
|
||||
{
|
||||
DisposeRoutineDescriptor(dev->doubleCallbackProc);
|
||||
}
|
||||
|
||||
if(dev->doubleHeader != NULL)
|
||||
{
|
||||
FLUID_FREE(dev->doubleHeader->dbhBufferPtr[0]);
|
||||
FLUID_FREE(dev->doubleHeader->dbhBufferPtr[1]);
|
||||
FLUID_FREE(dev->doubleHeader);
|
||||
}
|
||||
|
||||
FLUID_FREE(dev->convbuffers[0]);
|
||||
FLUID_FREE(dev->convbuffers[1]);
|
||||
FLUID_FREE(dev);
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_sndmgr_callback
|
||||
*
|
||||
*/
|
||||
void pascal fluid_sndmgr_callback(SndChannelPtr chan, SndDoubleBufferPtr doubleBuffer)
|
||||
{
|
||||
fluid_sndmgr_audio_driver_t *dev;
|
||||
signed short *buf;
|
||||
float *left;
|
||||
float *right;
|
||||
float v;
|
||||
int i, k, buffer_size;
|
||||
|
||||
dev = (fluid_sndmgr_audio_driver_t *) doubleBuffer->dbUserInfo[0];
|
||||
buf = (signed short *)doubleBuffer->dbSoundData;
|
||||
buffer_size = dev->bufferFrameSize;
|
||||
|
||||
if(dev->callback_is_audio_func)
|
||||
{
|
||||
/* float API : conversion to signed short */
|
||||
left = dev->convbuffers[0];
|
||||
right = dev->convbuffers[1];
|
||||
|
||||
FLUID_MEMSET(left, 0, buffer_size * sizeof(float));
|
||||
FLUID_MEMSET(right, 0, buffer_size * sizeof(float));
|
||||
|
||||
(*dev->callback)(dev->data, buffer_size, 0, NULL, 2, dev->convbuffers);
|
||||
|
||||
for(i = 0, k = 0; i < buffer_size; i++)
|
||||
{
|
||||
v = 32767.0f * left[i];
|
||||
fluid_clip(v, -32768.0f, 32767.0f);
|
||||
buf[k++] = (signed short) v;
|
||||
|
||||
v = 32767.0f * right[i];
|
||||
fluid_clip(v, -32768.0f, 32767.0f);
|
||||
buf[k++] = (signed short) v;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* let the synth do the conversion */
|
||||
fluid_synth_write_s16((fluid_synth_t *)dev->data, buffer_size, buf, 0, 2, buf, 1, 2);
|
||||
}
|
||||
|
||||
doubleBuffer->dbFlags = doubleBuffer->dbFlags | dbBufferReady;
|
||||
doubleBuffer->dbNumFrames = buffer_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* fluid_sndmgr_double_to_fix
|
||||
*
|
||||
* A Fixed number is of the type 12345.67890. It is 32 bits in size with the
|
||||
* high order bits representing the significant value (that before the point)
|
||||
* and the lower 16 bits representing the fractional part of the number.
|
||||
* The Sound Manager further complicates matters by using Fixed numbers, but
|
||||
* needing to represent numbers larger than what the Fixed is capable of.
|
||||
* To do this the Sound Manager treats the sign bit as having the value 32768
|
||||
* which will cause any number greater or equal to 32768 to look like it is
|
||||
* negative.
|
||||
* This routine is designed to "do the right thing" and convert any long double
|
||||
* into the Fixed number it represents.
|
||||
* long double is the input type because AIFF files use extended80 numbers and
|
||||
* there are routines that will convert from an extended80 to a long double.
|
||||
* A long double has far greater precision than a Fixed, so any number whose
|
||||
* significant or fraction is larger than 65535 will not convert correctly.
|
||||
*/
|
||||
#define _MAX_VALUE 65535
|
||||
#define _BITS_PER_BYTE 8
|
||||
Fixed fluid_sndmgr_double_to_fix(long double theLD)
|
||||
{
|
||||
unsigned long theResult = 0;
|
||||
unsigned short theSignificant = 0, theFraction = 0;
|
||||
|
||||
if(theLD < _MAX_VALUE)
|
||||
{
|
||||
theSignificant = theLD;
|
||||
theFraction = theLD - theSignificant;
|
||||
|
||||
if(theFraction > _MAX_VALUE)
|
||||
{
|
||||
/* Won't be able to convert */
|
||||
theSignificant = 0;
|
||||
theFraction = 0;
|
||||
}
|
||||
}
|
||||
|
||||
theResult |= theSignificant;
|
||||
theResult = theResult << (sizeof(unsigned short) * _BITS_PER_BYTE);
|
||||
theResult |= theFraction;
|
||||
return theResult;
|
||||
}
|
||||
|
||||
#endif
|
3916
thirdparty/fluidsynth/src/fluid_conv_tables.inc.h
vendored
Normal file
3916
thirdparty/fluidsynth/src/fluid_conv_tables.inc.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
4110
thirdparty/fluidsynth/src/fluid_rvoice_dsp_tables.inc.h
vendored
Normal file
4110
thirdparty/fluidsynth/src/fluid_rvoice_dsp_tables.inc.h
vendored
Normal file
File diff suppressed because it is too large
Load diff
36
thirdparty/fluidsynth/src/gentables/CMakeLists.txt
vendored
Normal file
36
thirdparty/fluidsynth/src/gentables/CMakeLists.txt
vendored
Normal file
|
@ -0,0 +1,36 @@
|
|||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
# remove $CC from the current environment and by that force cmake to look for a (working) C compiler,
|
||||
# which hopefully will be the host compiler
|
||||
unset(ENV{CC})
|
||||
|
||||
# also unset $CFLAGS to avoid passing any cross compilation flags to the host compiler
|
||||
unset(ENV{CFLAGS})
|
||||
|
||||
# linker flags as well
|
||||
unset(ENV{LDFLAGS})
|
||||
|
||||
project (gentables C)
|
||||
|
||||
set ( CMAKE_BUILD_TYPE Debug )
|
||||
|
||||
# hardcode ".exe" as suffix to the binary, else in case of cross-platform cross-compiling the calling cmake will not know the suffix used here and fail to find the binary
|
||||
set ( CMAKE_EXECUTABLE_SUFFIX ".exe" )
|
||||
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG ${CMAKE_BINARY_DIR})
|
||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE ${CMAKE_BINARY_DIR})
|
||||
|
||||
# Add the executable that generates the table
|
||||
add_executable( make_tables
|
||||
make_tables.c
|
||||
gen_conv.c
|
||||
gen_rvoice_dsp.c)
|
||||
|
||||
target_include_directories( make_tables PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../ )
|
||||
|
||||
if ( WIN32 )
|
||||
add_definitions ( -D_USE_MATH_DEFINES -D_CRT_SECURE_NO_WARNINGS )
|
||||
else ( WIN32 )
|
||||
target_link_libraries (make_tables "m")
|
||||
endif ()
|
84
thirdparty/fluidsynth/src/gentables/gen_conv.c
vendored
Normal file
84
thirdparty/fluidsynth/src/gentables/gen_conv.c
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
#include "utils/fluid_conv_tables.h"
|
||||
#include "make_tables.h"
|
||||
|
||||
|
||||
/* conversion tables */
|
||||
static double fluid_ct2hz_tab[FLUID_CENTS_HZ_SIZE];
|
||||
static double fluid_cb2amp_tab[FLUID_CB_AMP_SIZE];
|
||||
static double fluid_concave_tab[FLUID_VEL_CB_SIZE];
|
||||
static double fluid_convex_tab[FLUID_VEL_CB_SIZE];
|
||||
static double fluid_pan_tab[FLUID_PAN_SIZE];
|
||||
|
||||
/*
|
||||
* void fluid_synth_init
|
||||
*
|
||||
* Does all the initialization for this module.
|
||||
*/
|
||||
static void fluid_conversion_config(void)
|
||||
{
|
||||
int i;
|
||||
double x;
|
||||
|
||||
for(i = 0; i < FLUID_CENTS_HZ_SIZE; i++)
|
||||
{
|
||||
// 6,875 is just a factor that we already multiply into the lookup table to save
|
||||
// that multiplication in fluid_ct2hz_real()
|
||||
// 6.875 Hz because 440Hz / 2^6
|
||||
fluid_ct2hz_tab[i] = 6.875 * powl(2.0, (double) i / 1200.0);
|
||||
}
|
||||
|
||||
/* centibels to amplitude conversion
|
||||
* Note: SF2.01 section 8.1.3: Initial attenuation range is
|
||||
* between 0 and 144 dB. Therefore a negative attenuation is
|
||||
* not allowed.
|
||||
*/
|
||||
for(i = 0; i < FLUID_CB_AMP_SIZE; i++)
|
||||
{
|
||||
fluid_cb2amp_tab[i] = powl(10.0, (double) i / -200.0);
|
||||
}
|
||||
|
||||
/* initialize the conversion tables (see fluid_mod.c
|
||||
fluid_mod_get_value cases 4 and 8) */
|
||||
|
||||
/* concave unipolar positive transform curve */
|
||||
fluid_concave_tab[0] = 0.0;
|
||||
fluid_concave_tab[FLUID_VEL_CB_SIZE - 1] = 1.0;
|
||||
|
||||
/* convex unipolar positive transform curve */
|
||||
fluid_convex_tab[0] = 0;
|
||||
fluid_convex_tab[FLUID_VEL_CB_SIZE - 1] = 1.0;
|
||||
|
||||
/* There seems to be an error in the specs. The equations are
|
||||
implemented according to the pictures on SF2.01 page 73. */
|
||||
|
||||
for(i = 1; i < FLUID_VEL_CB_SIZE - 1; i++)
|
||||
{
|
||||
x = (-200.0 / FLUID_PEAK_ATTENUATION) * log((double)(i * i) / ((FLUID_VEL_CB_SIZE - 1) * (FLUID_VEL_CB_SIZE - 1))) / M_LN10;
|
||||
fluid_convex_tab[i] = (1.0 - x);
|
||||
fluid_concave_tab[(FLUID_VEL_CB_SIZE - 1) - i] = x;
|
||||
}
|
||||
|
||||
/* initialize the pan conversion table */
|
||||
x = M_PI / 2.0 / (FLUID_PAN_SIZE - 1.0);
|
||||
|
||||
for(i = 0; i < FLUID_PAN_SIZE; i++)
|
||||
{
|
||||
fluid_pan_tab[i] = sin(i * x);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gen_conv_table(FILE *fp)
|
||||
{
|
||||
/* Calculate the values */
|
||||
fluid_conversion_config();
|
||||
|
||||
/* fluid_ct2hz_tab */
|
||||
EMIT_ARRAY(fp, fluid_ct2hz_tab);
|
||||
EMIT_ARRAY(fp, fluid_cb2amp_tab);
|
||||
EMIT_ARRAY(fp, fluid_concave_tab);
|
||||
EMIT_ARRAY(fp, fluid_convex_tab);
|
||||
EMIT_ARRAY(fp, fluid_pan_tab);
|
||||
}
|
||||
|
81
thirdparty/fluidsynth/src/gentables/gen_rvoice_dsp.c
vendored
Normal file
81
thirdparty/fluidsynth/src/gentables/gen_rvoice_dsp.c
vendored
Normal file
|
@ -0,0 +1,81 @@
|
|||
|
||||
#include "rvoice/fluid_rvoice_dsp_tables.h"
|
||||
#include "make_tables.h"
|
||||
|
||||
/* Linear interpolation table (2 coefficients centered on 1st) */
|
||||
static double interp_coeff_linear[FLUID_INTERP_MAX][2];
|
||||
|
||||
/* 4th order (cubic) interpolation table (4 coefficients centered on 2nd) */
|
||||
static double interp_coeff[FLUID_INTERP_MAX][4];
|
||||
|
||||
/* 7th order interpolation (7 coefficients centered on 3rd) */
|
||||
static double sinc_table7[FLUID_INTERP_MAX][SINC_INTERP_ORDER];
|
||||
|
||||
static double cb_interp_coeff_linear(int y, int x) { return interp_coeff_linear[y][x]; }
|
||||
static double cb_interp_coeff (int y, int x) { return interp_coeff[y][x]; }
|
||||
static double cb_sinc_table7 (int y, int x) { return sinc_table7[y][x]; }
|
||||
|
||||
/* Initializes interpolation tables */
|
||||
void fluid_rvoice_dsp_config(void)
|
||||
{
|
||||
int i, i2;
|
||||
double x, v;
|
||||
double i_shifted;
|
||||
|
||||
/* Initialize the coefficients for the interpolation. The math comes
|
||||
* from a mail, posted by Olli Niemitalo to the music-dsp mailing
|
||||
* list (I found it in the music-dsp archives
|
||||
* http://www.smartelectronix.com/musicdsp/). */
|
||||
|
||||
for(i = 0; i < FLUID_INTERP_MAX; i++)
|
||||
{
|
||||
x = (double) i / (double) FLUID_INTERP_MAX;
|
||||
|
||||
interp_coeff[i][0] = (x * (-0.5 + x * (1 - 0.5 * x)));
|
||||
interp_coeff[i][1] = (1.0 + x * x * (1.5 * x - 2.5));
|
||||
interp_coeff[i][2] = (x * (0.5 + x * (2.0 - 1.5 * x)));
|
||||
interp_coeff[i][3] = (0.5 * x * x * (x - 1.0));
|
||||
|
||||
interp_coeff_linear[i][0] = (1.0 - x);
|
||||
interp_coeff_linear[i][1] = x;
|
||||
}
|
||||
|
||||
/* i: Offset in terms of whole samples */
|
||||
for(i = 0; i < SINC_INTERP_ORDER; i++)
|
||||
{
|
||||
/* i2: Offset in terms of fractional samples ('subsamples') */
|
||||
for(i2 = 0; i2 < FLUID_INTERP_MAX; i2++)
|
||||
{
|
||||
/* center on middle of table */
|
||||
i_shifted = (double)i - ((double)SINC_INTERP_ORDER / 2.0)
|
||||
+ (double)i2 / (double)FLUID_INTERP_MAX;
|
||||
|
||||
/* sinc(0) cannot be calculated straightforward (limit needed for 0/0) */
|
||||
if(fabs(i_shifted) > 0.000001)
|
||||
{
|
||||
double arg = M_PI * i_shifted;
|
||||
v = sin(arg) / (arg);
|
||||
/* Hanning window */
|
||||
v *= 0.5 * (1.0 + cos(2.0 * arg / (double)SINC_INTERP_ORDER));
|
||||
}
|
||||
else
|
||||
{
|
||||
v = 1.0;
|
||||
}
|
||||
|
||||
sinc_table7[FLUID_INTERP_MAX - i2 - 1][i] = v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gen_rvoice_table_dsp (FILE *fp)
|
||||
{
|
||||
/* Calculate the values */
|
||||
fluid_rvoice_dsp_config();
|
||||
|
||||
/* Emit the matrices */
|
||||
emit_matrix(fp, "interp_coeff_linear", cb_interp_coeff_linear, FLUID_INTERP_MAX, 2);
|
||||
emit_matrix(fp, "interp_coeff", cb_interp_coeff, FLUID_INTERP_MAX, 4);
|
||||
emit_matrix(fp, "sinc_table7", cb_sinc_table7, FLUID_INTERP_MAX, 7);
|
||||
}
|
84
thirdparty/fluidsynth/src/gentables/make_tables.c
vendored
Normal file
84
thirdparty/fluidsynth/src/gentables/make_tables.c
vendored
Normal file
|
@ -0,0 +1,84 @@
|
|||
|
||||
#include "make_tables.h"
|
||||
|
||||
static void write_value(FILE *fp, double val, int i)
|
||||
{
|
||||
fprintf(fp, " %.15e%c /* %d */\n",
|
||||
val,
|
||||
',',
|
||||
i
|
||||
);
|
||||
}
|
||||
|
||||
/* Emit an array of real numbers */
|
||||
void emit_array(FILE *fp, const char *tblname, const double *tbl, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
fprintf(fp, "static const fluid_real_t %s[%d] = {\n", tblname, size);
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
{
|
||||
write_value(fp, tbl[i], i);
|
||||
}
|
||||
fprintf(fp, "};\n\n");
|
||||
}
|
||||
|
||||
/* Emit a matrix of real numbers */
|
||||
void emit_matrix(FILE *fp, const char *tblname, emit_matrix_cb tbl_cb, int sizeh, int sizel)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
fprintf(fp, "static const fluid_real_t %s[%d][%d] = {\n {\n", tblname, sizeh, sizel);
|
||||
|
||||
for (i = 0; i < sizeh; i++)
|
||||
{
|
||||
for (j = 0; j < sizel; j++)
|
||||
{
|
||||
write_value(fp, tbl_cb(i, j), i*sizel+j);
|
||||
}
|
||||
|
||||
|
||||
if (i < (sizeh-1))
|
||||
fprintf(fp, " }, {\n");
|
||||
else
|
||||
fprintf(fp, " }\n};\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void open_table(FILE**fp, const char* dir, const char* file)
|
||||
{
|
||||
char buf[2048] = {0};
|
||||
|
||||
strcat(buf, dir);
|
||||
strcat(buf, file);
|
||||
|
||||
/* open the output file */
|
||||
*fp = fopen(buf, "w");
|
||||
if (*fp == NULL)
|
||||
{
|
||||
exit(-2);
|
||||
}
|
||||
|
||||
/* Emit warning header */
|
||||
fprintf(*fp, "/* THIS FILE HAS BEEN AUTOMATICALLY GENERATED. DO NOT EDIT. */\n\n");
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
FILE *fp;
|
||||
|
||||
// make sure we have enough arguments
|
||||
if (argc < 2)
|
||||
return -1;
|
||||
|
||||
open_table(&fp, argv[1], "fluid_conv_tables.inc.h");
|
||||
gen_conv_table(fp);
|
||||
fclose(fp);
|
||||
|
||||
open_table(&fp, argv[1], "fluid_rvoice_dsp_tables.inc.h");
|
||||
gen_rvoice_table_dsp(fp);
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
26
thirdparty/fluidsynth/src/gentables/make_tables.h
vendored
Normal file
26
thirdparty/fluidsynth/src/gentables/make_tables.h
vendored
Normal file
|
@ -0,0 +1,26 @@
|
|||
|
||||
#ifndef _FLUID_MAKE_TABLES_H
|
||||
#define _FLUID_MAKE_TABLES_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#define EMIT_ARRAY(__fp__, __arr__) emit_array(__fp__, #__arr__, __arr__, sizeof(__arr__)/sizeof(*__arr__))
|
||||
|
||||
/* callback for general access to matrices */
|
||||
typedef double (*emit_matrix_cb)(int y, int x);
|
||||
|
||||
/* Generators */
|
||||
void gen_rvoice_table_dsp(FILE *fp);
|
||||
void gen_conv_table(FILE *fp);
|
||||
|
||||
/* Emit an array of real numbers */
|
||||
void emit_array(FILE *fp, const char *tblname, const double *tbl, int size);
|
||||
|
||||
/* Emit a matrix of real numbers */
|
||||
void emit_matrix(FILE *fp, const char *tblname, emit_matrix_cb tbl_cb, int sizeh, int sizel);
|
||||
|
||||
#endif
|
2788
thirdparty/fluidsynth/src/midi/fluid_midi.c
vendored
Normal file
2788
thirdparty/fluidsynth/src/midi/fluid_midi.c
vendored
Normal file
File diff suppressed because it is too large
Load diff
380
thirdparty/fluidsynth/src/midi/fluid_midi.h
vendored
Normal file
380
thirdparty/fluidsynth/src/midi/fluid_midi.h
vendored
Normal file
|
@ -0,0 +1,380 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef _FLUID_MIDI_H
|
||||
#define _FLUID_MIDI_H
|
||||
|
||||
#include "fluidsynth_priv.h"
|
||||
#include "fluid_sys.h"
|
||||
#include "fluid_list.h"
|
||||
|
||||
typedef struct _fluid_midi_parser_t fluid_midi_parser_t;
|
||||
|
||||
fluid_midi_parser_t *new_fluid_midi_parser(void);
|
||||
void delete_fluid_midi_parser(fluid_midi_parser_t *parser);
|
||||
fluid_midi_event_t *fluid_midi_parser_parse(fluid_midi_parser_t *parser, unsigned char c);
|
||||
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* CONSTANTS & ENUM
|
||||
*/
|
||||
|
||||
|
||||
#define MAX_NUMBER_OF_TRACKS 128
|
||||
#define MAX_NUMBER_OF_CHANNELS 16
|
||||
|
||||
enum fluid_midi_event_type
|
||||
{
|
||||
/* channel messages */
|
||||
NOTE_OFF = 0x80,
|
||||
NOTE_ON = 0x90,
|
||||
KEY_PRESSURE = 0xa0,
|
||||
CONTROL_CHANGE = 0xb0,
|
||||
PROGRAM_CHANGE = 0xc0,
|
||||
CHANNEL_PRESSURE = 0xd0,
|
||||
PITCH_BEND = 0xe0,
|
||||
/* system exclusive */
|
||||
MIDI_SYSEX = 0xf0,
|
||||
/* system common - never in midi files */
|
||||
MIDI_TIME_CODE = 0xf1,
|
||||
MIDI_SONG_POSITION = 0xf2,
|
||||
MIDI_SONG_SELECT = 0xf3,
|
||||
MIDI_TUNE_REQUEST = 0xf6,
|
||||
MIDI_EOX = 0xf7,
|
||||
/* system real-time - never in midi files */
|
||||
MIDI_SYNC = 0xf8,
|
||||
MIDI_TICK = 0xf9,
|
||||
MIDI_START = 0xfa,
|
||||
MIDI_CONTINUE = 0xfb,
|
||||
MIDI_STOP = 0xfc,
|
||||
MIDI_ACTIVE_SENSING = 0xfe,
|
||||
MIDI_SYSTEM_RESET = 0xff,
|
||||
/* meta event - for midi files only */
|
||||
MIDI_META_EVENT = 0xff
|
||||
};
|
||||
|
||||
enum fluid_midi_control_change
|
||||
{
|
||||
BANK_SELECT_MSB = 0x00,
|
||||
MODULATION_MSB = 0x01,
|
||||
BREATH_MSB = 0x02,
|
||||
FOOT_MSB = 0x04,
|
||||
PORTAMENTO_TIME_MSB = 0x05,
|
||||
DATA_ENTRY_MSB = 0x06,
|
||||
VOLUME_MSB = 0x07,
|
||||
BALANCE_MSB = 0x08,
|
||||
PAN_MSB = 0x0A,
|
||||
EXPRESSION_MSB = 0x0B,
|
||||
EFFECTS1_MSB = 0x0C,
|
||||
EFFECTS2_MSB = 0x0D,
|
||||
GPC1_MSB = 0x10, /* general purpose controller */
|
||||
GPC2_MSB = 0x11,
|
||||
GPC3_MSB = 0x12,
|
||||
GPC4_MSB = 0x13,
|
||||
BANK_SELECT_LSB = 0x20,
|
||||
MODULATION_WHEEL_LSB = 0x21,
|
||||
BREATH_LSB = 0x22,
|
||||
FOOT_LSB = 0x24,
|
||||
PORTAMENTO_TIME_LSB = 0x25,
|
||||
DATA_ENTRY_LSB = 0x26,
|
||||
VOLUME_LSB = 0x27,
|
||||
BALANCE_LSB = 0x28,
|
||||
PAN_LSB = 0x2A,
|
||||
EXPRESSION_LSB = 0x2B,
|
||||
EFFECTS1_LSB = 0x2C,
|
||||
EFFECTS2_LSB = 0x2D,
|
||||
GPC1_LSB = 0x30,
|
||||
GPC2_LSB = 0x31,
|
||||
GPC3_LSB = 0x32,
|
||||
GPC4_LSB = 0x33,
|
||||
SUSTAIN_SWITCH = 0x40,
|
||||
PORTAMENTO_SWITCH = 0x41,
|
||||
SOSTENUTO_SWITCH = 0x42,
|
||||
SOFT_PEDAL_SWITCH = 0x43,
|
||||
LEGATO_SWITCH = 0x44,
|
||||
HOLD2_SWITCH = 0x45,
|
||||
SOUND_CTRL1 = 0x46,
|
||||
SOUND_CTRL2 = 0x47,
|
||||
SOUND_CTRL3 = 0x48,
|
||||
SOUND_CTRL4 = 0x49,
|
||||
SOUND_CTRL5 = 0x4A,
|
||||
SOUND_CTRL6 = 0x4B,
|
||||
SOUND_CTRL7 = 0x4C,
|
||||
SOUND_CTRL8 = 0x4D,
|
||||
SOUND_CTRL9 = 0x4E,
|
||||
SOUND_CTRL10 = 0x4F,
|
||||
GPC5 = 0x50,
|
||||
GPC6 = 0x51,
|
||||
GPC7 = 0x52,
|
||||
GPC8 = 0x53,
|
||||
PORTAMENTO_CTRL = 0x54,
|
||||
EFFECTS_DEPTH1 = 0x5B,
|
||||
EFFECTS_DEPTH2 = 0x5C,
|
||||
EFFECTS_DEPTH3 = 0x5D,
|
||||
EFFECTS_DEPTH4 = 0x5E,
|
||||
EFFECTS_DEPTH5 = 0x5F,
|
||||
DATA_ENTRY_INCR = 0x60,
|
||||
DATA_ENTRY_DECR = 0x61,
|
||||
NRPN_LSB = 0x62,
|
||||
NRPN_MSB = 0x63,
|
||||
RPN_LSB = 0x64,
|
||||
RPN_MSB = 0x65,
|
||||
ALL_SOUND_OFF = 0x78,
|
||||
ALL_CTRL_OFF = 0x79,
|
||||
LOCAL_CONTROL = 0x7A,
|
||||
ALL_NOTES_OFF = 0x7B,
|
||||
OMNI_OFF = 0x7C,
|
||||
OMNI_ON = 0x7D,
|
||||
POLY_OFF = 0x7E,
|
||||
POLY_ON = 0x7F
|
||||
};
|
||||
|
||||
/* General MIDI RPN event numbers (LSB, MSB = 0) */
|
||||
enum midi_rpn_event
|
||||
{
|
||||
RPN_PITCH_BEND_RANGE = 0x00,
|
||||
RPN_CHANNEL_FINE_TUNE = 0x01,
|
||||
RPN_CHANNEL_COARSE_TUNE = 0x02,
|
||||
RPN_TUNING_PROGRAM_CHANGE = 0x03,
|
||||
RPN_TUNING_BANK_SELECT = 0x04,
|
||||
RPN_MODULATION_DEPTH_RANGE = 0x05
|
||||
};
|
||||
|
||||
enum midi_meta_event
|
||||
{
|
||||
MIDI_TEXT = 0x01,
|
||||
MIDI_COPYRIGHT = 0x02,
|
||||
MIDI_TRACK_NAME = 0x03,
|
||||
MIDI_INST_NAME = 0x04,
|
||||
MIDI_LYRIC = 0x05,
|
||||
MIDI_MARKER = 0x06,
|
||||
MIDI_CUE_POINT = 0x07,
|
||||
MIDI_EOT = 0x2f,
|
||||
MIDI_SET_TEMPO = 0x51,
|
||||
MIDI_SMPTE_OFFSET = 0x54,
|
||||
MIDI_TIME_SIGNATURE = 0x58,
|
||||
MIDI_KEY_SIGNATURE = 0x59,
|
||||
MIDI_SEQUENCER_EVENT = 0x7f
|
||||
};
|
||||
|
||||
/* MIDI SYSEX useful manufacturer values */
|
||||
enum midi_sysex_manuf
|
||||
{
|
||||
MIDI_SYSEX_MANUF_ROLAND = 0x41, /**< Roland manufacturer ID */
|
||||
MIDI_SYSEX_MANUF_YAMAHA = 0x43,
|
||||
MIDI_SYSEX_UNIV_NON_REALTIME = 0x7E, /**< Universal non realtime message */
|
||||
MIDI_SYSEX_UNIV_REALTIME = 0x7F /**< Universal realtime message */
|
||||
};
|
||||
|
||||
#define MIDI_SYSEX_DEVICE_ID_ALL 0x7F /**< Device ID used in SYSEX messages to indicate all devices */
|
||||
|
||||
/* SYSEX sub-ID #1 which follows device ID */
|
||||
#define MIDI_SYSEX_MIDI_TUNING_ID 0x08 /**< Sysex sub-ID #1 for MIDI tuning messages */
|
||||
#define MIDI_SYSEX_GM_ID 0x09 /**< Sysex sub-ID #1 for General MIDI messages */
|
||||
#define MIDI_SYSEX_GS_ID 0x42 /**< Model ID (GS) serving as sub-ID #1 for GS messages*/
|
||||
#define MIDI_SYSEX_XG_ID 0x4C /**< Model ID (XG) serving as sub-ID #1 for XG messages*/
|
||||
|
||||
/**
|
||||
* SYSEX tuning message IDs.
|
||||
*/
|
||||
enum midi_sysex_tuning_msg_id
|
||||
{
|
||||
MIDI_SYSEX_TUNING_BULK_DUMP_REQ = 0x00, /**< Bulk tuning dump request (non-realtime) */
|
||||
MIDI_SYSEX_TUNING_BULK_DUMP = 0x01, /**< Bulk tuning dump response (non-realtime) */
|
||||
MIDI_SYSEX_TUNING_NOTE_TUNE = 0x02, /**< Tuning note change message (realtime) */
|
||||
MIDI_SYSEX_TUNING_BULK_DUMP_REQ_BANK = 0x03, /**< Bulk tuning dump request (with bank, non-realtime) */
|
||||
MIDI_SYSEX_TUNING_BULK_DUMP_BANK = 0x04, /**< Bulk tuning dump response (with bank, non-realtime) */
|
||||
MIDI_SYSEX_TUNING_OCTAVE_DUMP_1BYTE = 0x05, /**< Octave tuning dump using 1 byte values (non-realtime) */
|
||||
MIDI_SYSEX_TUNING_OCTAVE_DUMP_2BYTE = 0x06, /**< Octave tuning dump using 2 byte values (non-realtime) */
|
||||
MIDI_SYSEX_TUNING_NOTE_TUNE_BANK = 0x07, /**< Tuning note change message (with bank, realtime/non-realtime) */
|
||||
MIDI_SYSEX_TUNING_OCTAVE_TUNE_1BYTE = 0x08, /**< Octave tuning message using 1 byte values (realtime/non-realtime) */
|
||||
MIDI_SYSEX_TUNING_OCTAVE_TUNE_2BYTE = 0x09 /**< Octave tuning message using 2 byte values (realtime/non-realtime) */
|
||||
};
|
||||
|
||||
/* General MIDI sub-ID #2 */
|
||||
#define MIDI_SYSEX_GM_ON 0x01 /**< Enable GM mode */
|
||||
#define MIDI_SYSEX_GM_OFF 0x02 /**< Disable GM mode */
|
||||
#define MIDI_SYSEX_GM2_ON 0x03 /**< Enable GM2 mode */
|
||||
#define MIDI_SYSEX_GS_DT1 0x12 /**< GS DT1 command */
|
||||
|
||||
enum fluid_driver_status
|
||||
{
|
||||
FLUID_MIDI_READY,
|
||||
FLUID_MIDI_LISTENING,
|
||||
FLUID_MIDI_DONE
|
||||
};
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* TYPE DEFINITIONS & FUNCTION DECLARATIONS
|
||||
*/
|
||||
|
||||
/*
|
||||
* fluid_midi_event_t
|
||||
*/
|
||||
struct _fluid_midi_event_t
|
||||
{
|
||||
fluid_midi_event_t *next; /* Link to next event */
|
||||
void *paramptr; /* Pointer parameter (for SYSEX data), size is stored to param1, param2 indicates if pointer should be freed (dynamic if TRUE) */
|
||||
unsigned int dtime; /* Delay (ticks) between this and previous event. midi tracks. */
|
||||
unsigned int param1; /* First parameter */
|
||||
unsigned int param2; /* Second parameter */
|
||||
unsigned char type; /* MIDI event type */
|
||||
unsigned char channel; /* MIDI channel */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* fluid_track_t
|
||||
*/
|
||||
struct _fluid_track_t
|
||||
{
|
||||
char *name;
|
||||
int num;
|
||||
fluid_midi_event_t *first;
|
||||
fluid_midi_event_t *cur;
|
||||
fluid_midi_event_t *last;
|
||||
unsigned int ticks;
|
||||
};
|
||||
|
||||
typedef struct _fluid_track_t fluid_track_t;
|
||||
|
||||
#define fluid_track_eot(track) ((track)->cur == NULL)
|
||||
|
||||
|
||||
/*
|
||||
* fluid_playlist_item
|
||||
* Used as the `data' elements of the fluid_player.playlist.
|
||||
* Represents either a filename or a pre-loaded memory buffer.
|
||||
* Exactly one of `filename' and `buffer' is non-NULL.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
char *filename; /** Name of file (owned); NULL if data pre-loaded */
|
||||
void *buffer; /** The MIDI file data (owned); NULL if filename */
|
||||
size_t buffer_len; /** Number of bytes in buffer; 0 if filename */
|
||||
} fluid_playlist_item;
|
||||
|
||||
/* range of tempo values */
|
||||
#define MIN_TEMPO_VALUE (1.0f)
|
||||
#define MAX_TEMPO_VALUE (60000000.0f)
|
||||
/* range of tempo multiplier values */
|
||||
#define MIN_TEMPO_MULTIPLIER (0.001f)
|
||||
#define MAX_TEMPO_MULTIPLIER (1000.0f)
|
||||
|
||||
/*
|
||||
* fluid_player
|
||||
*/
|
||||
struct _fluid_player_t
|
||||
{
|
||||
fluid_atomic_int_t status;
|
||||
fluid_atomic_int_t stopping; /* Flag for sending all_notes_off when player is stopped */
|
||||
int ntracks;
|
||||
fluid_track_t *track[MAX_NUMBER_OF_TRACKS];
|
||||
fluid_synth_t *synth;
|
||||
fluid_timer_t *system_timer;
|
||||
fluid_sample_timer_t *sample_timer;
|
||||
|
||||
int loop; /* -1 = loop infinitely, otherwise times left to loop the playlist */
|
||||
fluid_list_t *playlist; /* List of fluid_playlist_item* objects */
|
||||
fluid_list_t *currentfile; /* points to an item in files, or NULL if not playing */
|
||||
|
||||
char use_system_timer; /* if zero, use sample timers, otherwise use system clock timer */
|
||||
char reset_synth_between_songs; /* 1 if system reset should be sent to the synth between songs. */
|
||||
fluid_atomic_int_t seek_ticks; /* new position in tempo ticks (midi ticks) for seeking */
|
||||
int start_ticks; /* the number of tempo ticks passed at the last tempo change */
|
||||
int cur_ticks; /* the number of tempo ticks passed */
|
||||
int last_callback_ticks; /* the last tick number that was passed to player->tick_callback */
|
||||
int begin_msec; /* the time (msec) of the beginning of the file */
|
||||
int start_msec; /* the start time of the last tempo change */
|
||||
int cur_msec; /* the current time */
|
||||
/* sync mode: indicates the tempo mode the player is driven by (see fluid_player_set_tempo()):
|
||||
1, the player is driven by internal tempo (miditempo). This is the default.
|
||||
0, the player is driven by external tempo (exttempo)
|
||||
*/
|
||||
int sync_mode;
|
||||
/* miditempo: internal tempo coming from MIDI file tempo change events
|
||||
(in micro seconds per quarter note)
|
||||
*/
|
||||
int miditempo; /* as indicated by MIDI SetTempo: n 24th of a usec per midi-clock. bravo! */
|
||||
/* exttempo: external tempo set by fluid_player_set_tempo() (in micro seconds per quarter note) */
|
||||
int exttempo;
|
||||
/* multempo: tempo multiplier set by fluid_player_set_tempo() */
|
||||
float multempo;
|
||||
float deltatime; /* milliseconds per midi tick. depends on current tempo mode (see sync_mode) */
|
||||
unsigned int division;
|
||||
|
||||
handle_midi_event_func_t playback_callback; /* function fired on each midi event as it is played */
|
||||
void *playback_userdata; /* pointer to user-defined data passed to playback_callback function */
|
||||
handle_midi_tick_func_t tick_callback; /* function fired on each tick change */
|
||||
void *tick_userdata; /* pointer to user-defined data passed to tick_callback function */
|
||||
|
||||
int channel_isplaying[MAX_NUMBER_OF_CHANNELS]; /* flags indicating channels on which notes have played */
|
||||
};
|
||||
|
||||
void fluid_player_settings(fluid_settings_t *settings);
|
||||
|
||||
|
||||
/*
|
||||
* fluid_midi_file
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
const char *buffer; /* Entire contents of MIDI file (borrowed) */
|
||||
int buf_len; /* Length of buffer, in bytes */
|
||||
int buf_pos; /* Current read position in contents buffer */
|
||||
int eof; /* The "end of file" condition */
|
||||
int running_status;
|
||||
int c;
|
||||
int type;
|
||||
int ntracks;
|
||||
int uses_smpte;
|
||||
unsigned int smpte_fps;
|
||||
unsigned int smpte_res;
|
||||
unsigned int division; /* If uses_SMPTE == 0 then division is
|
||||
ticks per beat (quarter-note) */
|
||||
double tempo; /* Beats per second (SI rules =) */
|
||||
int tracklen;
|
||||
int trackpos;
|
||||
int eot;
|
||||
int varlen;
|
||||
int dtime;
|
||||
} fluid_midi_file;
|
||||
|
||||
|
||||
|
||||
#define FLUID_MIDI_PARSER_MAX_DATA_SIZE 1024 /**< Maximum size of MIDI parameters/data (largest is SYSEX data) */
|
||||
|
||||
/*
|
||||
* fluid_midi_parser_t
|
||||
*/
|
||||
struct _fluid_midi_parser_t
|
||||
{
|
||||
unsigned char status; /* Identifies the type of event, that is currently received ('Noteon', 'Pitch Bend' etc). */
|
||||
unsigned char channel; /* The channel of the event that is received (in case of a channel event) */
|
||||
unsigned int nr_bytes; /* How many bytes have been read for the current event? */
|
||||
unsigned int nr_bytes_total; /* How many bytes does the current event type include? */
|
||||
unsigned char data[FLUID_MIDI_PARSER_MAX_DATA_SIZE]; /* The parameters or SYSEX data */
|
||||
fluid_midi_event_t event; /* The event, that is returned to the MIDI driver. */
|
||||
};
|
||||
|
||||
|
||||
#endif /* _FLUID_MIDI_H */
|
974
thirdparty/fluidsynth/src/midi/fluid_midi_router.c
vendored
Normal file
974
thirdparty/fluidsynth/src/midi/fluid_midi_router.c
vendored
Normal file
|
@ -0,0 +1,974 @@
|
|||
/* FluidSynth - A Software Synthesizer
|
||||
*
|
||||
* Copyright (C) 2003 Peter Hanappe and others.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation; either version 2.1 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free
|
||||
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
||||
* 02110-1301, USA
|
||||
*/
|
||||
|
||||
/* Original author: Markus Nentwig, nentwig@users.sourceforge.net
|
||||
*
|
||||
* Josh Green made it general purpose with a complete usable public API and
|
||||
* cleaned it up a bit.
|
||||
*/
|
||||
|
||||
#include "fluid_midi_router.h"
|
||||
#include "fluid_midi.h"
|
||||
#include "fluid_synth.h"
|
||||
|
||||
/*
|
||||
* fluid_midi_router
|
||||
*/
|
||||
struct _fluid_midi_router_t
|
||||
{
|
||||
fluid_mutex_t rules_mutex;
|
||||
fluid_midi_router_rule_t *rules[FLUID_MIDI_ROUTER_RULE_COUNT]; /* List of rules for each rule type */
|
||||
fluid_midi_router_rule_t *free_rules; /* List of rules to free (was waiting for final events which were received) */
|
||||
|
||||
handle_midi_event_func_t event_handler; /* Callback function for generated events */
|
||||
void *event_handler_data; /* One arg for the callback */
|
||||
|
||||
int nr_midi_channels; /* For clipping the midi channel */
|
||||
};
|
||||
|
||||
struct _fluid_midi_router_rule_t
|
||||
{
|
||||
int chan_min; /* Channel window, for which this rule is valid */
|
||||
int chan_max;
|
||||
fluid_real_t chan_mul; /* Channel multiplier (usually 0 or 1) */
|
||||
int chan_add; /* Channel offset */
|
||||
|
||||
int par1_min; /* Parameter 1 window, for which this rule is valid */
|
||||
int par1_max;
|
||||
fluid_real_t par1_mul;
|
||||
int par1_add;
|
||||
|
||||
int par2_min; /* Parameter 2 window, for which this rule is valid */
|
||||
int par2_max;
|
||||
fluid_real_t par2_mul;
|
||||
int par2_add;
|
||||
|
||||
int pending_events; /* In case of noteon: How many keys are still down? */
|
||||
char keys_cc[128]; /* Flags, whether a key is down / controller is set (sustain) */
|
||||
fluid_midi_router_rule_t *next; /* next entry */
|
||||
int waiting; /* Set to TRUE when rule has been deactivated but there are still pending_events */
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Create a new midi router.
|
||||
*
|
||||
* @param settings Settings used to configure MIDI router
|
||||
* @param handler MIDI event callback.
|
||||
* @param event_handler_data Caller defined data pointer which gets passed to 'handler'
|
||||
* @return New MIDI router instance or NULL on error
|
||||
*
|
||||
* The new router will start with default rules and therefore pass all events unmodified.
|
||||
*
|
||||
* The MIDI handler callback should process the possibly filtered/modified MIDI
|
||||
* events from the MIDI router and forward them on to a synthesizer for example.
|
||||
* The function fluid_synth_handle_midi_event() can be used for \a handle and
|
||||
* a #fluid_synth_t passed as the \a event_handler_data parameter for this purpose.
|
||||
*/
|
||||
fluid_midi_router_t *
|
||||
new_fluid_midi_router(fluid_settings_t *settings, handle_midi_event_func_t handler,
|
||||
void *event_handler_data)
|
||||
{
|
||||
fluid_midi_router_t *router = NULL;
|
||||
int i;
|
||||
|
||||
router = FLUID_NEW(fluid_midi_router_t);
|
||||
|
||||
if(router == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(router, 0, sizeof(fluid_midi_router_t));
|
||||
|
||||
/* Retrieve the number of MIDI channels for range limiting */
|
||||
fluid_settings_getint(settings, "synth.midi-channels", &router->nr_midi_channels);
|
||||
|
||||
fluid_mutex_init(router->rules_mutex);
|
||||
|
||||
router->event_handler = handler;
|
||||
router->event_handler_data = event_handler_data;
|
||||
|
||||
/* Create default routing rules which pass all events unmodified */
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
router->rules[i] = new_fluid_midi_router_rule();
|
||||
|
||||
if(!router->rules[i])
|
||||
{
|
||||
goto error_recovery;
|
||||
}
|
||||
}
|
||||
|
||||
return router;
|
||||
|
||||
error_recovery:
|
||||
delete_fluid_midi_router(router);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a MIDI router instance.
|
||||
* @param router MIDI router to delete
|
||||
* @return Returns #FLUID_OK on success, #FLUID_FAILED otherwise (only if NULL
|
||||
* \a router passed really)
|
||||
*/
|
||||
void
|
||||
delete_fluid_midi_router(fluid_midi_router_t *router)
|
||||
{
|
||||
fluid_midi_router_rule_t *rule;
|
||||
fluid_midi_router_rule_t *next_rule;
|
||||
int i;
|
||||
|
||||
fluid_return_if_fail(router != NULL);
|
||||
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
for(rule = router->rules[i]; rule; rule = next_rule)
|
||||
{
|
||||
next_rule = rule->next;
|
||||
FLUID_FREE(rule);
|
||||
}
|
||||
}
|
||||
|
||||
fluid_mutex_destroy(router->rules_mutex);
|
||||
FLUID_FREE(router);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a MIDI router to use default "unity" rules.
|
||||
*
|
||||
* @param router Router to set to default rules.
|
||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
*
|
||||
* Such a router will pass all events unmodified.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
int
|
||||
fluid_midi_router_set_default_rules(fluid_midi_router_t *router)
|
||||
{
|
||||
fluid_midi_router_rule_t *new_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
|
||||
fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
|
||||
fluid_midi_router_rule_t *rule, *next_rule, *prev_rule;
|
||||
int i, i2;
|
||||
|
||||
fluid_return_val_if_fail(router != NULL, FLUID_FAILED);
|
||||
|
||||
/* Allocate new default rules outside of lock */
|
||||
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
new_rules[i] = new_fluid_midi_router_rule();
|
||||
|
||||
if(!new_rules[i])
|
||||
{
|
||||
/* Free already allocated rules */
|
||||
for(i2 = 0; i2 < i; i2++)
|
||||
{
|
||||
delete_fluid_midi_router_rule(new_rules[i2]);
|
||||
}
|
||||
|
||||
return FLUID_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fluid_mutex_lock(router->rules_mutex); /* ++ lock */
|
||||
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
del_rules[i] = NULL;
|
||||
prev_rule = NULL;
|
||||
|
||||
/* Process existing rules */
|
||||
for(rule = router->rules[i]; rule; rule = next_rule)
|
||||
{
|
||||
next_rule = rule->next;
|
||||
|
||||
if(rule->pending_events == 0) /* Rule has no pending events? */
|
||||
{
|
||||
/* Remove rule from rule list */
|
||||
if(prev_rule)
|
||||
{
|
||||
prev_rule->next = next_rule;
|
||||
}
|
||||
else if(rule == router->rules[i])
|
||||
{
|
||||
router->rules[i] = next_rule;
|
||||
}
|
||||
|
||||
/* Prepend to delete list */
|
||||
rule->next = del_rules[i];
|
||||
del_rules[i] = rule;
|
||||
}
|
||||
else
|
||||
{
|
||||
rule->waiting = TRUE; /* Pending events, mark as waiting */
|
||||
prev_rule = rule;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prepend new default rule */
|
||||
new_rules[i]->next = router->rules[i];
|
||||
router->rules[i] = new_rules[i];
|
||||
}
|
||||
|
||||
fluid_mutex_unlock(router->rules_mutex); /* -- unlock */
|
||||
|
||||
|
||||
/* Free old rules outside of lock */
|
||||
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
for(rule = del_rules[i]; rule; rule = next_rule)
|
||||
{
|
||||
next_rule = rule->next;
|
||||
FLUID_FREE(rule);
|
||||
}
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all rules in a MIDI router.
|
||||
*
|
||||
* @param router Router to clear all rules from
|
||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
*
|
||||
* An empty router will drop all events until rules are added.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
int
|
||||
fluid_midi_router_clear_rules(fluid_midi_router_t *router)
|
||||
{
|
||||
fluid_midi_router_rule_t *del_rules[FLUID_MIDI_ROUTER_RULE_COUNT];
|
||||
fluid_midi_router_rule_t *rule, *next_rule, *prev_rule;
|
||||
int i;
|
||||
|
||||
fluid_return_val_if_fail(router != NULL, FLUID_FAILED);
|
||||
|
||||
fluid_mutex_lock(router->rules_mutex); /* ++ lock */
|
||||
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
del_rules[i] = NULL;
|
||||
prev_rule = NULL;
|
||||
|
||||
/* Process existing rules */
|
||||
for(rule = router->rules[i]; rule; rule = next_rule)
|
||||
{
|
||||
next_rule = rule->next;
|
||||
|
||||
if(rule->pending_events == 0) /* Rule has no pending events? */
|
||||
{
|
||||
/* Remove rule from rule list */
|
||||
if(prev_rule)
|
||||
{
|
||||
prev_rule->next = next_rule;
|
||||
}
|
||||
else if(rule == router->rules[i])
|
||||
{
|
||||
router->rules[i] = next_rule;
|
||||
}
|
||||
|
||||
/* Prepend to delete list */
|
||||
rule->next = del_rules[i];
|
||||
del_rules[i] = rule;
|
||||
}
|
||||
else
|
||||
{
|
||||
rule->waiting = TRUE; /* Pending events, mark as waiting */
|
||||
prev_rule = rule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock(router->rules_mutex); /* -- unlock */
|
||||
|
||||
|
||||
/* Free old rules outside of lock */
|
||||
|
||||
for(i = 0; i < FLUID_MIDI_ROUTER_RULE_COUNT; i++)
|
||||
{
|
||||
for(rule = del_rules[i]; rule; rule = next_rule)
|
||||
{
|
||||
next_rule = rule->next;
|
||||
FLUID_FREE(rule);
|
||||
}
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a rule to a MIDI router.
|
||||
* @param router MIDI router
|
||||
* @param rule Rule to add (used directly and should not be accessed again following a
|
||||
* successful call to this function).
|
||||
* @param type The type of rule to add (#fluid_midi_router_rule_type)
|
||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise (invalid rule for example)
|
||||
* @since 1.1.0
|
||||
*/
|
||||
int
|
||||
fluid_midi_router_add_rule(fluid_midi_router_t *router, fluid_midi_router_rule_t *rule,
|
||||
int type)
|
||||
{
|
||||
fluid_midi_router_rule_t *free_rules, *next_rule;
|
||||
|
||||
fluid_return_val_if_fail(router != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(rule != NULL, FLUID_FAILED);
|
||||
fluid_return_val_if_fail(type >= 0 && type < FLUID_MIDI_ROUTER_RULE_COUNT, FLUID_FAILED);
|
||||
|
||||
|
||||
fluid_mutex_lock(router->rules_mutex); /* ++ lock */
|
||||
|
||||
/* Take over free rules list, if any (to free outside of lock) */
|
||||
free_rules = router->free_rules;
|
||||
router->free_rules = NULL;
|
||||
|
||||
rule->next = router->rules[type];
|
||||
router->rules[type] = rule;
|
||||
|
||||
fluid_mutex_unlock(router->rules_mutex); /* -- unlock */
|
||||
|
||||
|
||||
/* Free any deactivated rules which were waiting for events and are now done */
|
||||
|
||||
for(; free_rules; free_rules = next_rule)
|
||||
{
|
||||
next_rule = free_rules->next;
|
||||
FLUID_FREE(free_rules);
|
||||
}
|
||||
|
||||
return FLUID_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new MIDI router rule.
|
||||
*
|
||||
* @return Newly allocated router rule or NULL if out of memory.
|
||||
*
|
||||
* The new rule is a "unity" rule which will accept any values and wont modify
|
||||
* them.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
fluid_midi_router_rule_t *
|
||||
new_fluid_midi_router_rule(void)
|
||||
{
|
||||
fluid_midi_router_rule_t *rule;
|
||||
|
||||
rule = FLUID_NEW(fluid_midi_router_rule_t);
|
||||
|
||||
if(rule == NULL)
|
||||
{
|
||||
FLUID_LOG(FLUID_ERR, "Out of memory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FLUID_MEMSET(rule, 0, sizeof(fluid_midi_router_rule_t));
|
||||
|
||||
rule->chan_min = 0;
|
||||
rule->chan_max = 999999;
|
||||
rule->chan_mul = 1.0;
|
||||
rule->chan_add = 0;
|
||||
rule->par1_min = 0;
|
||||
rule->par1_max = 999999;
|
||||
rule->par1_mul = 1.0;
|
||||
rule->par1_add = 0;
|
||||
rule->par2_min = 0;
|
||||
rule->par2_max = 999999;
|
||||
rule->par2_mul = 1.0;
|
||||
rule->par2_add = 0;
|
||||
|
||||
return rule;
|
||||
};
|
||||
|
||||
/**
|
||||
* Free a MIDI router rule.
|
||||
*
|
||||
* @param rule Router rule to free
|
||||
*
|
||||
* Note that rules which have been added to a router are managed by the router,
|
||||
* so this function should seldom be needed.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
void
|
||||
delete_fluid_midi_router_rule(fluid_midi_router_rule_t *rule)
|
||||
{
|
||||
fluid_return_if_fail(rule != NULL);
|
||||
FLUID_FREE(rule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel portion of a rule.
|
||||
*
|
||||
* @param rule MIDI router rule
|
||||
* @param min Minimum value for rule match
|
||||
* @param max Maximum value for rule match
|
||||
* @param mul Value which is multiplied by matching event's channel value (1.0 to not modify)
|
||||
* @param add Value which is added to matching event's channel value (0 to not modify)
|
||||
*
|
||||
* The \a min and \a max parameters define a channel range window to match
|
||||
* incoming events to. If \a min is less than or equal to \a max then an event
|
||||
* is matched if its channel is within the defined range (including \a min
|
||||
* and \a max). If \a min is greater than \a max then rule is inverted and matches
|
||||
* everything except in *between* the defined range (so \a min and \a max would match).
|
||||
*
|
||||
* The \a mul and \a add values are used to modify event channel values prior to
|
||||
* sending the event, if the rule matches.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
void
|
||||
fluid_midi_router_rule_set_chan(fluid_midi_router_rule_t *rule, int min, int max,
|
||||
float mul, int add)
|
||||
{
|
||||
fluid_return_if_fail(rule != NULL);
|
||||
rule->chan_min = min;
|
||||
rule->chan_max = max;
|
||||
rule->chan_mul = mul;
|
||||
rule->chan_add = add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the first parameter portion of a rule.
|
||||
*
|
||||
* @param rule MIDI router rule
|
||||
* @param min Minimum value for rule match
|
||||
* @param max Maximum value for rule match
|
||||
* @param mul Value which is multiplied by matching event's 1st parameter value (1.0 to not modify)
|
||||
* @param add Value which is added to matching event's 1st parameter value (0 to not modify)
|
||||
*
|
||||
* The 1st parameter of an event depends on the type of event. For note events
|
||||
* its the MIDI note #, for CC events its the MIDI control number, for program
|
||||
* change events its the MIDI program #, for pitch bend events its the bend value,
|
||||
* for channel pressure its the channel pressure value and for key pressure
|
||||
* its the MIDI note number.
|
||||
*
|
||||
* Pitch bend values have a maximum value of 16383 (8192 is pitch bend center) and all
|
||||
* other events have a max of 127. All events have a minimum value of 0.
|
||||
*
|
||||
* The \a min and \a max parameters define a parameter range window to match
|
||||
* incoming events to. If \a min is less than or equal to \a max then an event
|
||||
* is matched if its 1st parameter is within the defined range (including \a min
|
||||
* and \a max). If \a min is greater than \a max then rule is inverted and matches
|
||||
* everything except in *between* the defined range (so \a min and \a max would match).
|
||||
*
|
||||
* The \a mul and \a add values are used to modify event 1st parameter values prior to
|
||||
* sending the event, if the rule matches.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
void
|
||||
fluid_midi_router_rule_set_param1(fluid_midi_router_rule_t *rule, int min, int max,
|
||||
float mul, int add)
|
||||
{
|
||||
fluid_return_if_fail(rule != NULL);
|
||||
rule->par1_min = min;
|
||||
rule->par1_max = max;
|
||||
rule->par1_mul = mul;
|
||||
rule->par1_add = add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the second parameter portion of a rule.
|
||||
*
|
||||
* @param rule MIDI router rule
|
||||
* @param min Minimum value for rule match
|
||||
* @param max Maximum value for rule match
|
||||
* @param mul Value which is multiplied by matching event's 2nd parameter value (1.0 to not modify)
|
||||
* @param add Value which is added to matching event's 2nd parameter value (0 to not modify)
|
||||
*
|
||||
* The 2nd parameter of an event depends on the type of event. For note events
|
||||
* its the MIDI velocity, for CC events its the control value and for key pressure
|
||||
* events its the key pressure value. All other types lack a 2nd parameter.
|
||||
*
|
||||
* All applicable 2nd parameters have the range 0-127.
|
||||
*
|
||||
* The \a min and \a max parameters define a parameter range window to match
|
||||
* incoming events to. If \a min is less than or equal to \a max then an event
|
||||
* is matched if its 2nd parameter is within the defined range (including \a min
|
||||
* and \a max). If \a min is greater than \a max then rule is inverted and matches
|
||||
* everything except in *between* the defined range (so \a min and \a max would match).
|
||||
*
|
||||
* The \a mul and \a add values are used to modify event 2nd parameter values prior to
|
||||
* sending the event, if the rule matches.
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
void
|
||||
fluid_midi_router_rule_set_param2(fluid_midi_router_rule_t *rule, int min, int max,
|
||||
float mul, int add)
|
||||
{
|
||||
fluid_return_if_fail(rule != NULL);
|
||||
rule->par2_min = min;
|
||||
rule->par2_max = max;
|
||||
rule->par2_mul = mul;
|
||||
rule->par2_add = add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a MIDI event through a MIDI router instance.
|
||||
* @param data MIDI router instance #fluid_midi_router_t, its a void * so that
|
||||
* this function can be used as a callback for other subsystems
|
||||
* (new_fluid_midi_driver() for example).
|
||||
* @param event MIDI event to handle
|
||||
* @return #FLUID_OK if all rules were applied successfully, #FLUID_FAILED if
|
||||
* an error occurred while applying a rule or (since 2.2.2) the event was
|
||||
* ignored because a parameter was out-of-range after the rule had been applied.
|
||||
* See the note below.
|
||||
*
|
||||
* Purpose: The midi router is called for each event, that is received
|
||||
* via the 'physical' midi input. Each event can trigger an arbitrary number
|
||||
* of generated events (one for each rule that matches).
|
||||
*
|
||||
* In default mode, a noteon event is just forwarded to the synth's 'noteon' function,
|
||||
* a 'CC' event to the synth's 'CC' function and so on.
|
||||
*
|
||||
* The router can be used to:
|
||||
* - filter messages (for example: Pass sustain pedal CCs only to selected channels)
|
||||
* - split the keyboard (noteon with notenr < x: to ch 1, >x to ch 2)
|
||||
* - layer sounds (for each noteon received on ch 1, create a noteon on ch1, ch2, ch3,...)
|
||||
* - velocity scaling (for each noteon event, scale the velocity by 1.27 to give DX7 users
|
||||
* a chance)
|
||||
* - velocity switching ("v <=100: Angel Choir; V > 100: Hell's Bells")
|
||||
* - get rid of aftertouch
|
||||
* - ...
|
||||
*
|
||||
* @note Each input event has values (ch, par1, par2) that could be changed by a rule.
|
||||
* After a rule has been applied on any value and the value is out of range, the event
|
||||
* can be either ignored or the value can be clamped depending on the type of the event:
|
||||
* - To get full benefice of the rule the value is clamped and the event passed to the output.
|
||||
* - To avoid MIDI messages conflicts at the output, the event is ignored
|
||||
* (i.e not passed to the output).
|
||||
* - ch out of range: event is ignored regardless of the event type.
|
||||
* - par1 out of range: event is ignored for PROG_CHANGE or CONTROL_CHANGE type,
|
||||
* par1 is clamped otherwise.
|
||||
* - par2 out of range: par2 is clamped regardless of the event type.
|
||||
*/
|
||||
int
|
||||
fluid_midi_router_handle_midi_event(void *data, fluid_midi_event_t *event)
|
||||
{
|
||||
fluid_midi_router_t *router = (fluid_midi_router_t *)data;
|
||||
fluid_midi_router_rule_t **rulep, *rule, *next_rule, *prev_rule = NULL;
|
||||
int event_has_par2 = 0; /* Flag, indicates that current event needs two parameters */
|
||||
int is_par1_ignored = 0; /* Flag, indicates that current event should be
|
||||
ignored/clamped when par1 is getting out of range
|
||||
value after the rule had been applied:1:ignored, 0:clamped */
|
||||
int par1_max = 127; /* Range limit for par1 */
|
||||
int par2_max = 127; /* Range limit for par2 */
|
||||
int ret_val = FLUID_OK;
|
||||
|
||||
int chan; /* Channel of the generated event */
|
||||
int par1; /* par1 of the generated event */
|
||||
int par2;
|
||||
int event_par1;
|
||||
int event_par2;
|
||||
fluid_midi_event_t new_event;
|
||||
|
||||
/* Some keyboards report noteoff through a noteon event with vel=0.
|
||||
* Convert those to noteoff to ease processing. */
|
||||
if(event->type == NOTE_ON && event->param2 == 0)
|
||||
{
|
||||
event->type = NOTE_OFF;
|
||||
event->param2 = 127; /* Release velocity */
|
||||
}
|
||||
|
||||
fluid_mutex_lock(router->rules_mutex); /* ++ lock rules */
|
||||
|
||||
/* Depending on the event type, choose the correct list of rules. */
|
||||
switch(event->type)
|
||||
{
|
||||
/* For NOTE_ON event, par1(pitch) and par2(velocity) will be clamped if
|
||||
they are out of range after the rule had been applied */
|
||||
case NOTE_ON:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE];
|
||||
event_has_par2 = 1;
|
||||
break;
|
||||
|
||||
/* For NOTE_OFF event, par1(pitch) and par2(velocity) will be clamped if
|
||||
they are out of range after the rule had been applied */
|
||||
case NOTE_OFF:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_NOTE];
|
||||
event_has_par2 = 1;
|
||||
break;
|
||||
|
||||
/* CONTROL_CHANGE event will be ignored if par1 (ctrl num) is out
|
||||
of range after the rule had been applied */
|
||||
case CONTROL_CHANGE:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CC];
|
||||
event_has_par2 = 1;
|
||||
is_par1_ignored = 1;
|
||||
break;
|
||||
|
||||
/* PROGRAM_CHANGE event will be ignored if par1 (program num) is out
|
||||
of range after the rule had been applied */
|
||||
case PROGRAM_CHANGE:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PROG_CHANGE];
|
||||
is_par1_ignored = 1;
|
||||
break;
|
||||
|
||||
/* For PITCH_BEND event, par1(bend value) will be clamped if
|
||||
it is out of range after the rule had been applied */
|
||||
case PITCH_BEND:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_PITCH_BEND];
|
||||
par1_max = 16383;
|
||||
break;
|
||||
|
||||
/* For CHANNEL_PRESSURE event, par1(pressure value) will be clamped if
|
||||
it is out of range after the rule had been applied */
|
||||
case CHANNEL_PRESSURE:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_CHANNEL_PRESSURE];
|
||||
break;
|
||||
|
||||
/* For KEY_PRESSURE event, par1(pitch) and par2(pressure value) will be
|
||||
clamped if they are out of range after the rule had been applied */
|
||||
case KEY_PRESSURE:
|
||||
rulep = &router->rules[FLUID_MIDI_ROUTER_RULE_KEY_PRESSURE];
|
||||
event_has_par2 = 1;
|
||||
break;
|
||||
|
||||
case MIDI_SYSTEM_RESET:
|
||||
case MIDI_SYSEX:
|
||||
ret_val = router->event_handler(router->event_handler_data, event);
|
||||
fluid_mutex_unlock(router->rules_mutex); /* -- unlock rules */
|
||||
return ret_val;
|
||||
|
||||
default:
|
||||
rulep = NULL; /* Event will not be passed on */
|
||||
break;
|
||||
}
|
||||
|
||||
/* Loop over rules in the list, looking for matches for this event. */
|
||||
for(rule = rulep ? *rulep : NULL; rule; prev_rule = rule, rule = next_rule)
|
||||
{
|
||||
event_par1 = (int)event->param1;
|
||||
event_par2 = (int)event->param2;
|
||||
next_rule = rule->next; /* Rule may get removed from list, so get next here */
|
||||
|
||||
/* Channel window */
|
||||
if(rule->chan_min > rule->chan_max)
|
||||
{
|
||||
/* Inverted rule: Exclude everything between max and min (but not min/max) */
|
||||
if(event->channel > rule->chan_max && event->channel < rule->chan_min)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else /* Normal rule: Exclude everything < max or > min (but not min/max) */
|
||||
{
|
||||
if(event->channel > rule->chan_max || event->channel < rule->chan_min)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Par 1 window */
|
||||
if(rule->par1_min > rule->par1_max)
|
||||
{
|
||||
/* Inverted rule: Exclude everything between max and min (but not min/max) */
|
||||
if(event_par1 > rule->par1_max && event_par1 < rule->par1_min)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else /* Normal rule: Exclude everything < max or > min (but not min/max)*/
|
||||
{
|
||||
if(event_par1 > rule->par1_max || event_par1 < rule->par1_min)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Par 2 window (only applies to event types, which have 2 pars)
|
||||
* For noteoff events, velocity switching doesn't make any sense.
|
||||
* Velocity scaling might be useful, though.
|
||||
*/
|
||||
if(event_has_par2 && event->type != NOTE_OFF)
|
||||
{
|
||||
if(rule->par2_min > rule->par2_max)
|
||||
{
|
||||
/* Inverted rule: Exclude everything between max and min (but not min/max) */
|
||||
if(event_par2 > rule->par2_max && event_par2 < rule->par2_min)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else /* Normal rule: Exclude everything < max or > min (but not min/max)*/
|
||||
{
|
||||
if(event_par2 > rule->par2_max || event_par2 < rule->par2_min)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Channel scaling / offset
|
||||
* Note: rule->chan_mul will probably be 0 or 1. If it's 0, input from all
|
||||
* input channels is mapped to the same synth channel.
|
||||
*/
|
||||
chan = rule->chan_add + (int)((fluid_real_t)event->channel * rule->chan_mul
|
||||
+ (fluid_real_t)0.5);
|
||||
|
||||
/* We ignore the event if chan is out of range */
|
||||
if((chan < 0) || (chan >= router->nr_midi_channels))
|
||||
{
|
||||
ret_val = FLUID_FAILED;
|
||||
continue; /* go to next rule */
|
||||
}
|
||||
|
||||
/* par 1 scaling / offset */
|
||||
par1 = rule->par1_add + (int)((fluid_real_t)event_par1 * rule->par1_mul
|
||||
+ (fluid_real_t)0.5);
|
||||
|
||||
if(is_par1_ignored)
|
||||
{
|
||||
/* We ignore the event if par1 is out of range */
|
||||
if((par1 < 0) || (par1 > par1_max))
|
||||
{
|
||||
ret_val = FLUID_FAILED;
|
||||
continue; /* go to next rule */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* par1 range clamping */
|
||||
if(par1 < 0)
|
||||
{
|
||||
par1 = 0;
|
||||
}
|
||||
else if(par1 > par1_max)
|
||||
{
|
||||
par1 = par1_max;
|
||||
}
|
||||
}
|
||||
|
||||
/* par 2 scaling / offset, if applicable */
|
||||
if(event_has_par2)
|
||||
{
|
||||
par2 = rule->par2_add + (int)((fluid_real_t)event_par2 * rule->par2_mul
|
||||
+ (fluid_real_t)0.5);
|
||||
|
||||
/* par2 range clamping */
|
||||
if(par2 < 0)
|
||||
{
|
||||
par2 = 0;
|
||||
}
|
||||
else if(par2 > par2_max)
|
||||
{
|
||||
par2 = par2_max;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
par2 = 0;
|
||||
}
|
||||
|
||||
/* At this point we have to create an event of event->type on 'chan' with par1 (maybe par2).
|
||||
* We keep track on the state of noteon and sustain pedal events. If the application tries
|
||||
* to delete a rule, it will only be fully removed, if pending noteoff / pedal off events have
|
||||
* arrived. In the meantime while waiting, it will only let through 'negative' events
|
||||
* (noteoff or pedal up).
|
||||
*/
|
||||
if(event->type == NOTE_ON || (event->type == CONTROL_CHANGE
|
||||
&& par1 == SUSTAIN_SWITCH && par2 >= 64))
|
||||
{
|
||||
/* Noteon or sustain pedal down event generated */
|
||||
if(rule->keys_cc[par1] == 0)
|
||||
{
|
||||
rule->keys_cc[par1] = 1;
|
||||
rule->pending_events++;
|
||||
}
|
||||
}
|
||||
else if(event->type == NOTE_OFF || (event->type == CONTROL_CHANGE
|
||||
&& par1 == SUSTAIN_SWITCH && par2 < 64))
|
||||
{
|
||||
/* Noteoff or sustain pedal up event generated */
|
||||
if(rule->keys_cc[par1] > 0)
|
||||
{
|
||||
rule->keys_cc[par1] = 0;
|
||||
rule->pending_events--;
|
||||
|
||||
/* Rule is waiting for negative event to be destroyed? */
|
||||
if(rule->waiting)
|
||||
{
|
||||
if(rule->pending_events == 0)
|
||||
{
|
||||
/* Remove rule from rule list */
|
||||
if(prev_rule)
|
||||
{
|
||||
prev_rule->next = next_rule;
|
||||
}
|
||||
else
|
||||
{
|
||||
*rulep = next_rule;
|
||||
}
|
||||
|
||||
/* Add to free list */
|
||||
rule->next = router->free_rules;
|
||||
router->free_rules = rule;
|
||||
|
||||
rule = prev_rule; /* Set rule to previous rule, which gets assigned to the next prev_rule value (in for() statement) */
|
||||
}
|
||||
|
||||
goto send_event; /* Pass the event to complete the cycle */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Rule is still waiting for negative event? (note off or pedal up) */
|
||||
if(rule->waiting)
|
||||
{
|
||||
continue; /* Skip (rule is inactive except for matching negative event) */
|
||||
}
|
||||
|
||||
send_event:
|
||||
|
||||
/* At this point it is decided, what is sent to the synth.
|
||||
* Create a new event and make the appropriate call */
|
||||
|
||||
fluid_midi_event_set_type(&new_event, event->type);
|
||||
fluid_midi_event_set_channel(&new_event, chan);
|
||||
new_event.param1 = par1;
|
||||
new_event.param2 = par2;
|
||||
|
||||
/* On failure, continue to process events, but return failure to caller. */
|
||||
if(router->event_handler(router->event_handler_data, &new_event) != FLUID_OK)
|
||||
{
|
||||
ret_val = FLUID_FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
fluid_mutex_unlock(router->rules_mutex); /* -- unlock rules */
|
||||
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
/**
|
||||
* MIDI event callback function to display event information to stdout
|
||||
* @param data MIDI router instance
|
||||
* @param event MIDI event data
|
||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
*
|
||||
* An implementation of the #handle_midi_event_func_t function type, used for
|
||||
* displaying MIDI event information between the MIDI driver and router to
|
||||
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
|
||||
*/
|
||||
int fluid_midi_dump_prerouter(void *data, fluid_midi_event_t *event)
|
||||
{
|
||||
switch(event->type)
|
||||
{
|
||||
case NOTE_ON:
|
||||
fprintf(stdout, "event_pre_noteon %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
case NOTE_OFF:
|
||||
fprintf(stdout, "event_pre_noteoff %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
case CONTROL_CHANGE:
|
||||
fprintf(stdout, "event_pre_cc %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
fprintf(stdout, "event_pre_prog %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
|
||||
case PITCH_BEND:
|
||||
fprintf(stdout, "event_pre_pitch %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
|
||||
case CHANNEL_PRESSURE:
|
||||
fprintf(stdout, "event_pre_cpress %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
|
||||
case KEY_PRESSURE:
|
||||
fprintf(stdout, "event_pre_kpress %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return fluid_midi_router_handle_midi_event((fluid_midi_router_t *) data, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* MIDI event callback function to display event information to stdout
|
||||
* @param data MIDI router instance
|
||||
* @param event MIDI event data
|
||||
* @return #FLUID_OK on success, #FLUID_FAILED otherwise
|
||||
*
|
||||
* An implementation of the #handle_midi_event_func_t function type, used for
|
||||
* displaying MIDI event information between the MIDI driver and router to
|
||||
* stdout. Useful for adding into a MIDI router chain for debugging MIDI events.
|
||||
*/
|
||||
int fluid_midi_dump_postrouter(void *data, fluid_midi_event_t *event)
|
||||
{
|
||||
switch(event->type)
|
||||
{
|
||||
case NOTE_ON:
|
||||
fprintf(stdout, "event_post_noteon %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
case NOTE_OFF:
|
||||
fprintf(stdout, "event_post_noteoff %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
case CONTROL_CHANGE:
|
||||
fprintf(stdout, "event_post_cc %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
case PROGRAM_CHANGE:
|
||||
fprintf(stdout, "event_post_prog %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
|
||||
case PITCH_BEND:
|
||||
fprintf(stdout, "event_post_pitch %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
|
||||
case CHANNEL_PRESSURE:
|
||||
fprintf(stdout, "event_post_cpress %i %i\n", event->channel, event->param1);
|
||||
break;
|
||||
|
||||
case KEY_PRESSURE:
|
||||
fprintf(stdout, "event_post_kpress %i %i %i\n",
|
||||
event->channel, event->param1, event->param2);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return fluid_synth_handle_midi_event((fluid_synth_t *) data, event);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue