mirror of
https://github.com/ZDoom/ZMusic.git
synced 2025-04-07 01:42:11 +00:00
Compare commits
79 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 | ||
|
6da5525ba8 | ||
|
304de9b0aa | ||
|
c5b6c0d317 | ||
|
9fbc2ec095 | ||
|
ad00418fec | ||
|
a3b79ca8f6 | ||
|
f4cfb36f4a | ||
|
6b5aebf6a3 | ||
|
8375c06737 | ||
|
5ac16461ad | ||
|
592bb9126b | ||
|
ae70ea40f2 | ||
|
db05f4a8ef | ||
|
3696d8fa27 | ||
|
dd76ab1fce | ||
|
d8e6e28879 | ||
|
95e6bfcd8c | ||
|
514ef6b528 | ||
|
fee3bc352e | ||
|
2b291705f2 | ||
|
0ee7aa9a5b | ||
|
69692696ec | ||
|
2cae98b442 | ||
|
74ff273a3d | ||
|
0c2ac8cbf3 | ||
|
e79fdcef2c | ||
|
0f1d954646 | ||
|
e598ab7f1c | ||
|
ba9e9da6e6 | ||
|
a192e66049 | ||
|
f24498950d | ||
|
6bcbc7aeb5 | ||
|
4c223a7de7 | ||
|
ecad4aaf06 |
397 changed files with 141973 additions and 28306 deletions
96
.github/workflows/continuous_integration.yml
vendored
96
.github/workflows/continuous_integration.yml
vendored
|
@ -10,62 +10,65 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
config:
|
||||
- {
|
||||
name: "Visual Studio 64-bit",
|
||||
os: windows-latest,
|
||||
build_type: "Release",
|
||||
extra_options: "-A x64"
|
||||
}
|
||||
- {
|
||||
name: "Visual Studio 32-bit",
|
||||
os: windows-latest,
|
||||
build_type: "Release",
|
||||
extra_options: "-A Win32 -DFORCE_INTERNAL_ZLIB=ON"
|
||||
}
|
||||
- {
|
||||
name: "macOS Clang",
|
||||
os: macos-latest,
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Linux GCC",
|
||||
os: ubuntu-latest,
|
||||
build_type: "Release"
|
||||
}
|
||||
- {
|
||||
name: "Linux Clang",
|
||||
os: ubuntu-latest,
|
||||
build_type: "Release",
|
||||
extra_options: "-DCMAKE_C_COMPILER=/usr/bin/clang -DCMAKE_CXX_COMPILER=/usr/bin/clang++"
|
||||
}
|
||||
- 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
|
||||
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
|
||||
|
@ -74,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}
|
||||
|
@ -85,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.4
|
||||
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)
|
||||
|
@ -12,12 +27,28 @@ include(ZUtility)
|
|||
|
||||
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
|
||||
|
||||
# If building standalone give the user the option to build shared or static.
|
||||
# Otherwise the vendoring project should set the variable.
|
||||
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
# This project is being built standalone
|
||||
|
||||
# Give user option to build shared or static
|
||||
option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
elseif(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
|
||||
# Enable install rules
|
||||
set(ZMUSIC_INSTALL ON)
|
||||
else()
|
||||
# This project is being vendored by another project, set option default if
|
||||
# the parent project doesn't provide them.
|
||||
|
||||
if(NOT DEFINED BUILD_SHARED_LIBS)
|
||||
set(BUILD_SHARED_LIBS ON)
|
||||
endif()
|
||||
|
||||
# Although install rules can be avoided with EXCLUDE_FROM_ALL on
|
||||
# add_subdirectory, the EXPORT rules may place certain usage requirements on
|
||||
# targets shared between the two projects.
|
||||
if(NOT DEFINED ZMUSIC_INSTALL)
|
||||
set(ZMUSIC_INSTALL OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CMAKE_BUILD_TYPE)
|
||||
|
@ -97,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)
|
||||
|
||||
|
@ -110,10 +146,12 @@ configure_package_config_file(
|
|||
${CMAKE_CURRENT_BINARY_DIR}/ZMusicConfig.cmake
|
||||
INSTALL_DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake
|
||||
)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ZMusicConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/ZMusicConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ZMusic
|
||||
COMPONENT devel
|
||||
)
|
||||
if(ZMUSIC_INSTALL)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ZMusicConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/ZMusicConfigVersion.cmake
|
||||
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ZMusic
|
||||
COMPONENT devel
|
||||
)
|
||||
endif()
|
||||
|
||||
if(PROJECT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
|
||||
set(CPACK_PACKAGE_CONTACT "First Last <example@example.com>" CACHE STRING "Contact info for archive maintainer.")
|
||||
|
|
|
@ -9,8 +9,8 @@ Compile instructions are pretty simple for most systems.
|
|||
git clone https://github.com/coelckers/ZMusic.git
|
||||
mkdir ZMusic/build
|
||||
cd ZMusic/build
|
||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
||||
cmake . --build
|
||||
cmake -DCMAKE_BUILD_TYPE=Release ..
|
||||
cmake --build .
|
||||
```
|
||||
|
||||
On Unix/Linux you may also supply `sudo make install` in the build folder to push the compiled library directly into the file system so that it can be found by the previously mentioned projects.
|
||||
|
|
|
@ -27,7 +27,7 @@ include(FindPackageHandleStandardArgs)
|
|||
find_package_handle_standard_args(SndFile DEFAULT_MSG SNDFILE_LIBRARY SNDFILE_INCLUDE_DIR)
|
||||
|
||||
if(SNDFILE_FOUND)
|
||||
add_library(sndfile UNKNOWN IMPORTED)
|
||||
add_library(sndfile UNKNOWN IMPORTED GLOBAL)
|
||||
set_target_properties(sndfile
|
||||
PROPERTIES
|
||||
IMPORTED_LOCATION "${SNDFILE_LIBRARY}"
|
||||
|
|
|
@ -120,10 +120,18 @@ function(require_strnicmp Tgt Visibility)
|
|||
endif()
|
||||
endfunction()
|
||||
|
||||
function(use_fast_math Tgt)
|
||||
if(MSVC)
|
||||
set_property( TARGET "${Tgt}" APPEND PROPERTY COMPILE_OPTIONS "/fp:fast" )
|
||||
elseif(ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE)
|
||||
set_property( TARGET "${Tgt}" APPEND PROPERTY COMPILE_OPTIONS "-ffast-math" "-ffp-contract=fast" )
|
||||
endif()
|
||||
function(use_fast_math)
|
||||
foreach(Tgt IN LISTS ARGN)
|
||||
if(TARGET Tgt)
|
||||
set(TgtType TARGET)
|
||||
else()
|
||||
set(TgtType SOURCE)
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
set_property("${TgtType}" "${Tgt}" APPEND PROPERTY COMPILE_OPTIONS "/fp:fast")
|
||||
elseif(COMPILER_IS_GNUCXX_COMPATIBLE)
|
||||
set_property("${TgtType}" "${Tgt}" APPEND PROPERTY COMPILE_OPTIONS "-ffast-math" "-ffp-contract=fast")
|
||||
endif()
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
|
|
@ -67,7 +67,8 @@ typedef struct SoundStreamInfo_
|
|||
typedef enum SampleType_
|
||||
{
|
||||
SampleType_UInt8,
|
||||
SampleType_Int16
|
||||
SampleType_Int16,
|
||||
SampleType_Float32
|
||||
} SampleType;
|
||||
|
||||
typedef enum ChannelConfig_
|
||||
|
@ -76,6 +77,15 @@ typedef enum ChannelConfig_
|
|||
ChannelConfig_Stereo
|
||||
} ChannelConfig;
|
||||
|
||||
typedef struct SoundStreamInfoEx_
|
||||
{
|
||||
int mBufferSize; // If mBufferSize is 0, the song doesn't use streaming but plays through a different interface.
|
||||
int mSampleRate;
|
||||
SampleType mSampleType;
|
||||
ChannelConfig mChannelConfig;
|
||||
} SoundStreamInfoEx;
|
||||
|
||||
|
||||
typedef enum EIntConfigKey_
|
||||
{
|
||||
zmusic_adl_chips_count,
|
||||
|
@ -141,6 +151,7 @@ typedef enum EIntConfigKey_
|
|||
|
||||
zmusic_snd_mididevice,
|
||||
zmusic_snd_outputrate,
|
||||
zmusic_mod_preferredplayer,
|
||||
|
||||
NUM_ZMUSIC_INT_CONFIGS
|
||||
} EIntConfigKey;
|
||||
|
@ -264,14 +275,14 @@ typedef struct ZMusicConfigurationSetting_
|
|||
|
||||
|
||||
#ifndef ZMUSIC_INTERNAL
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(ZMUSIC_STATIC)
|
||||
#define DLL_IMPORT _declspec(dllimport)
|
||||
#else // !_MSC_VER
|
||||
#else
|
||||
#define DLL_IMPORT
|
||||
#endif // _MSC_VER
|
||||
#endif
|
||||
// Note that the internal 'class' definitions are not C compatible!
|
||||
typedef struct { int zm1; } *ZMusic_MidiSource;
|
||||
typedef struct { int zm2; } *ZMusic_MusicStream;
|
||||
typedef struct _ZMusic_MidiSource_Struct { int zm1; } *ZMusic_MidiSource;
|
||||
typedef struct _ZMusic_MusicStream_Struct { int zm2; } *ZMusic_MusicStream;
|
||||
struct SoundDecoder;
|
||||
#endif
|
||||
|
||||
|
@ -314,10 +325,12 @@ extern "C"
|
|||
DLL_IMPORT void ZMusic_Close(ZMusic_MusicStream song);
|
||||
DLL_IMPORT zmusic_bool ZMusic_SetSubsong(ZMusic_MusicStream song, int subsong);
|
||||
DLL_IMPORT zmusic_bool ZMusic_IsLooping(ZMusic_MusicStream song);
|
||||
DLL_IMPORT int ZMusic_GetDeviceType(ZMusic_MusicStream song);
|
||||
DLL_IMPORT zmusic_bool ZMusic_IsMIDI(ZMusic_MusicStream song);
|
||||
DLL_IMPORT void ZMusic_VolumeChanged(ZMusic_MusicStream song);
|
||||
DLL_IMPORT zmusic_bool ZMusic_WriteSMF(ZMusic_MidiSource source, const char* fn, int looplimit);
|
||||
DLL_IMPORT void ZMusic_GetStreamInfo(ZMusic_MusicStream song, SoundStreamInfo *info);
|
||||
DLL_IMPORT void ZMusic_GetStreamInfoEx(ZMusic_MusicStream song, SoundStreamInfoEx *info);
|
||||
// Configuration interface. The return value specifies if a music restart is needed.
|
||||
// RealValue should be written back to the CVAR or whatever other method the client uses to store configuration state.
|
||||
DLL_IMPORT zmusic_bool ChangeMusicSettingInt(EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue);
|
||||
|
@ -405,6 +418,7 @@ typedef zmusic_bool (*pfn_ZMusic_IsMIDI)(ZMusic_MusicStream song);
|
|||
typedef void (*pfn_ZMusic_VolumeChanged)(ZMusic_MusicStream song);
|
||||
typedef zmusic_bool (*pfn_ZMusic_WriteSMF)(ZMusic_MidiSource source, const char* fn, int looplimit);
|
||||
typedef void (*pfn_ZMusic_GetStreamInfo)(ZMusic_MusicStream song, SoundStreamInfo *info);
|
||||
typedef void (*pfn_ZMusic_GetStreamInfoEx)(ZMusic_MusicStream song, SoundStreamInfoEx *info);
|
||||
typedef zmusic_bool (*pfn_ChangeMusicSettingInt)(EIntConfigKey key, ZMusic_MusicStream song, int value, int* pRealValue);
|
||||
typedef zmusic_bool (*pfn_ChangeMusicSettingFloat)(EFloatConfigKey key, ZMusic_MusicStream song, float value, float* pRealValue);
|
||||
typedef zmusic_bool (*pfn_ChangeMusicSettingString)(EStringConfigKey key, ZMusic_MusicStream song, const char* value);
|
||||
|
@ -418,4 +432,4 @@ typedef const ZMusicMidiOutDevice *(*pfn_ZMusic_GetMidiDevices)(int *pAmount);
|
|||
|
||||
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -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
|
||||
|
@ -152,13 +149,14 @@ use_fast_math(zmusiclite)
|
|||
|
||||
# Although zmusic-obj puts the public include directory in our private include
|
||||
# list, we need to add it to the interface include directories for consumers.
|
||||
target_include_directories(zmusic INTERFACE $<INSTALL_INTERFACE:include>)
|
||||
target_include_directories(zmusiclite INTERFACE $<INSTALL_INTERFACE:include>)
|
||||
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(zmusiclite PRIVATE ZMUSIC_LITE=1)
|
||||
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>)
|
||||
|
||||
set_target_properties(zmusic zmusiclite
|
||||
PROPERTIES
|
||||
|
@ -168,37 +166,43 @@ PROPERTIES
|
|||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
)
|
||||
|
||||
install(TARGETS zmusic EXPORT ZMusicFullTargets
|
||||
PUBLIC_HEADER
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT devel
|
||||
LIBRARY
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
COMPONENT full
|
||||
NAMELINK_COMPONENT devel
|
||||
)
|
||||
if (VCPKG_TOOLCHAIN)
|
||||
x_vcpkg_install_local_dependencies(TARGETS zmusic zmusiclite DESTINATION ".")
|
||||
endif()
|
||||
|
||||
install(TARGETS zmusiclite EXPORT ZMusicLiteTargets
|
||||
PUBLIC_HEADER
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT devel
|
||||
LIBRARY
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
COMPONENT lite
|
||||
NAMELINK_COMPONENT devel
|
||||
)
|
||||
if(ZMUSIC_INSTALL)
|
||||
install(TARGETS zmusic EXPORT ZMusicFullTargets
|
||||
PUBLIC_HEADER
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT devel
|
||||
LIBRARY
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
COMPONENT full
|
||||
NAMELINK_COMPONENT devel
|
||||
)
|
||||
|
||||
install(EXPORT ZMusicFullTargets
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ZMusic"
|
||||
NAMESPACE ZMusic::
|
||||
COMPONENT devel
|
||||
)
|
||||
install(TARGETS zmusiclite EXPORT ZMusicLiteTargets
|
||||
PUBLIC_HEADER
|
||||
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||
COMPONENT devel
|
||||
LIBRARY
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}"
|
||||
COMPONENT lite
|
||||
NAMELINK_COMPONENT devel
|
||||
)
|
||||
|
||||
install(EXPORT ZMusicLiteTargets
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ZMusic"
|
||||
NAMESPACE ZMusic::
|
||||
COMPONENT devel
|
||||
)
|
||||
install(EXPORT ZMusicFullTargets
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ZMusic"
|
||||
NAMESPACE ZMusic::
|
||||
COMPONENT devel
|
||||
)
|
||||
|
||||
install(EXPORT ZMusicLiteTargets
|
||||
DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/ZMusic"
|
||||
NAMESPACE ZMusic::
|
||||
COMPONENT devel
|
||||
)
|
||||
endif()
|
||||
|
||||
if( MSVC )
|
||||
option( ZMUSIC_GENERATE_MAPFILE "Generate .map file for debugging." OFF )
|
||||
|
|
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
|
||||
|
||||
|
|
|
@ -105,13 +105,53 @@ short* dumb_decode_vorbis(int outlen, const void* oggstream, int sizebytes)
|
|||
}
|
||||
|
||||
decoder->getInfo(&srate, &chans, &type);
|
||||
if (chans != ChannelConfig_Mono || type != SampleType_Int16)
|
||||
if (chans != ChannelConfig_Mono)
|
||||
{
|
||||
delete decoder;
|
||||
return samples;
|
||||
}
|
||||
|
||||
decoder->read((char*)samples, outlen);
|
||||
if(type == SampleType_Int16)
|
||||
decoder->read((char*)samples, outlen);
|
||||
else if(type == SampleType_Float32)
|
||||
{
|
||||
constexpr size_t tempsize = 1024;
|
||||
float temp[tempsize];
|
||||
size_t spos = 0;
|
||||
|
||||
outlen /= sizeof(short);
|
||||
int done = 0;
|
||||
while(done < outlen)
|
||||
{
|
||||
size_t got = decoder->read((char*)temp, tempsize * sizeof(float)) / sizeof(float);
|
||||
for(size_t i = 0;i < got;++i)
|
||||
{
|
||||
float s = temp[i] * 32768.0f;
|
||||
samples[spos++] = (s > 32767.0f) ? 32767 : (s < -32768.0f) ? -32768 : (short)s;
|
||||
}
|
||||
if(got < tempsize)
|
||||
break;
|
||||
done += got;
|
||||
}
|
||||
}
|
||||
else if(type == SampleType_UInt8)
|
||||
{
|
||||
constexpr size_t tempsize = 1024;
|
||||
uint8_t temp[tempsize];
|
||||
size_t spos = 0;
|
||||
|
||||
outlen /= sizeof(short);
|
||||
int done = 0;
|
||||
while(done < outlen)
|
||||
{
|
||||
size_t got = decoder->read((char*)temp, tempsize);
|
||||
for(size_t i = 0;i < got;++i)
|
||||
samples[spos++] = (short)((temp[i]-128) * 256);
|
||||
if(got < tempsize)
|
||||
break;
|
||||
done += got;
|
||||
}
|
||||
}
|
||||
delete decoder;
|
||||
return samples;
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
virtual std::string GetStats();
|
||||
virtual int GetDeviceType() const { return MDEV_DEFAULT; }
|
||||
virtual bool CanHandleSysex() const { return true; }
|
||||
virtual SoundStreamInfo GetStreamInfo() const;
|
||||
virtual SoundStreamInfoEx GetStreamInfoEx() const;
|
||||
|
||||
protected:
|
||||
MidiCallback Callback;
|
||||
|
@ -81,7 +81,7 @@ public:
|
|||
virtual int Open() override;
|
||||
virtual bool ServiceStream(void* buff, int numbytes);
|
||||
int GetSampleRate() const { return SampleRate; }
|
||||
SoundStreamInfo GetStreamInfo() const override;
|
||||
SoundStreamInfoEx GetStreamInfoEx() const override;
|
||||
|
||||
protected:
|
||||
double Tempo;
|
||||
|
@ -117,6 +117,7 @@ public:
|
|||
int Resume() override;
|
||||
int Open() override
|
||||
{
|
||||
playDevice->SetCallback(Callback, CallbackData);
|
||||
return playDevice->Open();
|
||||
}
|
||||
int OpenRenderer() override { return playDevice->OpenRenderer(); }
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
|
|
@ -50,7 +50,6 @@ namespace {
|
|||
|
||||
enum class EventType {
|
||||
Null,
|
||||
Delay,
|
||||
Action
|
||||
};
|
||||
|
||||
|
@ -160,7 +159,7 @@ int AlsaMIDIDevice::Open()
|
|||
snd_seq_port_info_set_port(pinfo, IntendedPortId);
|
||||
snd_seq_port_info_set_port_specified(pinfo, 1);
|
||||
|
||||
snd_seq_port_info_set_name(pinfo, "GZDoom Music");
|
||||
snd_seq_port_info_set_name(pinfo, "ZMusic Program Music");
|
||||
|
||||
snd_seq_port_info_set_capability(pinfo, 0);
|
||||
snd_seq_port_info_set_type(pinfo, SND_SEQ_PORT_TYPE_MIDI_GENERIC | SND_SEQ_PORT_TYPE_APPLICATION);
|
||||
|
@ -172,7 +171,7 @@ int AlsaMIDIDevice::Open()
|
|||
|
||||
if (QueueId < 0)
|
||||
{
|
||||
QueueId = snd_seq_alloc_named_queue(sequencer.handle, "GZDoom Queue");
|
||||
QueueId = snd_seq_alloc_named_queue(sequencer.handle, "ZMusic Program Queue");
|
||||
}
|
||||
|
||||
if (!Connected) {
|
||||
|
@ -290,8 +289,8 @@ EventType AlsaMIDIDevice::PullEvent(EventState & state) {
|
|||
return EventType::Action;
|
||||
|
||||
case MIDI_POLYPRESS:
|
||||
// FIXME: Seems to be missing in the Alsa sequencer implementation
|
||||
break;
|
||||
snd_seq_ev_set_keypress(&state.data, channel, parm1, parm2);
|
||||
return EventType::Action;
|
||||
|
||||
case MIDI_CTRLCHANGE:
|
||||
snd_seq_ev_set_controller(&state.data, channel, parm1, parm2);
|
||||
|
@ -315,8 +314,10 @@ EventType AlsaMIDIDevice::PullEvent(EventState & state) {
|
|||
break;
|
||||
}
|
||||
}
|
||||
// We didn't really recognize the event, treat it as a delay
|
||||
return EventType::Delay;
|
||||
// We didn't really recognize the event, treat it as a NOP
|
||||
state.data.type = SND_SEQ_EVENT_NONE;
|
||||
snd_seq_ev_set_fixed(&state.data);
|
||||
return EventType::Action;
|
||||
}
|
||||
|
||||
void AlsaMIDIDevice::SetExit(bool exit) {
|
||||
|
@ -374,13 +375,6 @@ void AlsaMIDIDevice::PumpEvents() {
|
|||
continue;
|
||||
}
|
||||
|
||||
// chomp delays as they come...
|
||||
if(type == EventType::Delay) {
|
||||
buffer_ticks += event.ticks;
|
||||
Position += event.size_of;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Figure out if we should sleep (the event is too far in the future for us to care), and for how long
|
||||
int next_event_tick = buffer_ticks + event.ticks;
|
||||
int queue_tick = snd_seq_queue_status_get_tick_time(status);
|
||||
|
@ -433,7 +427,6 @@ void AlsaMIDIDevice::PumpEvents() {
|
|||
snd_seq_drain_output(sequencer.handle);
|
||||
snd_seq_sync_output_queue(sequencer.handle);
|
||||
}
|
||||
snd_seq_sync_output_queue(sequencer.handle);
|
||||
snd_seq_stop_queue(sequencer.handle, QueueId, NULL);
|
||||
snd_seq_drain_output(sequencer.handle);
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ bool AlsaSequencer::Open() {
|
|||
if(error) {
|
||||
return false;
|
||||
}
|
||||
error = snd_seq_set_client_name(handle, "GZDoom");
|
||||
error = snd_seq_set_client_name(handle, "ZMusic Program");
|
||||
if(error) {
|
||||
snd_seq_close(handle);
|
||||
handle = nullptr;
|
||||
|
@ -131,11 +131,7 @@ int AlsaSequencer::EnumerateDevices() {
|
|||
while (snd_seq_query_next_client(handle, cinfo) >= 0) {
|
||||
snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
|
||||
|
||||
// Ignore 'ALSA oddities' that we don't want to use
|
||||
int clientID = snd_seq_client_info_get_client(cinfo);
|
||||
if(clientID < 16) {
|
||||
continue;
|
||||
}
|
||||
|
||||
snd_seq_port_info_set_port(pinfo, -1);
|
||||
// enumerate ports
|
||||
|
|
|
@ -172,11 +172,11 @@ std::string MIDIDevice::GetStats()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// MIDIDevice :: GetStreamInfo
|
||||
// MIDIDevice :: GetStreamInfoEx
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundStreamInfo MIDIDevice::GetStreamInfo() const
|
||||
SoundStreamInfoEx MIDIDevice::GetStreamInfoEx() const
|
||||
{
|
||||
return { 0, 0, 0 }; // i.e. do not use streaming.
|
||||
return {}; // i.e. do not use streaming.
|
||||
}
|
||||
|
|
|
@ -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,70 +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);
|
||||
void UnloadFluidSynth();
|
||||
#endif
|
||||
};
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#ifndef _M_X64
|
||||
#define FLUIDSYNTHLIB1 "fluidsynth.dll"
|
||||
#define FLUIDSYNTHLIB2 "libfluidsynth.dll"
|
||||
#else
|
||||
#define FLUIDSYNTHLIB1 "fluidsynth64.dll"
|
||||
#define FLUIDSYNTHLIB2 "libfluidsynth64.dll"
|
||||
#endif
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define FLUIDSYNTHLIB1 "libfluidsynth.1.dylib"
|
||||
#define FLUIDSYNTHLIB2 "libfluidsynth.2.dylib"
|
||||
#else // !__APPLE__
|
||||
#define FLUIDSYNTHLIB1 "libfluidsynth.so.1"
|
||||
#define FLUIDSYNTHLIB2 "libfluidsynth.so.2"
|
||||
#endif // __APPLE__
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// TYPES -------------------------------------------------------------------
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
@ -179,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)
|
||||
|
@ -225,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");
|
||||
|
@ -251,9 +168,6 @@ FluidSynthMIDIDevice::~FluidSynthMIDIDevice()
|
|||
{
|
||||
delete_fluid_settings(FluidSettings);
|
||||
}
|
||||
#ifdef DYN_FLUIDSYNTH
|
||||
UnloadFluidSynth();
|
||||
#endif
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -266,7 +180,8 @@ FluidSynthMIDIDevice::~FluidSynthMIDIDevice()
|
|||
|
||||
int FluidSynthMIDIDevice::OpenRenderer()
|
||||
{
|
||||
fluid_synth_system_reset(FluidSynth);
|
||||
// Send MIDI system reset command (big red 'panic' button), turns off notes, resets controllers and restores initial basic channel configuration.
|
||||
//fluid_synth_system_reset(FluidSynth);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -324,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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -492,85 +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)
|
||||
{
|
||||
if (fluid_lib && strlen(fluid_lib) > 0)
|
||||
{
|
||||
if(!FluidSynthModule.Load({fluid_lib}))
|
||||
{
|
||||
const char* libname = fluid_lib;
|
||||
ZMusic_Printf(ZMUSIC_MSG_ERROR, "Could not load %s\n", libname);
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
if(!FluidSynthModule.Load({FLUIDSYNTHLIB1, FLUIDSYNTHLIB2}))
|
||||
{
|
||||
ZMusic_Printf(ZMUSIC_MSG_ERROR, "Could not load " FLUIDSYNTHLIB1 " or " FLUIDSYNTHLIB2 "\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// FluidSynthMIDIDevice :: UnloadFluidSynth
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
void FluidSynthMIDIDevice::UnloadFluidSynth()
|
||||
{
|
||||
FluidSynthModule.Unload();
|
||||
}
|
||||
|
||||
#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"
|
||||
|
||||
|
|
|
@ -88,18 +88,19 @@ SoftSynthMIDIDevice::~SoftSynthMIDIDevice()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// SoftSynthMIDIDevice :: GwrStreamInfo
|
||||
// SoftSynthMIDIDevice :: GetStreamInfoEx
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundStreamInfo SoftSynthMIDIDevice::GetStreamInfo() const
|
||||
SoundStreamInfoEx SoftSynthMIDIDevice::GetStreamInfoEx() const
|
||||
{
|
||||
int chunksize = (SampleRate / StreamBlockSize) * 4;
|
||||
if (!isMono)
|
||||
{
|
||||
chunksize *= 2;
|
||||
}
|
||||
return { chunksize, SampleRate, isMono? 1:2 };
|
||||
return { chunksize, SampleRate, SampleType_Float32,
|
||||
isMono ? ChannelConfig_Mono : ChannelConfig_Stereo };
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include <stdlib.h>
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
@ -94,42 +95,44 @@ protected:
|
|||
|
||||
void TimidityMIDIDevice::LoadInstruments()
|
||||
{
|
||||
if (gusConfig.dmxgus.size())
|
||||
if (gusConfig.reader)
|
||||
{
|
||||
// Check if we got some GUS data before using it.
|
||||
std::string ultradir = getenv("ULTRADIR");
|
||||
if (ultradir.length() || gusConfig.gus_patchdir.length() != 0)
|
||||
std::string ultradir;
|
||||
const char *ret = getenv("ULTRADIR");
|
||||
if (ret) ultradir = std::string(ret);
|
||||
// The GUS put its patches in %ULTRADIR%/MIDI so we can try that
|
||||
if (ultradir.length())
|
||||
{
|
||||
auto psreader = new MusicIO::FileSystemSoundFontReader("");
|
||||
|
||||
// The GUS put its patches in %ULTRADIR%/MIDI so we can try that
|
||||
if (ultradir.length())
|
||||
{
|
||||
ultradir += "/midi";
|
||||
psreader->add_search_path(ultradir.c_str());
|
||||
}
|
||||
// Load DMXGUS lump and patches from gus_patchdir
|
||||
if (gusConfig.gus_patchdir.length() != 0) psreader->add_search_path(gusConfig.gus_patchdir.c_str());
|
||||
|
||||
gusConfig.instruments.reset(new Timidity::Instruments(psreader));
|
||||
bool success = gusConfig.instruments->LoadDMXGUS(gusConfig.gus_memsize, (const char*)gusConfig.dmxgus.data(), gusConfig.dmxgus.size()) >= 0;
|
||||
|
||||
gusConfig.dmxgus.clear();
|
||||
|
||||
if (success)
|
||||
{
|
||||
gusConfig.loadedConfig = "DMXGUS";
|
||||
return;
|
||||
}
|
||||
ultradir += "/midi";
|
||||
gusConfig.reader->add_search_path(ultradir.c_str());
|
||||
}
|
||||
gusConfig.loadedConfig = "";
|
||||
gusConfig.instruments.reset();
|
||||
throw std::runtime_error("Unable to initialize DMXGUS for GUS MIDI device");
|
||||
}
|
||||
else if (gusConfig.reader)
|
||||
{
|
||||
gusConfig.loadedConfig = gusConfig.readerName;
|
||||
// Load DMXGUS lump and patches from gus_patchdir
|
||||
if (gusConfig.gus_patchdir.length() != 0) gusConfig.reader->add_search_path(gusConfig.gus_patchdir.c_str());
|
||||
|
||||
gusConfig.instruments.reset(new Timidity::Instruments(gusConfig.reader));
|
||||
gusConfig.loadedConfig = gusConfig.readerName;
|
||||
}
|
||||
|
||||
if (gusConfig.instruments == nullptr)
|
||||
{
|
||||
throw std::runtime_error("No instruments set for GUS device");
|
||||
}
|
||||
|
||||
if (gusConfig.gus_dmxgus && gusConfig.dmxgus.size())
|
||||
{
|
||||
bool success = gusConfig.instruments->LoadDMXGUS(gusConfig.gus_memsize, (const char*)gusConfig.dmxgus.data(), gusConfig.dmxgus.size()) >= 0;
|
||||
gusConfig.reader = nullptr;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
gusConfig.instruments.reset();
|
||||
gusConfig.loadedConfig = "";
|
||||
throw std::runtime_error("Unable to initialize DMXGUS for GUS MIDI device");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool err = gusConfig.instruments->LoadConfig() < 0;
|
||||
gusConfig.reader = nullptr;
|
||||
|
||||
|
@ -140,10 +143,6 @@ void TimidityMIDIDevice::LoadInstruments()
|
|||
throw std::runtime_error("Unable to initialize instruments for GUS MIDI device");
|
||||
}
|
||||
}
|
||||
else if (gusConfig.instruments == nullptr)
|
||||
{
|
||||
throw std::runtime_error("No instruments set for GUS device");
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -257,20 +256,11 @@ void TimidityMIDIDevice::ComputeOutput(float *buffer, int len)
|
|||
|
||||
bool GUS_SetupConfig(const char* args)
|
||||
{
|
||||
gusConfig.reader = nullptr;
|
||||
if ((gusConfig.gus_dmxgus && *args == 0) || !stricmp(args, "DMXGUS"))
|
||||
{
|
||||
if (stricmp(gusConfig.loadedConfig.c_str(), "DMXGUS") == 0) return false; // aleady loaded
|
||||
if (gusConfig.dmxgus.size() > 0)
|
||||
{
|
||||
gusConfig.readerName = "DMXGUS";
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (*args == 0) args = gusConfig.gus_config.c_str();
|
||||
if (stricmp(gusConfig.loadedConfig.c_str(), args) == 0) return false; // aleady loaded
|
||||
if (gusConfig.gus_dmxgus && *args == 0) args = "DMXGUS";
|
||||
//if (stricmp(gusConfig.loadedConfig.c_str(), args) == 0) return false; // aleady loaded
|
||||
|
||||
MusicIO::SoundFontReaderInterface* reader = MusicIO::ClientOpenSoundFont(args, SF_GUS | SF_SF2);
|
||||
MusicIO::SoundFontReaderInterface* reader = MusicIO::ClientOpenSoundFont(args, SF_GUS);
|
||||
if (!reader && MusicIO::fileExists(args))
|
||||
{
|
||||
auto f = MusicIO::utf8_fopen(args, "rb");
|
||||
|
@ -286,6 +276,11 @@ bool GUS_SetupConfig(const char* args)
|
|||
if (!reader) reader = new MusicIO::FileSystemSoundFontReader(args, true);
|
||||
}
|
||||
|
||||
if (!reader && gusConfig.gus_dmxgus)
|
||||
{
|
||||
reader = new MusicIO::FileSystemSoundFontReader(args, true);
|
||||
}
|
||||
|
||||
if (reader == nullptr)
|
||||
{
|
||||
char error[80];
|
||||
|
|
|
@ -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 ------------------------------------------------------------------
|
||||
|
@ -86,7 +87,7 @@ struct FmtChunk
|
|||
MIDIWaveWriter::MIDIWaveWriter(const char *filename, SoftSynthMIDIDevice *playdevice)
|
||||
: SoftSynthMIDIDevice(playdevice->GetSampleRate())
|
||||
{
|
||||
File = MusicIO::utf8_fopen(filename, "wt");
|
||||
File = MusicIO::utf8_fopen(filename, "wb");
|
||||
playDevice = playdevice;
|
||||
if (File != nullptr)
|
||||
{ // Write wave header
|
||||
|
@ -150,9 +151,9 @@ bool MIDIWaveWriter::CloseFile()
|
|||
if (4 == fwrite(&size, 1, 4, File))
|
||||
{
|
||||
size = LittleLong(uint32_t(pos - 12 - sizeof(FmtChunk) - 8));
|
||||
if (0 == fseek(File, 4 + sizeof(FmtChunk) + 4, SEEK_CUR))
|
||||
if (0 == fseek(File, 4 + sizeof(FmtChunk) + 8, SEEK_CUR))
|
||||
{
|
||||
if (4 == fwrite(&size, 1, 5, File))
|
||||
if (4 == fwrite(&size, 1, 4, File))
|
||||
{
|
||||
fclose(File);
|
||||
File = nullptr;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdexcept>
|
||||
#include "mididevice.h"
|
||||
#include "zmusic/zmusic_internal.h"
|
||||
|
||||
|
@ -87,15 +88,7 @@ void WildMIDIDevice::LoadInstruments()
|
|||
{
|
||||
wildMidiConfig.loadedConfig = wildMidiConfig.readerName;
|
||||
wildMidiConfig.instruments.reset(new WildMidi::Instruments(wildMidiConfig.reader, SampleRate));
|
||||
bool success = wildMidiConfig.instruments->LoadConfig(wildMidiConfig.readerName.c_str());
|
||||
wildMidiConfig.reader = nullptr;
|
||||
|
||||
if (!success)
|
||||
{
|
||||
wildMidiConfig.instruments.reset();
|
||||
wildMidiConfig.loadedConfig = "";
|
||||
throw std::runtime_error("Unable to initialize instruments for WildMidi device");
|
||||
}
|
||||
}
|
||||
else if (wildMidiConfig.instruments == nullptr)
|
||||
{
|
||||
|
@ -104,7 +97,9 @@ void WildMIDIDevice::LoadInstruments()
|
|||
instruments = wildMidiConfig.instruments;
|
||||
if (instruments->LoadConfig(nullptr) < 0)
|
||||
{
|
||||
throw std::runtime_error("Unable to load instruments set for WildMidi device");
|
||||
wildMidiConfig.instruments.reset();
|
||||
wildMidiConfig.loadedConfig = "";
|
||||
throw std::runtime_error("Unable to initialize instruments for WildMidi device");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -284,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -178,16 +178,29 @@ MIDISong2::MIDISong2 (const uint8_t* data, size_t len)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
enum
|
||||
{
|
||||
EMIDI_GeneralMIDI = 0,
|
||||
EMIDI_SoundCanvas = 1,
|
||||
EMIDI_AWE32 = 2,
|
||||
EMIDI_WaveBlaster = 3,
|
||||
EMIDI_SoundBlaster = 4,
|
||||
EMIDI_ProAudio = 5,
|
||||
EMIDI_SoundMan16 = 6,
|
||||
EMIDI_Adlib = 7,
|
||||
EMIDI_Soundscape = 8,
|
||||
EMIDI_Ultrasound = 9,
|
||||
};
|
||||
|
||||
void MIDISong2::CheckCaps(int tech)
|
||||
{
|
||||
DesignationMask = 0xFF0F;
|
||||
if (tech == MIDIDEV_FMSYNTH)
|
||||
{
|
||||
DesignationMask = 0x00F0;
|
||||
DesignationMask = 1 << EMIDI_Adlib;
|
||||
}
|
||||
else if (tech == MIDIDEV_MIDIPORT)
|
||||
else
|
||||
{
|
||||
DesignationMask = 0x0001;
|
||||
DesignationMask = 1 << EMIDI_GeneralMIDI;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -443,7 +456,12 @@ uint32_t *MIDISong2::SendCommand (uint32_t *events, TrackInfo *track, uint32_t d
|
|||
case 111: // EMIDI Track Exclusion - InitBeat only
|
||||
if (track->PlayedTime < (uint32_t)Division)
|
||||
{
|
||||
if (track->Designated && data2 <= 9)
|
||||
if (!track->Designated)
|
||||
{
|
||||
track->Designation = ~0;
|
||||
track->Designated = true;
|
||||
}
|
||||
if (data2 <= 9)
|
||||
{
|
||||
track->Designation &= ~(1 << data2);
|
||||
}
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
void Resume();
|
||||
void Stop();
|
||||
bool IsPlaying();
|
||||
SoundStreamInfoEx GetStreamInfoEx() const override { return {}; }
|
||||
bool IsValid() const { return m_Inited; }
|
||||
|
||||
protected:
|
||||
|
|
|
@ -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"
|
||||
|
@ -87,7 +88,7 @@ public:
|
|||
int ServiceEvent();
|
||||
void SetMIDISource(MIDISource* _source);
|
||||
bool ServiceStream(void* buff, int len) override;
|
||||
SoundStreamInfo GetStreamInfo() const override;
|
||||
SoundStreamInfoEx GetStreamInfoEx() const override;
|
||||
|
||||
int GetDeviceType() const override;
|
||||
|
||||
|
@ -446,10 +447,10 @@ bool MIDIStreamer::InitPlayback()
|
|||
}
|
||||
}
|
||||
|
||||
SoundStreamInfo MIDIStreamer::GetStreamInfo() const
|
||||
SoundStreamInfoEx MIDIStreamer::GetStreamInfoEx() const
|
||||
{
|
||||
if (MIDI) return MIDI->GetStreamInfo();
|
||||
else return { 0, 0, 0 };
|
||||
if (MIDI) return MIDI->GetStreamInfoEx();
|
||||
else return {};
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -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
|
||||
|
@ -1021,7 +1031,7 @@ DLL_EXPORT zmusic_bool ZMusic_MIDIDumpWave(ZMusic_MidiSource source, EMidiDevice
|
|||
{
|
||||
try
|
||||
{
|
||||
MIDIStreamer me(devtype, devarg);
|
||||
MIDIStreamer me(devtype, devarg ? devarg : "");
|
||||
me.SetMIDISource(source);
|
||||
me.DumpWave(outname, subsong, samplerate);
|
||||
return true;
|
||||
|
|
|
@ -54,7 +54,7 @@ public:
|
|||
void ChangeSettingNum(const char *name, double value) override { if (m_Source) m_Source->ChangeSettingNum(name, value); }
|
||||
void ChangeSettingString(const char *name, const char *value) override { if(m_Source) m_Source->ChangeSettingString(name, value); }
|
||||
bool ServiceStream(void* buff, int len) override;
|
||||
SoundStreamInfo GetStreamInfo() const override { return m_Source->GetFormat(); }
|
||||
SoundStreamInfoEx GetStreamInfoEx() const override { return m_Source->GetFormatEx(); }
|
||||
|
||||
|
||||
protected:
|
||||
|
|
|
@ -64,7 +64,7 @@ public:
|
|||
//bool SetPosition(int ms);
|
||||
bool SetSubsong(int subsong) override;
|
||||
bool Start() override;
|
||||
SoundStreamInfo GetFormat() override;
|
||||
SoundStreamInfoEx GetFormatEx() override;
|
||||
void ChangeSettingNum(const char* setting, double val) override;
|
||||
std::string GetStats() override;
|
||||
|
||||
|
@ -885,6 +885,18 @@ StreamSource* MOD_OpenSong(MusicIO::FileInterface *reader, int samplerate)
|
|||
duh = dumb_read_okt_quick(f);
|
||||
}
|
||||
}
|
||||
else if (size >= 4 &&
|
||||
(dstart[0] == MAKE_ID('A','M','F','\xa') ||
|
||||
dstart[0] == MAKE_ID('A','M','F','\xb') ||
|
||||
dstart[0] == MAKE_ID('A','M','F','\xc') ||
|
||||
dstart[0] == MAKE_ID('A','M','F','\xd') ||
|
||||
dstart[0] == MAKE_ID('A','M','F','\xe')))
|
||||
{
|
||||
if ((f = dumb_read_allfile(&filestate, start, reader, headsize, size)))
|
||||
{
|
||||
duh = dumb_read_amf_quick(f);
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! duh )
|
||||
{
|
||||
|
@ -1004,7 +1016,7 @@ DumbSong::DumbSong(DUH* myduh, int samplerate)
|
|||
written = 0;
|
||||
length = 0;
|
||||
start_order = 0;
|
||||
MasterVolume = (float)dumbConfig.mod_dumb_mastervolume;
|
||||
MasterVolume = (float)dumbConfig.mod_dumb_mastervolume * 4;
|
||||
if (dumbConfig.mod_samplerate != 0)
|
||||
{
|
||||
srate = dumbConfig.mod_samplerate;
|
||||
|
@ -1030,13 +1042,13 @@ DumbSong::~DumbSong()
|
|||
|
||||
//==========================================================================
|
||||
//
|
||||
// DumbSong GetFormat
|
||||
// DumbSong GetFormatEx
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundStreamInfo DumbSong::GetFormat()
|
||||
SoundStreamInfoEx DumbSong::GetFormatEx()
|
||||
{
|
||||
return { 32*1024, srate, 2 };
|
||||
return { 32*1024, srate, SampleType_Float32, ChannelConfig_Stereo };
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -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 ------------------------------------------------------------------
|
||||
|
@ -57,7 +59,7 @@ public:
|
|||
void ChangeSettingNum(const char *name, double val) override;
|
||||
std::string GetStats() override;
|
||||
bool GetData(void *buffer, size_t len) override;
|
||||
SoundStreamInfo GetFormat() override;
|
||||
SoundStreamInfoEx GetFormatEx() override;
|
||||
|
||||
protected:
|
||||
Music_Emu *Emu;
|
||||
|
@ -167,9 +169,9 @@ GMESong::GMESong(Music_Emu *emu, int sample_rate)
|
|||
}
|
||||
|
||||
|
||||
SoundStreamInfo GMESong::GetFormat()
|
||||
SoundStreamInfoEx GMESong::GetFormatEx()
|
||||
{
|
||||
return { 32*1024, SampleRate, -2 };
|
||||
return { 32*1024, SampleRate, SampleType_Int16, ChannelConfig_Stereo };
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -50,14 +50,13 @@ public:
|
|||
SndFileSong(SoundDecoder *decoder, uint32_t loop_start, uint32_t loop_end, bool startass, bool endass);
|
||||
~SndFileSong();
|
||||
std::string GetStats() override;
|
||||
SoundStreamInfo GetFormat() override;
|
||||
SoundStreamInfoEx GetFormatEx() override;
|
||||
bool GetData(void *buffer, size_t len) override;
|
||||
|
||||
protected:
|
||||
SoundDecoder *Decoder;
|
||||
int Channels;
|
||||
int SampleRate;
|
||||
|
||||
unsigned int FrameSize;
|
||||
|
||||
uint32_t Loop_Start;
|
||||
uint32_t Loop_End;
|
||||
|
||||
|
@ -434,25 +433,30 @@ static int32_t Scale(int32_t a, int32_t b, int32_t c)
|
|||
|
||||
SndFileSong::SndFileSong(SoundDecoder *decoder, uint32_t loop_start, uint32_t loop_end, bool startass, bool endass)
|
||||
{
|
||||
ChannelConfig iChannels;
|
||||
SampleType Type;
|
||||
|
||||
decoder->getInfo(&SampleRate, &iChannels, &Type);
|
||||
ChannelConfig chanconf;
|
||||
SampleType stype;
|
||||
int srate;
|
||||
|
||||
if (!startass) loop_start = Scale(loop_start, SampleRate, 1000);
|
||||
if (!endass) loop_end = Scale(loop_end, SampleRate, 1000);
|
||||
decoder->getInfo(&srate, &chanconf, &stype);
|
||||
|
||||
if (!startass) loop_start = Scale(loop_start, srate, 1000);
|
||||
if (!endass) loop_end = Scale(loop_end, srate, 1000);
|
||||
|
||||
const uint32_t sampleLength = (uint32_t)decoder->getSampleLength();
|
||||
Loop_Start = loop_start;
|
||||
Loop_End = sampleLength == 0 ? loop_end : std::min<uint32_t>(loop_end, sampleLength);
|
||||
Decoder = decoder;
|
||||
Channels = iChannels == ChannelConfig_Stereo? 2:1;
|
||||
FrameSize = ZMusic_ChannelCount(chanconf) * ZMusic_SampleTypeSize(stype);
|
||||
}
|
||||
|
||||
SoundStreamInfo SndFileSong::GetFormat()
|
||||
SoundStreamInfoEx SndFileSong::GetFormatEx()
|
||||
{
|
||||
// deal with this once the configuration is handled better.
|
||||
return { 64/*snd_streambuffersize*/ * 1024, SampleRate, -Channels };
|
||||
ChannelConfig chanconf;
|
||||
SampleType stype;
|
||||
int srate;
|
||||
|
||||
Decoder->getInfo(&srate, &chanconf, &stype);
|
||||
return { 64/*snd_streambuffersize*/ * 1024, srate, stype, chanconf };
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -479,14 +483,17 @@ std::string SndFileSong::GetStats()
|
|||
{
|
||||
char out[80];
|
||||
|
||||
size_t SamplePos;
|
||||
ChannelConfig chanconf;
|
||||
SampleType stype;
|
||||
int srate;
|
||||
Decoder->getInfo(&srate, &chanconf, &stype);
|
||||
|
||||
SamplePos = Decoder->getSampleOffset();
|
||||
int time = int (SamplePos / SampleRate);
|
||||
size_t SamplePos = Decoder->getSampleOffset();
|
||||
int time = int (SamplePos / srate);
|
||||
|
||||
snprintf(out, 80,
|
||||
"Track: %s, %dHz Time: %02d:%02d",
|
||||
Channels == 2? "Stereo" : "Mono", SampleRate,
|
||||
ZMusic_ChannelConfigName(chanconf), srate,
|
||||
time/60,
|
||||
time % 60);
|
||||
return out;
|
||||
|
@ -503,7 +510,7 @@ bool SndFileSong::GetData(void *vbuff, size_t len)
|
|||
char *buff = (char*)vbuff;
|
||||
|
||||
size_t currentpos = Decoder->getSampleOffset();
|
||||
size_t framestoread = len / (Channels*2);
|
||||
size_t framestoread = len / FrameSize;
|
||||
bool err = false;
|
||||
if (!m_Looping)
|
||||
{
|
||||
|
@ -515,7 +522,7 @@ bool SndFileSong::GetData(void *vbuff, size_t len)
|
|||
}
|
||||
if (currentpos + framestoread > maxpos)
|
||||
{
|
||||
size_t got = Decoder->read(buff, (maxpos - currentpos) * Channels * 2);
|
||||
size_t got = Decoder->read(buff, (maxpos - currentpos) * FrameSize);
|
||||
memset(buff + got, 0, len - got);
|
||||
}
|
||||
else
|
||||
|
@ -532,7 +539,7 @@ bool SndFileSong::GetData(void *vbuff, size_t len)
|
|||
// Loop can be very short, make sure the current position doesn't exceed it
|
||||
if (currentpos < Loop_End)
|
||||
{
|
||||
size_t endblock = (Loop_End - currentpos) * Channels * 2;
|
||||
size_t endblock = (Loop_End - currentpos) * FrameSize;
|
||||
size_t endlen = Decoder->read(buff, endblock);
|
||||
|
||||
// Even if zero bytes was read give it a chance to start from the beginning
|
||||
|
|
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"
|
||||
|
@ -54,7 +56,7 @@ public:
|
|||
~OPLMUSSong ();
|
||||
bool Start() override;
|
||||
void ChangeSettingInt(const char *name, int value) override;
|
||||
SoundStreamInfo GetFormat() override;
|
||||
SoundStreamInfoEx GetFormatEx() override;
|
||||
|
||||
protected:
|
||||
bool GetData(void *buffer, size_t len) override;
|
||||
|
@ -93,10 +95,11 @@ OPLMUSSong::OPLMUSSong(MusicIO::FileInterface* reader, OPLConfig* config)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
SoundStreamInfo OPLMUSSong::GetFormat()
|
||||
SoundStreamInfoEx OPLMUSSong::GetFormatEx()
|
||||
{
|
||||
int samples = int(OPL_SAMPLE_RATE / 14);
|
||||
return { samples * 4, int(OPL_SAMPLE_RATE), current_opl_core == 0? 1:2 };
|
||||
return { samples * 4, int(OPL_SAMPLE_RATE), SampleType_Float32,
|
||||
current_opl_core == 0? ChannelConfig_Mono:ChannelConfig_Stereo };
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -235,7 +235,7 @@ class XASong : public StreamSource
|
|||
{
|
||||
public:
|
||||
XASong(MusicIO::FileInterface *readr);
|
||||
SoundStreamInfo GetFormat() override;
|
||||
SoundStreamInfoEx GetFormatEx() override;
|
||||
bool Start() override;
|
||||
bool GetData(void *buffer, size_t len) override;
|
||||
|
||||
|
@ -260,10 +260,10 @@ XASong::XASong(MusicIO::FileInterface * reader)
|
|||
getNextXABlock(&xad, false);
|
||||
}
|
||||
|
||||
SoundStreamInfo XASong::GetFormat()
|
||||
SoundStreamInfoEx XASong::GetFormatEx()
|
||||
{
|
||||
auto SampleRate = xad.blockIs18K? 18900 : 37800;
|
||||
return { 64*1024, SampleRate, 2};
|
||||
return { 64*1024, SampleRate, SampleType_Float32, ChannelConfig_Stereo };
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -21,7 +21,7 @@ public:
|
|||
virtual bool SetPosition(unsigned position) { return false; }
|
||||
virtual bool SetSubsong(int subsong) { return false; }
|
||||
virtual bool GetData(void *buffer, size_t len) = 0;
|
||||
virtual SoundStreamInfo GetFormat() { return {65536, m_OutputRate, 2 }; } // Default format is: System's output sample rate, 32 bit float, stereo
|
||||
virtual SoundStreamInfoEx GetFormatEx() = 0;
|
||||
virtual std::string GetStats() { return ""; }
|
||||
virtual void ChangeSettingInt(const char *name, int value) { }
|
||||
virtual void ChangeSettingNum(const char *name, double value) { }
|
||||
|
@ -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
|
||||
|
@ -503,7 +503,7 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingInt(EIntConfigKey key, MusInfo *currSon
|
|||
|
||||
case zmusic_gus_memsize:
|
||||
ChangeAndReturn(gusConfig.gus_memsize, value, pRealValue);
|
||||
return devType() == MDEV_GUS && gusConfig.gus_dmxgus;
|
||||
return devType() == MDEV_GUS;
|
||||
#endif
|
||||
#ifdef HAVE_TIMIDITY
|
||||
case zmusic_timidity_modulation_wheel:
|
||||
|
@ -518,15 +518,15 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingInt(EIntConfigKey key, MusInfo *currSon
|
|||
|
||||
case zmusic_timidity_reverb:
|
||||
if (value < 0 || value > 4) value = 0;
|
||||
else TimidityPlus_SetReverb();
|
||||
local_timidity_reverb = value;
|
||||
TimidityPlus_SetReverb();
|
||||
if (pRealValue) *pRealValue = value;
|
||||
return false;
|
||||
|
||||
case zmusic_timidity_reverb_level:
|
||||
if (value < 0 || value > 127) value = 0;
|
||||
else TimidityPlus_SetReverb();
|
||||
local_timidity_reverb_level = value;
|
||||
TimidityPlus_SetReverb();
|
||||
if (pRealValue) *pRealValue = value;
|
||||
return false;
|
||||
|
||||
|
@ -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);
|
||||
|
@ -856,7 +860,7 @@ DLL_EXPORT zmusic_bool ChangeMusicSettingString(EStringConfigKey key, MusInfo* c
|
|||
#ifdef HAVE_WILDMIDI
|
||||
case zmusic_wildmidi_config:
|
||||
wildMidiConfig.config = value;
|
||||
return devType() == MDEV_TIMIDITY;
|
||||
return devType() == MDEV_WILDMIDI;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
|
@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -320,7 +324,7 @@ public:
|
|||
std::string fullname;
|
||||
if (!fn)
|
||||
{
|
||||
f = utf8_fopen(mBaseFile.c_str(), "rt");
|
||||
f = utf8_fopen(mBaseFile.c_str(), "rb");
|
||||
fullname = mBaseFile;
|
||||
}
|
||||
else
|
||||
|
@ -330,11 +334,11 @@ public:
|
|||
for(int i = (int)mPaths.size()-1; i>=0; i--)
|
||||
{
|
||||
fullname = mPaths[i] + fn;
|
||||
f = utf8_fopen(fullname.c_str(), "rt");
|
||||
break;
|
||||
f = utf8_fopen(fullname.c_str(), "rb");
|
||||
if (f) break;
|
||||
}
|
||||
}
|
||||
if (!f) f = fopen(fn, "rt");
|
||||
if (!f) f = fopen(fn, "rb");
|
||||
}
|
||||
if (!f) return nullptr;
|
||||
auto tf = new StdioFileReader;
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -31,7 +31,7 @@ public:
|
|||
virtual void ChangeSettingNum(const char* setting, double value) {} // "
|
||||
virtual void ChangeSettingString(const char* setting, const char* value) {} // "
|
||||
virtual bool ServiceStream(void *buff, int len) { return false; }
|
||||
virtual SoundStreamInfo GetStreamInfo() const { return { 0,0,0 }; }
|
||||
virtual SoundStreamInfoEx GetStreamInfoEx() const = 0;
|
||||
|
||||
enum EState
|
||||
{
|
||||
|
|
|
@ -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.
|
||||
|
@ -440,6 +458,12 @@ DLL_EXPORT zmusic_bool ZMusic_IsLooping(MusInfo *song)
|
|||
return song->m_Looping;
|
||||
}
|
||||
|
||||
DLL_EXPORT int ZMusic_GetDeviceType(MusInfo* song)
|
||||
{
|
||||
if (!song) return false;
|
||||
return song->GetDeviceType();
|
||||
}
|
||||
|
||||
DLL_EXPORT zmusic_bool ZMusic_IsMIDI(MusInfo *song)
|
||||
{
|
||||
if (!song) return false;
|
||||
|
@ -447,11 +471,34 @@ DLL_EXPORT zmusic_bool ZMusic_IsMIDI(MusInfo *song)
|
|||
}
|
||||
|
||||
DLL_EXPORT void ZMusic_GetStreamInfo(MusInfo *song, SoundStreamInfo *fmt)
|
||||
{
|
||||
if (!fmt) return;
|
||||
*fmt = {};
|
||||
|
||||
if (!song)
|
||||
return;
|
||||
|
||||
SoundStreamInfoEx fmtex;
|
||||
{
|
||||
std::lock_guard<FCriticalSection> lock(song->CritSec);
|
||||
fmtex = song->GetStreamInfoEx();
|
||||
}
|
||||
if (fmtex.mSampleRate > 0)
|
||||
{
|
||||
fmt->mBufferSize = fmtex.mBufferSize;
|
||||
fmt->mSampleRate = fmtex.mSampleRate;
|
||||
fmt->mNumChannels = ZMusic_ChannelCount(fmtex.mChannelConfig);
|
||||
if (fmtex.mSampleType == SampleType_Int16)
|
||||
fmt->mNumChannels *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
DLL_EXPORT void ZMusic_GetStreamInfoEx(MusInfo *song, SoundStreamInfoEx *fmt)
|
||||
{
|
||||
if (!fmt) return;
|
||||
if (!song) *fmt = {};
|
||||
std::lock_guard<FCriticalSection> lock(song->CritSec);
|
||||
*fmt = song->GetStreamInfo();
|
||||
*fmt = song->GetStreamInfoEx();
|
||||
}
|
||||
|
||||
DLL_EXPORT void ZMusic_Close(MusInfo *song)
|
||||
|
@ -497,6 +544,6 @@ DLL_EXPORT zmusic_bool ZMusic_WriteSMF(MIDISource* source, const char *fn, int l
|
|||
auto f = MusicIO::utf8_fopen(fn, "wt");
|
||||
if (f == nullptr) return false;
|
||||
success = (fwrite(&midi[0], 1, midi.size(), f) == midi.size());
|
||||
delete f;
|
||||
fclose(f);
|
||||
return success;
|
||||
}
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
#pragma once
|
||||
#define ZMUSIC_INTERNAL
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#if defined(_MSC_VER) && !defined(ZMUSIC_STATIC)
|
||||
#define DLL_EXPORT __declspec(dllexport)
|
||||
#define DLL_IMPORT __declspec(dllexport) // without this the compiler complains.
|
||||
#else // !_MSC_VER
|
||||
#else
|
||||
#define DLL_EXPORT
|
||||
#define DLL_IMPORT
|
||||
#endif // _MSC_VER
|
||||
#endif
|
||||
|
||||
typedef class MIDISource *ZMusic_MidiSource;
|
||||
typedef class MusInfo *ZMusic_MusicStream;
|
||||
|
@ -49,3 +49,34 @@ struct CustomFileReader : public MusicIO::FileInterface
|
|||
|
||||
|
||||
void ZMusic_Printf(int type, const char* msg, ...);
|
||||
|
||||
inline uint8_t ZMusic_SampleTypeSize(SampleType stype)
|
||||
{
|
||||
switch(stype)
|
||||
{
|
||||
case SampleType_UInt8: return sizeof(uint8_t);
|
||||
case SampleType_Int16: return sizeof(int16_t);
|
||||
case SampleType_Float32: return sizeof(float);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline uint8_t ZMusic_ChannelCount(ChannelConfig chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
case ChannelConfig_Mono: return 1;
|
||||
case ChannelConfig_Stereo: return 2;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
inline const char *ZMusic_ChannelConfigName(ChannelConfig chans)
|
||||
{
|
||||
switch(chans)
|
||||
{
|
||||
case ChannelConfig_Mono: return "Mono";
|
||||
case ChannelConfig_Stereo: return "Stereo";
|
||||
}
|
||||
return "(unknown)";
|
||||
}
|
||||
|
|
22
thirdparty/CMakeLists.txt
vendored
22
thirdparty/CMakeLists.txt
vendored
|
@ -1,20 +1,4 @@
|
|||
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()
|
||||
|
||||
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
|
||||
|
@ -31,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()
|
||||
|
@ -43,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
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue